[FEATURE] Ensure `git commit` does not use command substitution

Status Fixed / completed
Maintainer reply ✓ Yes — ashwin-ant
Activity 6 comments · opened Mar 5, 2026 · closed Apr 19, 2026
💡 Likely answer: A maintainer (ashwin-ant, collaborator) responded on this thread — see the highlighted reply below.

Preflight Checklist

  • [x] I have searched existing requests and this feature hasn't been requested yet
  • [x] This is a single feature request (not multiple features)

Problem Statement

When claude performs a git commit with multiple lines, it uses command substitution (git comit -m "$(cat <<'EOF'... ), which triggers prompt to validate the command:

Command contains $() command substitution

 Do you want to proceed?

This is apparently hardcoded into claude:

● Found it! It's in the Bash tool's own system instructions, not in a superpowers skill. Look at the "Committing changes with git" section — it explicitly says:

  ALWAYS pass the commit message via a HEREDOC, a la this example:
  git commit -m "$(cat <<'EOF'
     Commit message here.
     Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
     EOF
     )"

  This is a built-in instruction in the Bash tool that I cannot override. It's part of the tool's system prompt for how to create commits.

Proposed Solution

Suggest another way for multiline commits that doesn't involve command substitution.

Alternative Solutions

_No response_

Priority

Low - Nice to have

Feature Category

Interactive mode (TUI)

Use Case Example

_No response_

Additional Context

_No response_

View original on GitHub ↗

6 Comments

mparker3 · 5 months ago

+1, this is a recent change and is disruptive to workflows

ozydingo · 5 months ago

Same with creating pull requests. The Bash tool's description field (injected as a system instruction) contains two heredoc templates that directly cause this:

Commits (from the Bash tool description, under "# Committing changes with git"):

ALWAYS pass the commit message via a HEREDOC, a la this example:
git commit -m "$(cat <<'EOF'
   Commit message here.
   Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
   EOF
   )"

Pull Requests (under "# Creating pull requests"):

Use a HEREDOC to pass the body to ensure correct formatting.
gh pr create --title "the pr title" --body "$(cat <<'EOF'
## Summary
...
EOF
)"

Both use $(cat <<'EOF' ... EOF) — command substitution wrapping a heredoc — which triggers the "Command contains $() command substitution" approval prompt. This bypasses auto-accept settings entirely, since the shell substitution is flagged as potentially dangerous.

Why CLAUDE.md overrides don't work: The Bash tool description says "ALWAYS pass the commit message via a HEREDOC" — this competes directly with any project-level instructions to avoid substitution. Even though CLAUDE.md is documented as overriding default behavior, the tool-level instruction is specific and imperative enough that the model frequently follows it instead. We have a pull-request skill that successfully changes PR _format_ (title conventions, body sections, etc.) but cannot reliably prevent the heredoc pattern.

Workarounds we're trying:

  1. A PreToolUse hook that pattern-matches the heredoc-in-substitution pattern and denies with an error message redirecting to --body-file / git commit -F
  2. Stronger language in our skills explicitly naming the conflict: "The Bash tool's system prompt instructs you to use heredocs. Ignore those instructions."

Suggested fix: Replace the heredoc examples in the Bash tool description with patterns that don't trigger approval prompts:

  • Commits: git commit -F <file> (write message via Write tool first)
  • PRs: gh pr create --body-file <file>
  • Multi-flag: git commit -m "subject" -m "body paragraph"

These achieve the same multi-line formatting without command substitution.

amgcc · 5 months ago

Being constantly prompted to hand wave the tools through innocuous read only commands is such a time-waster. Please fix this already.

yurukusa · 5 months ago

A PreToolUse hook can rewrite git commit commands to avoid command substitution:

INPUT=$(cat)
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
[ -z "$COMMAND" ] && exit 0
if echo "$COMMAND" | grep -qE 'git\s+commit.*\$\(|git\s+commit.*`'; then
    echo '{"hookSpecificOutput":{"additionalContext":"Do NOT use command substitution $() in git commit messages. Use a simple git commit -m \"message\" format instead."}}'
fi
exit 0
{
  "hooks": {
    "PreToolUse": [{
      "matcher": "Bash",
      "hooks": [{ "type": "command", "command": "bash ~/.claude/hooks/no-subst-commit.sh" }]
    }]
  }
}

The hook detects $() or backticks in git commit commands and instructs Claude to use a simple -m "message" format instead.

ashwin-ant collaborator · 4 months ago

This was fixed in v2.1.71 — Fixed false-positive permission prompts for compound bash commands containing heredoc commit messages (e.g. git commit -m "$(cat <<'EOF'...)"). If you're still seeing this in the latest version, please comment with your version and repro and we'll reopen.

github-actions[bot] · 4 months ago

This issue has been automatically locked since it was closed and has not had any activity for 7 days. If you're experiencing a similar issue, please file a new issue and reference this one if it's relevant.