Conversation
…bodies The Claude Code Bash-tool `!`→`\!` rewrite no longer reproduces. Removed the workaround guidance across triage, review-reviewers, review-runs, running-in-ci, and notifications. Standardized PR/comment/gist body composition on the Write tool + --body-file. Kept the corruption-scan tripwires in review-reviewers so a regression is detectable. Co-Authored-By: Claude <noreply@anthropic.com>
tend-agent
reviewed
May 15, 2026
tend-agent
left a comment
Collaborator
There was a problem hiding this comment.
The premise — "the Bash-tool !→\! rewrite no longer reproduces" — does not hold in this CI environment. The preprocessor is still active, so the workarounds being removed are still load-bearing.
Repro from this very review run:
$ echo "hello!"
hello\!
$ echo '[{"status":"completed","id":1},{"status":"in_progress","id":2}]' \
| jq '.[] | select(.status != "completed") | .id'
jq: error: syntax error, unexpected INVALID_CHARACTER, expecting ';' or ')' (Unix shell quoting issues?) at <top-level>, line 1:
.[] | select(.status \!= "completed") | .id
jq: 1 compile error
$ cat << 'EOF'
> Thanks for reporting this!
> EOF
Thanks for reporting this\!
Concrete consequences if this lands:
- The new
select(.status != "completed")line inrunning-in-ci(the rerun-poll recipe) will fail withInvalid characterthe next timetend-ci-fixreruns failed jobs — exactly the failure mode the removed comment warned about. Inline suggestion below. - Bot greetings ending in
!, code references likeassert!()/format!()/panic!()/eprintln!(), and conventional-commits breaking-change titles likefeat(api)!:will start shipping as\!again. The corruption-scan tripwires kept inreview-reviewerswill catch the regression after the fact, but the per-skill author guidance that prevented the corruption upfront is gone. - Single-quoted heredoc bodies with
!in them will ship corrupted (last block above).
The good direction here — "compose bodies with the Write tool, post via --body-file" — does still avoid the corruption (verified: a Write-tool-authored file is bytes-perfect, no preprocessor in that path). So the broader simplification is sound; it's the assumption that bash heredocs and inline != are now safe that breaks.
Suggest one of:
- Hold this PR until the upstream fix is verified in the CI image tend-agent runs in (paste a
gh workflow runlink showingecho "hi!"printinghi!before merging), or - Keep the per-skill bang-trap callouts and the
||-not-if !reminders, and limit this PR to the genuinely-safe parts (the--body-filestandardization, the corruption-scan recipe simplification, the Write-tool-for-step-summary rewrite). Just revert the!=swap and the four "Use||notif !" / "Bash-tool preprocessor" deletions innotifications,review-runs,review-reviewers(the corruption-scan jq filter), andtriage.
Separately, two smaller observations on the cleanup direction itself (non-blocking):
- The new pseudo-code blocks in
review-reviewers(gist seed, step summary) embed instructions like# Use the Write tool to author …as bash comments inside a fenced bash block. It works, but reads ambiguously — a model could plausibly try to execute the block as bash and end up with an empty/tmp/gist-seed/findings.md. Prose between two real code blocks would be unambiguous. - The shortened
**GitHub URLs**paragraph drops the previous explicit guidance that the Write tool doesn't expand env vars (and theOWNER_REPOplaceholder +sed -irecipe). Without that, a body authored withhttps://github.com/${GITHUB_REPOSITORY}/issues/123ships the literal${GITHUB_REPOSITORY}, not the value. "Read from the environment" implies the right action but doesn't spell it out.
…ng bug Linux Claude Code v2.1.142's bwrap-wrapping path uses the legacy shell-quote quote() (/(["\\$`!])/g), which escapes ! to \! in any argv token containing both ' and whitespace. Disabling CLAUDE_CODE_SUBPROCESS_ENV_SCRUB routes bash through the fixed '\''-wrap path at the cost of subprocess env isolation. macOS uses sandbox-exec on an already-fixed path, so this is Linux-only. See anthropics/claude-code#35701. Co-Authored-By: Claude <noreply@anthropic.com>
# Conflicts: # plugins/tend-ci-runner/skills/running-in-ci/SKILL.md
tend-agent
approved these changes
May 15, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Bug
Linux Claude Code v2.1.142's bubblewrap-backed subprocess sandbox wraps bash commands using the legacy
shell-quotequote function with the regex/(["\\$!])/g, which escapes!to!in any argv token that mixes'with whitespace. That landed!=injqfilters,assert!()in code references,feat(api)!:in conventional-commit titles, etc. The same binary contains a **fixed**'''-wrap quoting path for the macOSsandbox-exec` route — both paths coexist, only the Linux-bwrap path still uses the buggy quoter. See anthropics/claude-code#35701 (closed as stale; multiple duplicates closed since).Fix
action.yaml: setCLAUDE_CODE_SUBPROCESS_ENV_SCRUB=0on theclaude-code-actioninvocation. This disables the bwrap sandbox and routes bash through the fixed'\''-wrap path. Trade-off: loses subprocess env isolation. Applied at the composite-action level, so allmax-sixty/tend@v1consumers pick it up automatically once tagged.Skills: with the bug worked around, the bang-trap guidance can go. Removed across
triage,notifications,review-runs,review-reviewers, andrunning-in-ci:!in comment body" / "use Write tool for bodies with!"!=rewrite warnings injqrecipes (and the awkward(.status == "completed") | notrephrase)--title-fileandgit commit -Fworkarounds||notif !rationale comments<<'EOF'/<<EOFinterpolation footgun warningBody composition: standardized on Write tool +
--body-filefor substantial PR/comment/gist bodies. Removed the inlinegh ... --body "$(cat <<'EOF' ...)"heredoc patterns fromreview-reviewers's gist seed and step summary and the line-wrap example inrunning-in-ci. Write-tool composition is reviewable, sandbox-independent, and bypasses the shell-quoting layer entirely.Kept on purpose
review-reviewers(grep -nP '\\!'andgrep -nP '\\\`'). If the workaround stops working — bug returns upstream, env var override, the sandbox surface changes — the scans catch it in the bot's own output.no-preprocessor-poison-in-skillspre-commit hook. Different bug (slash-command preprocessor crashes on literal!`in plugin skill.mdfiles, regressed twice per fix(review): unbreak /review slash command poisoned by\!\` sequence #234/fix(review): remove re-introduced \\!-backtick poison from skill comments #243/fix(review): re-unbreak /review slash command poisoned by PR #226 regression #244), unrelated to the Bash-tool rewrite.Validation posture
Workaround is empirically targeted: the bug reproduces in CI (bwrap sandbox active), does not reproduce locally (
sandbox-execon the fixed path), and the env-var docstring inside the binary explicitly documents the opt-out. If a regression slips,review-reviewers'sgrep -nP '\\!'/grep -nP '\\\`'scans against the bot's own output fire on the next run. Easy revert viagit revert <commit>if anything misbehaves.