MoonshotAI / MoonshotAI/kimi-code

Bash tool cwd is silently ignored when the command starts with cmd &

Open
#2,890 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug
Dominant language
TypeScript
Stars
7.5k
Forks
1.2k
Avg merge
11h 53m
Merged PRs (30d)
350

Description

What version of Kimi Code is running?

0.35.0

Which open platform/subscription were you using?

Kimi Code (OAuth)

Which model were you using?

K3

What platform is your computer?

Darwin 25.3.0 arm64 arm

What issue are you seeing?

TL;DR

The Bash tool applies its cwd parameter by textually prepending cd '' && to the user's command. If the command's first line ends with &, shell operator precedence (&& binds tighter than &) sends the entire chain — including the cd — into a background subshell. The main shell never changes directory, so all following lines of the script run in the wrong directory. Nothing is reported; the cwd parameter is silently ignored.


What the caller expects

 // Bash tool call                                                                                                     
 {                                                                                                                     
   "cwd": "/repo/packages/ui",                                                                                         
   "command": "node server.js &\nsleep 1\nnode check.js"                                                               
 }                                                                                                                     

The caller's mental model: the whole script runs with /repo/packages/ui as its working directory — server.js in the background, check.js in the foreground, both in that directory.

What actually runs

The harness prepends the cd, producing:

 cd '/repo/packages/ui' && node server.js &                                                                            
 sleep 1                                                                                                               
 node check.js                                                                                                         

Bash parses line 1 as "background the whole cd ... && node server.js list". The cd happens inside the background subshell and has no effect on the main shell. So:

  • node server.js — background, correct directory (output even looks right, e.g. it prints paths from the requested cwd);
  • node check.js — foreground, original default directory (e.g. the repo root).

The asymmetry is the nasty part: the visible output suggests everything worked, while the foreground half of the script silently ran somewhere else. In practice this surfaced as Cannot find module errors with a require stack pointing at a completely different directory tree than the requested cwd, plus orphaned background processes the script's own kill %1 couldn't reach.

Evidence from a real session wire log

Anonymized excerpt from wire.jsonl — the tool call and its result (paths shortened):

  // tool.call (Bash, step 81)                                                                                          
  {                                                                                                                     
    "cwd": "/repo/.worktrees/feature-x/frontend/packages/ui",                                                           
    "command": "node scripts/serve-static.mjs storybook-static 6175 &\nsleep 1\nnode -e                                 
\"require('@playwright/test')...\""                                                                                     
  }                                                                                                                     
                                                                                                                        
  // tool.result — note the require stack: the repo ROOT, not the requested cwd                                         
  "Error: Cannot find module '@playwright/test'                                                                         
  Require stack:                                                                                                        
  - /repo/[eval]"                                                                                                       

The backgrounded server correctly started from /repo/.worktrees/feature-x/... (it inherited the cd), while the foreground node -e resolved modules from /repo — the harness's default cwd. The requested cwd never applied to it.

What steps can reproduce the bug?
  mkdir -p /tmp/kimi-cwd-repro                                                                                          

Then, via the Bash tool with cwd set to /tmp/kimi-cwd-repro:

  sleep 0.1 & echo "foreground cwd: $(pwd)"; wait                                                                       

Expected: foreground cwd: /tmp/kimi-cwd-repro
Actual: the foreground pwd prints the caller's original working directory.

What is the expected behavior?

No response

Additional information

Suggested fix

Apply cwd as a real working directory of the spawned process (e.g. spawn(shell, { cwd })) instead of string-prepending cd. The cwd parameter is part of the tool's contract and should hold regardless of what shell syntax the command contains (&, ||, subshells, etc.).

If that's not feasible, a stopgap would be to detect commands whose first line ends with & and warn or reject, steering the caller to the tool's native run_in_background mechanism.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start at the Bash tool implementation and reproduce the issue with the supplied cwd and a command whose first line ends with an ampersand. Trace how the command is spawned and how cwd is applied; it is done when every command line uses the requested directory regardless of shell operators, with coverage for the reproduction case.

Written by the indexing model from the issue text.

Assessment

Tech stack
bash, typescript
Domain
cli, tooling
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
72/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.