diff --git a/agents/AGENTS.md b/agents/AGENTS.md index 6684104..9281881 100644 --- a/agents/AGENTS.md +++ b/agents/AGENTS.md @@ -61,6 +61,22 @@ Treat vague input and question-back responses critically, not as instructions. - `$TMPDIR` is set by the sandbox to a writable path. `.tmp/` inside the project directory is always writable without prompts. - Ensure `.tmp/` is listed in `.gitignore` when creating temp files in a tracked repo. +## Shell — literal `!` in Bash commands + +- **Never put a literal `!` in an inline Bash command.** Claude Code's Bash tool + escapes every `!` to `\!` at the transport layer before any shell sees it — + even inside single/double quotes and in non-interactive shells + (anthropics/claude-code#61121, a regression of a fix shipped in 2.1.87). The + stray backslash corrupts downstream tools: Python `!=` → SyntaxWarning + broken + string, jq, Jira JQL (`status != Done` → server 400), branch names, etc. + `bash -c '...'` and quoted heredocs do **not** avoid it. +- **One rule covers everything:** if a command needs a `!`, write the command/code + to a file with the Write tool under `.tmp/` and run the file. `.tmp/` is + prompt-free via the `Edit(.tmp/**)` allow rule in `~/.claude/settings.json`. Do + **not** create the file with inline `printf`/`echo >` — that re-escapes the `!`. +- Need a literal `!` inline anyway: ANSI-C hex `$'\x21'` (e.g. `B=$'\x21'; cmd + "${B}=…"`) yields a real `!` with no literal `!` in the command. + ## Tooling - **`ccc` for semantic code search.** Repos containing a