Skip to content

fix: pass CLAUDE_PROJECT_DIR so execute_file resolves relative paths#12

Closed
dunika wants to merge 1 commit into
mksglu:mainfrom
dunika:fix/execute-file-relative-paths
Closed

fix: pass CLAUDE_PROJECT_DIR so execute_file resolves relative paths#12
dunika wants to merge 1 commit into
mksglu:mainfrom
dunika:fix/execute-file-relative-paths

Conversation

@dunika

@dunika dunika commented Mar 1, 2026

Copy link
Copy Markdown
Contributor

Summary

  • start.sh does cd "$DIR" into the plugin install directory before launching node, so process.cwd() in the server becomes the plugin directory
  • Relative paths passed to execute_file then resolve against the wrong directory
  • Fix captures $(pwd) before the cd and passes it as CLAUDE_PROJECT_DIR env var to the node process

Changes

  • Capture CLAUDE_PROJECT_DIR (defaulting to $(pwd)) on line 2, before the cd
  • Pass it to both exec node invocations (bundle and fallback paths)

Test plan

  • [x ] Verify execute_file with a relative path resolves against the project directory, not the plugin directory

Fixed Error 1 — Silent misread

  package.json — printed context-mode instead of project folder. The relative path resolved to the context-mode
   plugin's own package.json at
  /Users/dunika/.claude/plugins/cache/claude-context-mode/context-mode/0.7.2/package.json, not the
  project's.

  The test was: execute_file with path package.json, code const pkg = JSON.parse(FILE_CONTENT);
  console.log(pkg.name); — should have printed the project folder, printed context-mode instead.
image

Fixed Error 2 — ENOENT

  Error processing apps/web-app/src/app/feedback/client.tsx (exit 1):
  1 | const FILE_CONTENT_PATH = "/Users/dunika/.claude/plugins/cache/claude-context-mode/context-mode/0.7.2
  /apps/web-app/src/app/feedback/client.tsx";
  2 | const FILE_CONTENT = require("fs").readFileSync(FILE_CONTENT_PATH, "utf-8");
            ^
  ENOENT: No such file or directory
     errno: -2
   syscall: "open"
     path: "/Users/dunika/.claude/plugins/cache/claude-context-mode/context-mode/0.7.2/apps/web-app/src/app
  /feedback/client.tsx"

        at /private/var/folders/1g/xh57x2qd1y77fml0bc_mk0q00000gn/T/ctx-mode-SCL3Cb/script.js:2:7
image

…e paths correctly

start.sh does `cd "$DIR"` (into the plugin install directory) before
launching node, which means process.cwd() in the server becomes the
plugin directory. Relative paths passed to execute_file then resolve
against the wrong directory.

Capture $(pwd) before the cd and pass it as CLAUDE_PROJECT_DIR env var
to the node process so the server can resolve relative paths against the
user's actual project directory.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@mksglu

mksglu commented Mar 1, 2026

Copy link
Copy Markdown
Owner

Thanks for the contribution @dunika! 🙏

I've added unit tests and wired the server-side consumption of CLAUDE_PROJECT_DIR:

What was added:

  • tests/project-dir.test.ts — 8 unit tests covering:
    • Relative path resolution against projectRoot (not process.cwd())
    • Nested directory path resolution
    • Absolute path bypass (ignores projectRoot)
    • Default projectRoot fallback to process.cwd()
    • Non-existent file graceful failure
    • Multi-language support (JS, Python, Shell)
  • src/server.ts — Pass process.env.CLAUDE_PROJECT_DIR to PolyglotExecutor constructor
  • package.json — Added test:project-dir script and included in test:all

Technical note: CLAUDE_PROJECT_DIR is officially supported by Claude Code for hook processes and file suggestion commands, but is not automatically injected into MCP server processes. Your start.sh approach of capturing $(pwd) before cd "$DIR" and passing it explicitly is the correct pattern for MCP servers that need to know the user's project directory. The server-side PolyglotExecutor already had the projectRoot mechanism — it just wasn't wired to the env var.

All 8 tests passing ✅

mksglu added a commit that referenced this pull request Mar 1, 2026
Captures the user's working directory in start.sh before cd-ing into
the plugin directory, and passes it to PolyglotExecutor so executeFile
resolves relative paths correctly.

Contributor: dunika
@mksglu

mksglu commented Mar 1, 2026

Copy link
Copy Markdown
Owner

Merged into next branch. The start.sh fix correctly captures the user's working directory before cd-ing into the plugin directory. We also wired CLAUDE_PROJECT_DIR into the PolyglotExecutor constructor in server.ts, and added 8 unit tests for relative path resolution. Thanks @dunika!

This will be included in the next release.

@mksglu mksglu closed this Mar 1, 2026
@mksglu

mksglu commented Mar 1, 2026

Copy link
Copy Markdown
Owner

@dunika Sorry about closing this instead of merging — that was a mistake on my end. Your changes have been merged into the next branch and will be included in v0.8.0. Apologies for the confusion!

mksglu added a commit that referenced this pull request Mar 1, 2026
## What's Changed

### Bug Fixes
- fix: stream-level byte cap to prevent OOM from runaway output (#5) — @rjkaes
- fix: shell $-expansion vulnerability in executeFile paths (#7) — @rjkaes
- fix: wire searchWithFallback, eliminate ephemeral DB, harden store (#4) — @rjkaes
- fix: pass CLAUDE_PROJECT_DIR for relative path resolution (#12) — @dunika
- fix: use npx tsx in skills instead of build/cli.js (#9) — @amoslives

### New Features
- feat: add Elixir language support (#8) — @ekosz

### Chore
- Dynamic contributor avatars via contrib.rocks
- Simplified test:all with glob pattern
- Version bump 0.7.3 → 0.8.0

## New Contributors
- @rjkaes
- @ekosz
- @dunika
- @amoslives
- @InTheCloudDan
@dunika

dunika commented Mar 1, 2026

Copy link
Copy Markdown
Contributor Author

Perfect - thanks! I really appreciate you making this open source.

@dunika dunika deleted the fix/execute-file-relative-paths branch March 1, 2026 13:50
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.

2 participants