[BUG] Inline !`cmd` preprocessor executes example commands inside fenced markdown code blocks (repro: /plugin-dev:command-development runs npm test)
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet (open issues; see "Prior reports" below for closed ones)
- [x] This is a single bug report
- [x] I am using the latest version of Claude Code
What's Wrong?
The inline-bash preprocessor that expands ` !cmd patterns in slash commands and skills does not respect markdown fencing. It scans the whole skill body, including fenced code blocks, and executes anything that matches. That means a skill whose job is to *document* the !cmd ` syntax has its documentation examples executed for real in the user's current working directory.
This is reproducible today with the first-party plugin-dev plugin from the claude-plugins-official marketplace. Invoking /plugin-dev:command-development in a project with no package.json runs npm test and surfaces a shell error, because the skill's SKILL.md contains an example command file inside a fenced ```markdown block.
The offending content is at skills/command-development/SKILL.md line 492, inside a fenced block that opens at line 484:
~~~
Testing Pattern
---
description: Run tests for specific file
argument-hint: [test-file]
allowed-tools: Bash(npm:*)
---
Run tests: !`npm test $1`
Analyze results and suggest fixes for failures.
~~~
The same example also appears at skills/command-development/examples/simple-commands.md line 100.
I want to be clear that I do not think the plugin content is wrong. The example is correctly fenced, which is exactly what a documentation author should do. The bug is that fencing does not suppress expansion. That is why I am filing here rather than against the plugins repo. The plugin is just the most convenient first-party repro.
The impact is broader than the noisy error. Any skill or command that documents the ! syntax will have its example commands executed in the user's project. Here it happened to be harmless (npm test with ENOENT). A documentation example showing ` !git clean -fdx , !rm -rf ./build , or a deploy command would not be harmless. Sixteen !... patterns exist in this one SKILL.md alone, several of which reference ${CLAUDE_PLUGIN_ROOT}` scripts.
What Should Happen?
` !cmd ` patterns that appear inside a fenced code block (and, I would argue, inside inline code spans) should be treated as literal text and not executed.
Failing that, at minimum a shell failure originating from a documentation-only skill should not surface to the user as an Error:.
Two possible fixes:
- Make the preprocessor markdown-aware: skip
!expansion inside fenced code blocks and inline code spans. This is the fix that makes correct documentation behave correctly, and needs no change to any existing skill. - Provide an explicit escape syntax and update the plugin-dev skill docs to use it. This works but requires every skill author who documents the syntax to know about and apply the escape, and it leaves existing third-party skills broken.
Option 1 seems clearly preferable, since fencing is already the universal markdown convention for "this is a sample, not a directive".
Error Messages/Logs
Error: Shell command failed for pattern "!`npm test $1`": [stderr]
npm error code ENOENT
npm error syscall open
npm error path /home/<user>/<project>/package.json
npm error errno -2
npm error enoent Could not read package.json: Error: ENOENT: no such file or directory, open '/home/<user>/<project>/package.json'
npm error enoent This is related to npm not being able to find a file.
Steps to Reproduce
- Install the
plugin-devplugin from theclaude-plugins-officialmarketplace via/plugin. (I reproduced this on a freshly updated copy, followed by/reload-plugins.) cdinto any project that has nopackage.jsonat its root. A Python repo works fine. Any empty directory should also work.- Start
claudein that directory. - Run the slash command
/plugin-dev:command-development. - The error above appears on stderr.
npm testhas been executed against the current working directory even though the command lives inside a fenced ```markdown block in the skill body.
To confirm the source, grep -n '!' ~/.claude/plugins/marketplaces/claude-plugins-official/plugins/plugin-dev/skills/command-development/SKILL.md` lists 16 matches, all of which are inside fenced documentation examples.
I have only verified the plugin-dev path above. If you want a self-contained case, I would expect a local .claude/commands/demo.md containing a fenced ``markdown block whose body includes !echo EXECUTED to show the same thing when /demo` is run, but I have not confirmed that the local-command path and the plugin-skill path share the preprocessor.
Prior reports
This has been reported before and is still present in 2.1.234. Filing fresh per the auto-lock bot's instruction to open a new issue and reference the old one.
- #12781 "Skill loading executes inline bash patterns from documentation examples" (closed as not planned, locked). Same root cause, and it also cites this same
plugin-dev:command-developmentskill. - #39864 "feat: Skip dynamic context injection inside markdown code blocks in SKILL.md" (closed as a duplicate of #12781).
- #55574 "Skill loader parses markdown content as shell commands" (closed).
- #9643 "[FEATURE] Escape ! execution in slash commands" (closed as not planned). This is the option-2 fix above.
Claude Model
Not sure / Multiple models (the failure happens during command preprocessing, before the model is involved)
Is this a regression?
No, this never worked. #12781 dates to 2025-12-01 and describes identical behavior.
Claude Code Version
2.1.234 (Claude Code)
Platform
Anthropic API
Operating System
Other Linux
Terminal/Shell
Other
Additional Information
Plugin: plugin-dev from claude-plugins-official, authored by Anthropic. Installed at ~/.claude/plugins/marketplaces/claude-plugins-official/plugins/plugin-dev/. Updated and reloaded immediately before reproducing, so this is not a stale-cache artifact.
Affected files in that plugin, for reference:
skills/command-development/SKILL.md(16 patterns, notably line 492 `!npm test $1and line 525!gh pr view $1`)skills/command-development/examples/simple-commands.md(line 100)
Note that line 525 is a gh pr view example, which would fire a network call and a gh auth path in any repo where the command is invoked. That one illustrates the side-effect concern better than the npm case does.
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗