Skip to content

Config discovery uses process.cwd() instead of ctx.cwd #206

Description

@adameq

The extension resolves project config paths from process.cwd() instead of the session's
ctx.cwd. When a session's workspace differs from the process working directory,
.pi/agents/ and .pi/subagents.json are read from the wrong tree — silently.

Every Agent call then falls back to the built-in general-purpose. Because that agent uses
prompt_mode: append, subagents inherit the full parent prompt and the complete tool set, so
tools:, disallowed_tools:, extensions: false and isolated: true are all ignored —
agents authored as read-only get edit/write. The only hint is
Unknown agent type "<name>" — using general-purpose, which reads like a typo, not a path bug.

Call sites (master): src/index.ts 283 (loadCustomAgents), 872
(agent-tool-description.md), 1572-1573 (agent dirs), 750 (applyAndEmitLoaded called
without cwd); src/settings.ts 251, 260, 310, 328 (cwd: string = process.cwd() defaults).
saveSettings shares the default, so settings written from /agents → Settings also land
outside the project.

When the two differ. Not in normal CLI use — running pi inside the project makes
process.cwd() === ctx.cwd, which is presumably why this went unnoticed. The CLI actively
keeps it that way: resuming a session from another directory prompts
Session found in different project — fork into current directory?, and the fork rewrites the
session cwd to the current one. So the divergence is reachable through the SDK
(docs/sdk.md, "embed pi in other applications"): a host process that creates sessions whose
workspace is not the directory the process was started in. That is what I hit.

Repro — pi 0.83.0, extension 0.14.3, node 24.18.0, Linux.

  1. Project at /home/me/project containing .pi/agents/my-agent.md and .pi/subagents.json
  2. Embed pi via the SDK and open a session with that project as its workspace, from a process
    whose own cwd is elsewhere (e.g. $HOME)
  3. Confirm the workspace is correct — bash pwd, git branch and file listing all report the project
  4. Call Agent({ subagent_type: "my-agent", ... })

Actual: Unknown agent type "my-agent" — using general-purpose; .pi/subagents.json is
ignored as well (maxConcurrent, outputTranscript, toolDescriptionMode fall back to defaults).
Expected: the agent from .pi/agents/ is used and project settings apply.

Fix direction: ctx.cwd is already used throughout the same file (resolveStorePath,
createOutputFilePath, readEnabledModels), and the SDK documents this pattern for project
config — docs/extensions.md:958-962 shows
pi.on("session_start", (_event, ctx) => join(ctx.cwd, CONFIG_DIR_NAME, "my-extension.json")).
reloadCustomAgents() has 15 call sites and all but the init one at index.ts:288 have ctx
in scope, so threading cwd through is mostly mechanical.

I fixed the same bug in two extensions of my own, and after the change they work correctly in
the very same host process that still breaks this one — so a one-sided fix here is sufficient.

Happy to open a PR if you want it.

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