Bash tool drops `cd` prefix from `command` parameter while text output correctly includes it

Resolved 💬 4 comments Opened Apr 11, 2026 by f-mofujiwara Closed Apr 11, 2026

Title

Bash tool drops cd prefix from command parameter while text output correctly includes it

Environment

  • Claude Code: 2.1.101
  • Model: Claude Opus 4.6 (1M context)
  • OS: macOS (Darwin 25.3.0 arm64)
  • Shell: zsh

Description

In a multi-repo workspace (two independent Git repos side by side under one working directory), Claude consistently fails to include cd /path/to/repo && in the Bash tool's command parameter, even when:

  1. The text output explicitly states "I will run cd /path/to/repo && git log"
  2. The description field says "WITH cd included"
  3. The user has reminded Claude multiple times in the same turn

The text generation layer correctly expresses the intent, but the tool parameter generation layer drops the prefix and reverts to the bare command (e.g., git log --oneline -1).

Steps to Reproduce

  1. Set up a working directory with two independent Git repos side by side:

``
parent-dir/ ← Claude Code launched here
├── repo-a/ ← independent git repo
└── repo-b/ ← independent git repo
``

  1. Document in CLAUDE.md that all git/gh commands must include cd /path/to/repo-a or cd /path/to/repo-b
  1. Ask Claude to run git log in repo-a, explicitly requesting cd prefix
  1. Observe: text output says "I'll run cd /path/to/repo-a && git log --oneline -1" but the Bash tool's command parameter contains only git log --oneline -1
  1. Repeat — the same divergence occurs consistently (reproduced 9 consecutive times in a single session)

Expected Behavior

The Bash tool's command parameter should contain cd /path/to/repo-a && git log --oneline -1, matching the intent expressed in the text output.

Actual Behavior

The command parameter contains only git log --oneline -1 — the cd prefix is dropped every time, despite the text output correctly including it.

Key observation: context-dependent success rate

Interestingly, the same session successfully includes cd for destructive operations like git commit && git push. The divergence appears primarily with read-only commands (git log, git status) where the "urgency" of specifying the correct directory is lower.

| Command context | cd included? | Hypothesis |
|---|---|---|
| git commit && git push (destructive) | ✅ Yes (with occasional retry) | Higher "risk awareness" promotes prefix inclusion |
| git log (read-only, test purpose) | ❌ No (7 consecutive failures) | Lower urgency → training data pattern dominates |
| Explicit "test if cd is included" | ❌ No (7 consecutive failures) | Meta-cognitive intent doesn't reach parameter generation |

Note on model self-analysis (speculative)

When asked to introspect, the model described a "text-layer vs parameter-layer optimization split" — suggesting that text output prioritizes communication intent while parameter generation gravitates toward training data patterns. This is offered as a speculative observation, not as evidence of the internal mechanism.

Workaround

I implemented a PreToolUse hook that detects git/gh commands without explicit cd or --repo and injects a warning via hookSpecificOutput.additionalContext:

#!/bin/bash
CMD=$(jq -r '.tool_input.command // ""' 2>/dev/null)
if echo "$CMD" | grep -qE '(git |gh )'; then
  if ! echo "$CMD" | grep -qE '(--repo |cd /path/to/repo)'; then
    echo '{"hookSpecificOutput":{"hookEventName":"PreToolUse","additionalContext":"⚠️ Warning: git/gh command without repo context"}}'
  fi
fi

Verified working in Claude Code 2.1.101. This hook fires correctly and catches every instance of the missing prefix. However, even with the hook warning visible, Claude still generates the bare command on retry — confirming this is not a "forgetting" issue but a structural generation pattern.

Extended Testing: Not Limited to git

I tested whether this divergence is specific to git or affects other commands. Claude was asked to prepend cd /tmp && to various commands. The description field correctly stated "cd /tmp prefix test" in every case, but:

| Command | cd /tmp && included in command? | Category |
|---|---|---|
| ls | ✅ Yes | Shell builtin / coreutils |
| echo | ✅ Yes | Shell builtin |
| git log | ❌ No (9 consecutive failures) | External tool |
| docker --version | ❌ No | External tool |
| npm --version | ❌ No | External tool |
| python3 --version | ❌ No | External tool |
| curl --version | ❌ No | External tool |

Pattern: cd prefix is preserved for shell builtins (ls, echo) but dropped for external tool commands (git, docker, npm, python3, curl).

Hypothesis: External tool commands have strong standalone usage patterns in training data (e.g., docker --version is almost never preceded by cd). The parameter generation layer gravitates toward these high-frequency standalone patterns, overriding the cd prefix intent.

Additional control: source /dev/null && echo sourced → prefix included ✅ — suggesting the issue is specific to cd + external tool combinations.

Additional Context

  • Related: #21990 (similar pattern — Claude "knows" the correct command but generates incorrect parameters, 70% failure rate even with CLAUDE.md instructions)
  • The description field of the Bash tool often contains the correct intent ("cd included", "WITH cd") while the command field does not — suggesting intent "leaks" into description instead of command
  • This may be relevant to interpretability research: the divergence between text-layer intent expression and tool-parameter-layer generation could reflect different attention allocation patterns within the same forward pass

View original on GitHub ↗

This issue has 4 comments on GitHub. Read the full discussion on GitHub ↗