You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Add Pi discovery and managed gateway configuration - #109
Adds first-class support for the pi.dev coding-agent harness (@earendil-works/pi-coding-agent) so it shows up in local inventory and can be pointed at the LLM gateway.
Discovery
Binary:pi on PATH, plus Homebrew / ~/.local/bin candidates. The name pi is too generic to trust alone, so a candidate is accepted only after verifying the @earendil-works/pi-coding-agent package manifest. Windows npm CMD, PowerShell, and shell shims are checked against their sibling package and launch target without executing them. PowerShell-only installs are discovered from the standard npm location or custom locations on PATH, even when .ps1 is absent from PATHEXT; PowerShell PATH entries retain their order.
Version: npm package.json (no pi --version exec).
MCP: defaults to Pi's built-in <agent-dir>/mcp.json and the working directory's .pi/mcp.json when saved project trust or defaultProjectTrust: always allows it. Honors built-in extension disable/override settings. An installed, enabled pi-mcp-adapter switches discovery to the adapter's user/shared/project paths, including its bounded ancestor opt-in and PI_MCP_CONFIG_MODE=exclusive. Detects configured npm/git/local packages and local extension directories; disabled, missing, hidden, and untrusted project adapters do not enable adapter inventory. Session-only trust and command-line extension overrides cannot be inferred. Args, env, and headers are omitted.
Skills:~/.pi/agent/skills, ~/.agents/skills, the working directory's .pi/skills, and .agents/skills from the working directory through the git repository root.
--user merges providers.agentdesktop into ~/.pi/agent/models.json (api: anthropic-messages, authHeader: true, apiKey: !<credential command> resolved at request time) and sets defaultProvider / defaultModel in settings.json. Other keys (theme, packages, extra providers) are preserved.
The daemon's local credential endpoint reuses the existing 60-second controller-token cache implementation, with a 30-second expiry margin and single-flight fetches. Cache admission is limited to allowed client IDs and separated by gateway, audience, and enrolled device; logout, re-enrollment, and local policy changes prevent reuse. OIDC and subscription flows retain their existing refresh behavior. Pi still executes the helper per request, but repeated requests avoid controller round trips.
model is required when the gateway is used. An omitted models map creates that catalog entry. Model map keys determine catalog IDs, and generated gateway URLs take precedence over per-model endpoints using each model's API dialect.
Sandbox translation is not supported (same as Grok / OpenCode / Claude Desktop / Copilot CLI / VS Code).
daemon.pi.models / daemon.pi.settings override the user paths. System mode rejects these overrides and has no Pi paths or cleanup placeholders. ~ in PI_CODING_AGENT_DIR is expanded consistently for configuration, MCP, and skills.
Commented models.json files, including BOMs and trailing commas, are merged and rewritten as standard JSON while preserving user values. Other settings files retain strict JSON parsing.
On Unix, models.json is written owner-only (0600), and a looser mode is repaired on the next reconcile; cleanup keeps the file's current mode. Dry runs report the models.json action and path without its contents, since it may hold the user's own API keys.
Pi does not read /etc/pi, so managing programs.pi requires --user. Empty model IDs are rejected before models.json is written. In user mode, authenticated gateway configuration rejects --once because credential helpers need a running daemon. Pi is opt-in in both standalone and Claude examples.
Mixed-mode fleet policies
A policy can include both user-only and system-only programs. Each daemon skips programs its mode cannot manage and reports them as inactive with an actionable reason in configuration status and dry-run output. Supported programs continue applying.
System daemons skip Pi, Copilot CLI, and VS Code; user daemons skip Claude Desktop and Grok Build.
Skipping happens before file access. Existing files and ownership metadata are preserved, including when a skipped program is removed from the policy. Cleanup runs only in the program's supported mode.
Removed the Pi/Claude Desktop and Pi/Grok combination checks. Normal configuration validation and genuine plan/write failures still apply.
--once ignores runtime requirements of skipped programs. A skipped Claude Desktop entry does not trigger subscription sign-in.
Documentation, examples, and generated configuration schemas describe the mode behavior.
Validation
CI on 2d797f5: Test and lint (including UI and schema checks), Windows agent tests, and Container all passed.
cargo test --locked --workspace --lib: 471 passed, including 386 agent tests.
cargo xtask schema regenerated configuration schema descriptions for mode skipping.
Frontend lint/packaging checks, both production builds, and all 126 Storybook tests passed on 3bdff6a; the mode-skipping follow-up changes no frontend code.
Mode regressions cover a mixed policy in both scopes, inactive reasons, supported writes, preservation of owned files/sidecars during apply and cleanup, unreadable skipped paths, genuine failure blocking, one-shot validation, and subscription selection.
Pi regressions cover native MCP project trust, adapter installation and enablement, package filters, project overrides, hidden extension directories, user-only paths, and credential-cache isolation across clients, gateway, audience, policy, and device identity.
Merged current main (74c58f5), resolved the standalone README conflict, and removed unrelated generated Tauri schemas from the PR diff.
Windows performance timing was not measured locally (macOS); the existing Windows CI job covers agent behavior.
Follow-ups
Official Pi mark if there is a canonical SVG
Wire crates/agent/tests/integration.rs once the container fixture exists
Nit (1): Update the walkthrough, prerequisites, and expected summary for Pi reconciliation.
examples/claude/claude-code.yaml
Adds Pi gateway configuration.
Moderate (1): Remove Pi from the system-mode example or provide a user-mode configuration/invocation.
crates/core/src/config.rs
Adds Pi config parsing and validation.
—
crates/agent/src/reconcile/mod.rs
Registers Pi reconciliation.
—
crates/agent/src/provider/README.md
Documents Pi provider support.
—
crates/agent/src/provider/pi/reconcile.rs
Merges Pi models and settings.
Moderate (2): Handle model IDs that differ from their map keys. Moderate (1): Support Pi-compatible comments in models.json. Critical (1): Prevent per-model baseUrl values from bypassing the managed gateway.
crates/agent/src/provider/pi/mod.rs
Defines Pi provider paths and behavior.
Critical (2): Reject unsupported system-mode management or implement a supported system path. Moderate (1): Expand ~ in PI_CODING_AGENT_DIR against the user home.
crates/agent/src/provider/pi/discovery.rs
Discovers Pi, MCP servers, and skills.
Moderate (1): Preserve each user’s default MCP root when an override is set. Moderate (1): Remove the unsupported ~/.agents/mcp/mcp.json path. Moderate (3): Resolve Windows pi.cmd npm shims or inspect the global package location. Moderate (1): Preserve each user’s default skills root alongside the override. Moderate (1): Normalize PI_CODING_AGENT_DIR, including ~ expansion. Moderate (1): Support Pi’s mcp-servers alias.
This function is documented as enumerating files that pi-mcp-adapter loads, but ~/.agents/mcp/mcp.json is not one of the adapter-owned paths listed in the PR contract. Scanning this extra file can show MCP servers in inventory that Pi will not actually load; remove it unless the adapter supports this path.
The documented Pi adapter paths include ~/.agents/mcp.json, but not ~/.agents/mcp/mcp.json. Scanning this extra file can surface MCP servers that Pi never loads, so the inventory is inaccurate; keep discovery limited to files the adapter actually reads.
Detect the pi.dev coding-agent harness (@earendil-works/pi-coding-agent),
inventory MCP servers and skills, and reconcile user-level models.json
and settings.json so Pi can use the LLM gateway with a request-time
credential helper.
Project MCP files stay in the working directory unless a user-global
adapter config opts into ancestorConfigRoots. Skill discovery keeps
.pi/skills in the working directory and stops .agents/skills at the
git root. Validation rejects Pi combined with Claude Desktop or Grok
Build, and rejects empty Pi model IDs before models.json is written.
…ness
Bring in the local LLM proxy, Copilot CLI and VS Code Copilot Chat
providers, per-program status, the opt-in reconcile tick, and inventory
refresh, and fit Pi into them.
- json_merge keeps main's MergeOptions (mode, keyed arrays, diff
redaction, looser-mode repair, removal keeping the file's mode) and
adds the JSONC format and replace_paths that Pi's models.json needs.
- Pi implements Provider::id and is listed by configured_programs, so it
gets a per-program status row like the other programs.
- Pi's models.json redacts dry-run diffs, like the other files that can
hold the user's API keys. Cleanup now keeps the file's current mode,
following main's json_merge removal rule.
- Reconciler::new, daemon startup paths, config validation, schemas,
READMEs, and the controller configuration list Pi next to the Copilot
CLI and VS Code.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E4vKY8hztcuF47Wc2hLnqA
json_merge keeps main's MergeOptions (mode, keyed arrays, diff redaction, looser-mode repair, removal keeping the file's mode) and adds only what Pi's models.json needs: the JSONC format and replace_paths. The Copilot CLI and VS Code options take the new fields from Default, so their behavior is unchanged.
Pi implements Provider::id and is listed in configured_programs, so it reports per-program status (pi_reports_applied_unchanged_removed_then_no_row). It needs no loopback proxy: its apiKey is a credential-helper command.
Pi's models.json now redacts dry-run diffs, like the other files that can hold the user's own API keys. Cleanup keeps the file's current mode, following main's removal rule; merges still write 0600 and repair a looser mode.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds first-class support for the pi.dev coding-agent harness (
@earendil-works/pi-coding-agent) so it shows up in local inventory and can be pointed at the LLM gateway.Discovery
pionPATH, plus Homebrew /~/.local/bincandidates. The namepiis too generic to trust alone, so a candidate is accepted only after verifying the@earendil-works/pi-coding-agentpackage manifest. Windows npm CMD, PowerShell, and shell shims are checked against their sibling package and launch target without executing them. PowerShell-only installs are discovered from the standard npm location or custom locations onPATH, even when.ps1is absent fromPATHEXT; PowerShellPATHentries retain their order.package.json(nopi --versionexec).<agent-dir>/mcp.jsonand the working directory's.pi/mcp.jsonwhen saved project trust ordefaultProjectTrust: alwaysallows it. Honors built-in extension disable/override settings. An installed, enabledpi-mcp-adapterswitches discovery to the adapter's user/shared/project paths, including its bounded ancestor opt-in andPI_MCP_CONFIG_MODE=exclusive. Detects configured npm/git/local packages and local extension directories; disabled, missing, hidden, and untrusted project adapters do not enable adapter inventory. Session-only trust and command-line extension overrides cannot be inferred. Args, env, and headers are omitted.~/.pi/agent/skills,~/.agents/skills, the working directory's.pi/skills, and.agents/skillsfrom the working directory through the git repository root.Managed configuration
--usermergesproviders.agentdesktopinto~/.pi/agent/models.json(api: anthropic-messages,authHeader: true,apiKey: !<credential command>resolved at request time) and setsdefaultProvider/defaultModelinsettings.json. Other keys (theme, packages, extra providers) are preserved.modelis required when the gateway is used. An omittedmodelsmap creates that catalog entry. Model map keys determine catalog IDs, and generated gateway URLs take precedence over per-model endpoints using each model's API dialect.daemon.pi.models/daemon.pi.settingsoverride the user paths. System mode rejects these overrides and has no Pi paths or cleanup placeholders.~inPI_CODING_AGENT_DIRis expanded consistently for configuration, MCP, and skills.models.jsonfiles, including BOMs and trailing commas, are merged and rewritten as standard JSON while preserving user values. Other settings files retain strict JSON parsing.models.jsonis written owner-only (0600), and a looser mode is repaired on the next reconcile; cleanup keeps the file's current mode. Dry runs report themodels.jsonaction and path without its contents, since it may hold the user's own API keys.Pi does not read
/etc/pi, so managingprograms.pirequires--user. Empty model IDs are rejected beforemodels.jsonis written. In user mode, authenticated gateway configuration rejects--oncebecause credential helpers need a running daemon. Pi is opt-in in both standalone and Claude examples.Mixed-mode fleet policies
A policy can include both user-only and system-only programs. Each daemon skips programs its mode cannot manage and reports them as inactive with an actionable reason in configuration status and dry-run output. Supported programs continue applying.
--onceignores runtime requirements of skipped programs. A skipped Claude Desktop entry does not trigger subscription sign-in.Validation
CI on 2d797f5: Test and lint (including UI and schema checks), Windows agent tests, and Container all passed.
cargo test --locked --workspace --lib: 471 passed, including 386 agent tests.cargo clippy --locked --workspace --all-targets -- -D warningsandcargo fmt --all --checkpass.cargo xtask schemaregenerated configuration schema descriptions for mode skipping.Frontend lint/packaging checks, both production builds, and all 126 Storybook tests passed on 3bdff6a; the mode-skipping follow-up changes no frontend code.
Mode regressions cover a mixed policy in both scopes, inactive reasons, supported writes, preservation of owned files/sidecars during apply and cleanup, unreadable skipped paths, genuine failure blocking, one-shot validation, and subscription selection.
Pi regressions cover native MCP project trust, adapter installation and enablement, package filters, project overrides, hidden extension directories, user-only paths, and credential-cache isolation across clients, gateway, audience, policy, and device identity.
Merged current
main(74c58f5), resolved the standalone README conflict, and removed unrelated generated Tauri schemas from the PR diff.Windows performance timing was not measured locally (macOS); the existing Windows CI job covers agent behavior.
Follow-ups
crates/agent/tests/integration.rsonce the container fixture exists