Skip to content

[Bug]: Pi provider lacks per-workspace skill discovery — project .agents skills never appear in the $ picker #15810

Description

@v-senninha-v

Before submitting

  • I searched existing issues and did not find a duplicate.
  • I included enough detail to reproduce or investigate the problem.

Area

apps/server

Steps to reproduce

  1. Add a project skill: <repo>/.agents/skills/test-skill/SKILL.md (committed; the repo is trusted in ~/.pi/agent/trust.json, or set the Pi provider launch args to --approve in T3 settings).
  2. Open a thread with the Pi provider in that repo.
  3. Ask the agent to list its skills → the agent does list the project skill (pi loads it; RPC get_commands returns it).
  4. Type $ in the composer → the project skill is absent; only user-scope skills appear.
  5. Inspect ~/.t3/caches/pi.json after a provider refresh: the workspaceSnapshots key is absent, and the provider-level skills array contains only entries under the home directory.

Expected behavior

The $ picker shows the same skills pi exposes via get_commands for the thread's cwd (project .agents/skills included), mirroring how the Claude provider surfaces .claude/skills per workspace. A provider refresh or app restart should make project skills appear.

Actual behavior

Only user-scope skills appear, for the life of the server process, regardless of provider refresh or app restart. The agent-side behavior is correct — pi's system prompt includes the project skills, so the model can use them; only the picker is wrong (easy to miss because of this A/B mismatch).

Impact

Blocks work completely

Version or commit

No response

Environment

  • T3 Code nightly 0.0.46-nightly.20261004 (Windows 11, desktop) - pi 1.0.2

Logs or stack traces

Root cause (verified against main @ HEAD):

- `ProviderRegistry.refreshWorkspaceSnapshot` (apps/server/src/provider/Layers/ProviderRegistry.ts) early-returns when `!instance?.snapshotForCwd`.
- Every driver implements `snapshotForCwd` (Claude, Codex, Cursor, Grok, OpenCode, Antigravity) — PiDriver does not. `ProviderDriver.ts` declares the field optional, so this type-checks silently.
- Composer fallback: `resolveProviderSkillsForCwd` -> `provider.skills`, discovered by `checkPiProviderStatus` in the server process cwd. On desktop that is `backendCwd = homeDirectory` (apps/desktop/src/app/DesktopEnvironment.ts), which can never see project skills.
- Confirmed pi itself works: `pi --mode rpc --no-session --approve` + `get_commands` in the repo returns the project skills (pi supports `.agents/skills` at user and project-ancestor scope, gated by project trust; `--approve` covers RPC mode, which cannot show the interactive trust prompt).

Related but distinct: #14801 (Claude, worktree created mid-session), #11575 (Claude, snapshot before first probe) — different drivers and causes.

Screenshots, recordings, or supporting files

No response

Workaround

Add the project skills directory to user-level pi settings (~/.pi/agent/settings.json):

{ "skills": ["D:\\path\\to\\repo\\.agents\\skills"] }

These load in every pi session (including the provider-level home-dir discovery), so they appear in the $ picker. Alternatively, /skill:<name> typed directly still works even when the picker omits the skill.

Activity

  1. added
    bugSomething is broken or behaving incorrectly.
    needs-triageIssue needs maintainer review and initial categorization.
    on Oct 5, 2026
  2. juliusmarminge commented on Oct 5, 2026

    @juliusmarminge
    Member

    Note

    Grok responding on behalf of Julius.

    Triage

    Thanks @v-senninha-v for the detailed root-cause write-up and the workaround. It checked out against current main (efecd3cf8b).

    What I found

    • ProviderRegistry.refreshWorkspaceSnapshot (apps/server/src/provider/Layers/ProviderRegistry.ts) returns the current provider list without scanning when the instance has no snapshotForCwd. PiDriver is the only driver that leaves it out. Claude, Codex, Cursor, Grok, OpenCode, and Antigravity all implement it. The field is optional in ProviderDriver.ts, so this type-checks.
    • The machine-level catalog comes from checkPiProviderStatus, which uses the server process cwd (ServerConfig.cwd). discoverPiViaRpc passes that cwd into pi --mode rpc, so get_commands only sees skills that are visible from there. Where that cwd ends up depends on how T3 is run:
      • Packaged desktop app: the home directory (backendCwd in DesktopEnvironment.ts).
      • Unpackaged desktop build: the app root.
      • npx t3: whatever directory the server was started in.
    • The composer already asks for a workspace scan and prefers workspaceSnapshots for the thread cwd (resolveProviderSkillsForCwd in packages/client-runtime/src/providerSkills.ts). When there's no snapshot, it falls back to provider.skills, and each re-ask does nothing on the server.
    • The live Pi session works because the adapter starts pi in the thread cwd. That's why the model can list the project skill, and why typing /skill:<name> still runs it.
    • Project slash commands are hidden the same way, because / uses resolveProviderSlashCommandsForCwd with the same fallback.
    • These are related but aren't duplicates:

    Likely fix area

    One option is to add snapshotForCwd to PiDriver. It would run the existing short-lived get_commands discovery in the requested cwd, using that instance's launch args, and lay both skills and slashCommands over the machine snapshot. Some details to keep in mind:

    • The cwd result has to be the full set Pi exposes there, user skills included, because the client replaces the machine list with it.
    • Keeping the existing discovery timeout means an untrusted project can't hang on Pi's trust prompt.
    • A regression test could show that a Pi cwd probe lands in workspaceSnapshots while the machine-level skills stay unchanged.

    Until then, the workaround in the report works: point Pi's user skills setting at the project's .agents/skills, or type /skill:<name>.

    A maintainer will decide on the fix direction.

  3. added
    via-triageFiled through npx t3 triage
    and removed
    needs-triageIssue needs maintainer review and initial categorization.
    on Oct 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething is broken or behaving incorrectly.via-triageFiled through npx t3 triage

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions