Skip to content

fix: pin Claude ctx_execute cwd to session cwd#765

Merged
mksglu merged 1 commit into
mksglu:nextfrom
NgoQuocViet2001:fix/ctx-execute-session-cwd
Jun 13, 2026
Merged

fix: pin Claude ctx_execute cwd to session cwd#765
mksglu merged 1 commit into
mksglu:nextfrom
NgoQuocViet2001:fix/ctx-execute-session-cwd

Conversation

@NgoQuocViet2001

Copy link
Copy Markdown
Contributor

Fixes #756.

Reported by @chrisjenx. cc @mksglu

What changed

  • Add an optional cwd argument to ctx_execute and ctx_batch_execute, and pass it through to shell execution.
  • Update Claude Code PreToolUse routing to resolve the active project dir from the hook payload (cwd / workspace_roots) instead of stale CLAUDE_PROJECT_DIR.
  • Automatically pin shell ctx_execute / ctx_batch_execute calls to the active session cwd when no explicit cwd is provided.
  • Preserve explicit cwd values and keep non-shell languages in their existing temp-dir sandbox.

Validation

  • node_modules/.bin/vitest.CMD run tests/hooks/core-routing.test.ts tests/hooks/integration.test.ts tests/core/server.test.ts -t "MCP execute|MCP batch_execute|runBatchCommands|ctx_execute_file: CONTEXT_MODE_PROJECT_DIR"
  • npm run typecheck
  • npm run bundle
  • npm run assert-bundle && npm run assert-asymmetric-drift
  • git diff --check

@mksglu

mksglu commented Jun 2, 2026

Copy link
Copy Markdown
Owner

Hi @NgoQuocViet2001 1- Let's reproduce the issue. 2- Let's fix them. 3- Let's verified manually.

@NgoQuocViet2001 NgoQuocViet2001 force-pushed the fix/ctx-execute-session-cwd branch from 741b9c0 to b050fa1 Compare June 2, 2026 11:01
@NgoQuocViet2001

Copy link
Copy Markdown
Contributor Author

@mksglu I reproduced and verified this manually with real Claude Code E2E on my Windows machine, then pushed the rebased branch onto next.

E2E setup:

  • Claude Code 2.1.96
  • temp git worktree as the session cwd
  • temp MCP config using mcp__plugin_context-mode_context-mode__ctx_execute
  • MCP server cwd intentionally set to the main checkout
  • prompt forced one tool call: ctx_execute(shell, "pwd; git rev-parse --show-toplevel")

Before (upstream/next, 1.0.161): PreToolUse returned no updatedInput, and the output was the MCP server checkout (.../upstream-next-main), not the session worktree.

After this branch: PreToolUse returns updatedInput.cwd = .../session-worktree, and the output is the session worktree.

Validation:

  • node_modules/.bin/vitest.CMD run tests/hooks/core-routing.test.ts tests/hooks/integration.test.ts tests/core/server.test.ts -t "MCP execute|MCP batch_execute|runBatchCommands|ctx_execute_file: CONTEXT_MODE_PROJECT_DIR"
  • npm run typecheck
  • npm run bundle
  • npm run assert-bundle && npm run assert-asymmetric-drift
  • git diff --check upstream/next..HEAD

@chrisjenx

Copy link
Copy Markdown

Anything I can do to check/test?

@mksglu

mksglu commented Jun 8, 2026

Copy link
Copy Markdown
Owner

Anything I can do to check/test?

I'll take it when soon. Until that please resolve conflicts. Thank you.

@ken-jo

ken-jo commented Jun 13, 2026

Copy link
Copy Markdown
Contributor

@mksglu Validation completed according to the maintainer review requirements.

Verdict

The behavior is valuable and functionally validated, but this PR needs an update before merge because GitHub reports mergeStateStatus: DIRTY.

After the conflict is resolved, I would re-run the same 3OS validation before final merge.

What this PR meaningfully fixes

This PR pins Claude Code ctx_execute / batch execution to the active Claude session project directory when the tool call does not already provide an explicit cwd.

That matters because MCP execution can otherwise run shell commands from the MCP server/plugin process location instead of the user's active project. In context-mode, cwd affects:

  • relative shell command behavior
  • project attribution
  • security/deny-policy resolution
  • session continuity data
  • whether the agent is analyzing the intended repository or a plugin/runtime directory

The important invariant is that the patch should only fill in a missing cwd. It must not overwrite a deliberate explicit cwd provided by the tool caller.

Git archaeology checked

I checked the cwd/project-dir history before accepting the behavior. Relevant history shows prior fixes around project directory resolution, ctx tool cwd behavior, and policy enforcement.

The key invariants checked for this PR were:

  • Claude Code tool execution should default to the session project dir.
  • Explicit cwd must remain explicit and must not be overwritten.
  • The fix should stay scoped to the affected Claude ctx execution path, not change unrelated adapters.
  • The change should not weaken deny-policy enforcement that depends on project directory resolution.

Validation performed

GitHub status:

  • Merge state: DIRTY
  • test (ubuntu-latest): pass
  • test (macos-latest): pass
  • test (windows-latest): pass
  • openclaw-e2e (ubuntu-latest): pass
  • openclaw-e2e (macos-latest): pass

Targeted tests passed:

  • tests/hooks/core-routing.test.ts
  • tests/hooks/integration.test.ts
  • tests/core/server.test.ts
  • focused pattern: MCP execute|MCP batch_execute|runBatchCommands|ctx_execute_file: CONTEXT_MODE_PROJECT_DIR

The explicit-cwd invariant was also covered: explicit ctx_execute.cwd is not overwritten.

Live Claude Code validation

Per maintainer requirements, live validation used Claude Haiku.

Linux:

  • Claude Code live run with the PR plugin loaded.
  • ctx_execute ran from the session project directory.
  • Debug output showed updatedInput.cwd set to the intended session repo.

macOS:

  • Claude Code live run with the PR plugin loaded.
  • ctx_execute cwd resolved to the macOS canonical project path.
  • /tmp vs /private/tmp normalization was observed and is expected on macOS.

Windows:

  • Claude Code live run with the PR plugin loaded.
  • ctx_execute ran from the intended Windows session project directory.
  • Debug output showed updatedInput.cwd as the expected Windows path.

Remaining update needed

The PR is worth merging after the merge conflict is resolved and the same 3OS live validation is re-run.

@ken-jo

ken-jo commented Jun 13, 2026

Copy link
Copy Markdown
Contributor

Hi @NgoQuocViet2001, thank you for contributing this PR.

I validated the change according to the maintainer review requirements. The behavior looks valuable and worth merging: the Claude Code ctx_execute cwd handling was validated with targeted tests and live Claude Haiku checks on Linux, macOS, and Windows.

The only blocker I see right now is that the PR has merge conflicts (mergeStateStatus: DIRTY).

Could you please resolve the conflicts? After that, we can re-run the same validation and move this toward merge.

@NgoQuocViet2001 NgoQuocViet2001 force-pushed the fix/ctx-execute-session-cwd branch from e18a358 to 2dcf262 Compare June 13, 2026 14:26
@mksglu

mksglu commented Jun 13, 2026

Copy link
Copy Markdown
Owner

Hi @NgoQuocViet2001 resolve conflicts pls

@NgoQuocViet2001 NgoQuocViet2001 force-pushed the fix/ctx-execute-session-cwd branch from 2dcf262 to 3cd82b0 Compare June 13, 2026 16:31
@NgoQuocViet2001

Copy link
Copy Markdown
Contributor Author

@mksglu @ken-jo conflicts resolved and pushed. Local checks passed; CI is running now.

@mksglu mksglu merged commit 498460d into mksglu:next Jun 13, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: ctx_execute runs in the MCP server's process cwd (main repo), not the session's git-worktree cwd — Claude Code, still repro on 1.0.161

4 participants