Skip to content

Pi bridge preserves claude-code identification env vars — spawned server misdetects as claude-code and writes to ~/.claude/ instead of ~/.pi/ #561

@ishabana

Description

@ishabana

Bug

When Pi runs npm:context-mode as a package extension, its MCP bridge (mcp-bridge.js) spawns server.bundle.mjs as a child process. The bridge scrubs foreign workspace env vars before spawn (Issue #545), but explicitly preserves identification vars — including CLAUDE_CODE_ENTRYPOINT and CLAUDE_PLUGIN_ROOT.

When Pi is used alongside Claude Code (a common setup), those Claude Code identification vars are present in the shell environment and are inherited by the spawned child. Since CLAUDE_CODE_ENTRYPOINT/CLAUDE_PLUGIN_ROOT are the highest-priority detection signals for the claude-code platform in detectPlatform(), Pi's spawned server always resolves to claude-code — not pi.

As a result:

  • Session dir resolves to ~/.claude/context-mode/sessions/ (not ~/.pi/context-mode/sessions/)
  • Content store (FTS5) resolves to ~/.claude/context-mode/content/ (not ~/.pi/context-mode/content/)
  • Pi's data is written into Claude Code's database
  • ~/.pi/context-mode/content/ is never created

Impact

Two independent processes (Claude Code plugin + Pi extension) simultaneously write to ~/.claude/context-mode/content/*.db in WAL mode. SQLite WAL auto-checkpoint requires no active readers to truncate. With two writers constantly active, the WAL never clears. On a system with additional zombie processes from upgrades (see #559), this caused the WAL to grow to 238MB, making every ctx_search call hang indefinitely.

Verified: ~/.pi/context-mode/sessions/ exists (Pi does write sessions correctly somewhere), but ~/.pi/context-mode/content/ does not exist — confirming content is landing in ~/.claude/.

Root cause

In mcp-bridge.js:

// Identification vars (CLAUDE_PLUGIN_ROOT etc.) and the universal escape hatch
// (CONTEXT_MODE_PROJECT_DIR) are NEVER scrubbed.
for (const banned of foreignWorkspaceEnv("pi")) {
    delete childEnv[banned];
}

foreignWorkspaceEnv("pi") only returns workspace-role vars. Identification vars like CLAUDE_CODE_ENTRYPOINT and CLAUDE_PLUGIN_ROOT are not in the scrub list and survive into the child env, triggering claude-code detection.

Suggested fix

When Pi spawns the MCP server, explicitly delete claude-code identification vars from the child env — OR explicitly set a Pi-specific env var that takes higher priority in detectPlatform():

// Option A — scrub claude-code identification vars for Pi spawns
for (const banned of [...foreignWorkspaceEnv("pi"), "CLAUDE_CODE_ENTRYPOINT", "CLAUDE_PLUGIN_ROOT"]) {
    delete childEnv[banned];
}

// Option B — set Pi's own marker so it wins detection priority
childEnv["PI_AGENT"] = "1"; // and add PI_AGENT as high-priority in PLATFORM_ENV_VARS

Option A is simpler. Option B is more robust if other identification vars are added later.

Environment

  • Platform: Windows 11, Claude Code + Pi running concurrently
  • context-mode v1.0.127
  • Pi packages: ["npm:context-mode", ...] in ~/.pi/agent/settings.json

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions