Skip to content

Commit 32a5834

Browse files
authored
docs(skill-authoring): correct relative-path resolution guidance for bundled scripts (#938)
1 parent ba133a2 commit 32a5834

2 files changed

Lines changed: 16 additions & 4 deletions

File tree

AGENTS.md

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,19 @@ If two skills need the same supporting file, duplicate it into each skill's dire
166166

167167
This plugin is authored once and converted for multiple agent platforms (Claude Code, Codex, Gemini CLI, etc.). Do not use platform-specific environment variables or string substitutions (e.g., `${CLAUDE_PLUGIN_ROOT}`, `${CLAUDE_SKILL_DIR}`, `${CLAUDE_SESSION_ID}`, `CODEX_SANDBOX`, `CODEX_SESSION_ID`) in skill content without a graceful fallback that works when the variable is unavailable or unresolved.
168168

169-
**Preferred approach — relative paths:** Reference co-located scripts and files using relative paths from the skill directory (e.g., `bash scripts/my-script.sh ARG`). All major platforms resolve these relative to the skill's directory. No variable prefix needed.
169+
Whether a relative path resolves against the skill directory depends on *who* resolves it, so the two cases below must be handled differently. Do not assume a bare `scripts/…` path works in both.
170+
171+
**Read-time file references — resolve against the skill directory:** When skill *content* points the agent at a co-located file to read (e.g., "read `references/schema.yaml`"), use a relative path from the skill root. The skill loader resolves these against the skill's own directory on all major platforms — no variable prefix needed. This is the rule in *File References in Skills* above.
172+
173+
**Runtime script invocations via the Bash tool — resolve against the project CWD:** When skill content tells the agent to *execute* a bundled script through the Bash tool, a bare relative path does **not** work on Claude Code. The Bash tool's working directory is the user's project, not the skill directory, so `bash scripts/my-script.sh` resolves to `<project>/scripts/…`, finds nothing, and the step is silently skipped. This is a recurring bug class — see #764 (`ce-worktree`), #811 (`ce-code-review`), and #898 (`ce-compound`). Invoke the script through the skill directory with the `:-.` fallback instead:
174+
175+
```
176+
bash "${CLAUDE_SKILL_DIR:-.}/scripts/my-script.sh" ARG
177+
```
178+
179+
`${CLAUDE_SKILL_DIR}` is substituted into SKILL.md content by Claude Code, covering both marketplace-cached installs and `claude --plugin-dir` local dev; it resolves to the skill's own directory, so the invocation is correct there. Note `${CLAUDE_SKILL_DIR}` is a SKILL.md *content* substitution, not an environment variable available inside the executed process — a script that needs its own directory should derive it from `BASH_SOURCE` rather than reading `$CLAUDE_SKILL_DIR` (see `ce-update/scripts/`). The `ce-worktree` and `ce-update` skills are the canonical examples of this pattern.
180+
181+
**Caveat — this only fully resolves on Claude Code.** On other targets (Codex, Gemini CLI, etc.) `${CLAUDE_SKILL_DIR}` is unset, so `:-.` degrades the command to a project-CWD-relative `./scripts/…`. That keeps the command syntactically valid (no unexpanded `${…}` literal) and is no worse than a bare relative path, but it does **not** resolve to the bundled script: those runtimes also execute the shell from the user's project, while the script lives in their own skill store (e.g. `~/.codex/skills/<plugin>/<skill>/scripts/…`). So runtime invocation of a bundled script is currently *unsolved* on Codex/Gemini — the converter (`src/utils/codex-content.ts`) does not rewrite these paths, and in the default `--to codex` mode skills are not emitted by the converter at all (native plugin install owns them). Use `${CLAUDE_SKILL_DIR:-.}` because it is correct on Claude Code and harmless elsewhere — but do not gate a skill's core behavior on a runtime bundled-script call when portability to those targets matters. Prefer logic the agent can perform inline, or content the agent reads (read-time references resolve against the skill dir on all targets).
170182

171183
**When a platform variable is unavoidable:** Use the pre-resolution pattern (`!` backtick syntax) and include explicit fallback instructions in the skill content, so the agent knows what to do if the value is empty, literal, or an error:
172184

plugins/compound-engineering/AGENTS.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -207,9 +207,9 @@ Design rules for blocking question menus (`AskUserQuestion` / `request_user_inpu
207207

208208
### Script Path References in Skills
209209

210-
- [ ] In bash code blocks, reference co-located scripts using relative paths (e.g., `bash scripts/my-script ARG`) — not `${CLAUDE_PLUGIN_ROOT}` or other platform-specific variables
211-
- [ ] All platforms resolve script paths relative to the skill's directory; no env var prefix is needed
212-
- [ ] Reference the script with a backtick path (e.g., `` `scripts/my-script` ``) so agents can locate it; a markdown link is not needed since the bash code block already provides the invocation
210+
- [ ] In bash code blocks, invoke co-located scripts through `${CLAUDE_SKILL_DIR:-.}` (e.g., `bash "${CLAUDE_SKILL_DIR:-.}/scripts/my-script" ARG`) — not a bare relative path, and not `${CLAUDE_PLUGIN_ROOT}`. The runtime Bash tool runs from the user's project CWD, not the skill directory, so a bare `bash scripts/my-script` resolves against `<project>/scripts/` and fails — the recurring bug class behind #764, #811, and #898.
211+
- [ ] On Claude Code `${CLAUDE_SKILL_DIR}` resolves to the skill directory; on other targets it is unset and the `:-.` fallback only keeps the command syntactically valid — it does **not** resolve to the bundled script there, so runtime bundled-script invocation is currently unsolved on Codex/Gemini. Do not gate a skill's core behavior on a runtime bundled-script call when portability to those targets matters. See "Permission gate on extracted scripts" under *Tool Selection in Agents and Skills* below for the `allowed-tools` pinning that pairs with this.
212+
- [ ] Reference the script with a backtick *read-time* path (e.g., `` `scripts/my-script` ``) so agents can locate it to read it — read-time references do resolve against the skill directory on all platforms; a markdown link is not needed since the bash code block already provides the invocation
213213

214214
### Cross-Platform Reference Rules
215215

0 commit comments

Comments
 (0)