pi-profile-switch

Named profiles for Pi: reference skills, extensions, MCP servers, and tools per workflow, switched without restarting. Install: npm install -g pi-profile-switch (not pi install).

Packages

Package details

extension

Install pi-profile-switch from npm and Pi will load the resources declared by the package manifest.

$ pi install npm:pi-profile-switch
Package
pi-profile-switch
Version
0.15.0
Published
Oct 9, 2026
Downloads
6,110/mo · 1,241/wk
Author
vincentff
License
MIT
Types
extension
Size
286.8 KB
Dependencies
2 dependencies · 1 peer
Pi manifest JSON
{
  "extensions": [
    "./extensions"
  ]
}

Security note

Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.

README

pi-profile-switch

English | 中文

Named profiles for Pi. A profile is a named set of resources you define: skills, extensions, MCP servers, tools, per-server MCP tool selections (mcp_tools), model defaults, and extra system-prompt instructions. Switch profiles inside a running Pi session — no restart.

Install

npm install -g pi-profile-switch

Requires Pi 0.99.1 or newer (installed automatically as a peer dependency). Use npm install -g, not pi install — this package provides the pi-profile launcher.

Quick start

# Built-in default profile: all resources, plain Pi behavior
pi-profile

# Starter read-only ask profile
pi-profile ask

# Anything after -- is passed to pi verbatim
pi-profile ask -- --model openai/gpt-5.4

Define your own profiles

Profiles live in two directories, one JSON file per profile:

Path Scope
~/.pi-profile-switch/profiles/<name>.json Global, all projects. PI_PROFILE_SWITCH_DIR overrides the root directory.
<project>/.pi/profiles/<name>.json Project-level, trusted projects only. Completely replaces a global profile with the same name.

Write the JSON directly (schema: schemas/profiles.schema.json), or configure profiles conversationally: the package ships a profile-config skill that creates, edits, and deletes profiles. Profiles created with a skills list include "profile-config" by default (unless you opt out or cover it with a wildcard like "*"), keeping configuration available after switching.

When the global profiles directory has no profile yet, pi-profile-switch writes a starter ask profile — read-only Q&A and code exploration. It assumes nothing about your setup; edit or delete it freely. See examples/ask.json.

A profile that uses every field:

{
  "label": "Implementation",
  "description": "Full-powered implementation profile: every available field, pinned model",
  "skills": ["tdd", "internal-*"],
  "mcps": ["github", "linear"],
  "tools": ["read", "grep", "find", "ls", "bash", "edit", "write"],
  "mcp_tools": {
    "github": ["search", "get_issue"],
    "linear": []
  },
  "defaultProvider": "anthropic",
  "defaultModel": "claude-sonnet-4-5",
  "defaultThinkingLevel": "high",
  "instructions": "Prefer small, verifiable changes. Run the test suite before claiming completion.",
  "subagents": {
    "defaultModel": "anthropic/claude-sonnet-4-5",
    "agentOverrides": {
      "reviewer": {
        "thinking": "high",
        "description": "Independent review for this project",
        "advertise": true
      }
    }
  }
}

How the fields behave:

  • skills, extensions, mcps, tools take names or globs (e.g. "internal-*") referencing resources you already installed or configured — profiles never copy them. Installed packages and files in standard locations are discovered automatically; no registration needed.
  • tools expands strictly against Pi's non-MCP tool registry — built-ins and extension-contributed tools, attributed by registration ownership (sourceInfo). Available MCP tools remain usable independently of tools. When a profile declares tools and at least one MCP server is enabled, Pi's native MCP discovery entry points (codemode and tool_search) stay active even if you did not list them; unrelated non-MCP tools excluded by tools stay excluded.
  • mcp_tools defines per-server MCP tool filtering: keys are literal configured server names and values are literal MCP tool names as exposed by Pi's built-in MCP extension. Globs are not accepted. An omitted server keeps native access to all its tools; a nonempty array allows only matched tools; an empty array ([]) denies all tools for that server while leaving it enabled. Unmatched selectors remain restrictive and are not diagnosed, so confirm selectors with the server before writing them.
  • Migration notes:
    • Former MCP references in tools (e.g. mcp__*, <server>_*) no longer govern MCP access. Move desired MCP tool restrictions to mcp_tools.
    • Prefixed selectors (e.g. <server>_<tool> forms used by previous MCP integrations) no longer apply; replace them with the literal tool names from Pi's built-in MCP extension.
  • mcps references servers from your Pi user-level MCP configuration (~/.config/mcp/mcp.json, ~/.agents/mcp.json, ~/.agents/mcp/mcp.json, and <agentDir>/mcp.json); connection details stay in those files.
    • Omitting mcps leaves all discovered user-level servers at their normal availability.
    • mcps: [] disables every discovered user-level server, including agentDir-only servers; every unselected user-level server keeps its full definition and is explicitly marked enabled: false in the generated instance mcp.json. Project-level servers are never narrowed.
    • Trusted project-level MCP servers are always kept enabled and are never narrowed by mcps.
    • Servers using type: "sse" cannot be selected; migrate them to streamable HTTP before referencing them in a profile.
    • A later user-level source replaces a same-named server from an earlier source in full (no field-wise merging), so connection and credential fields are never inherited across files.
    • A profile that declares neither mcps nor mcp_tools treats a malformed user-level MCP source as a non-fatal diagnostic (printed on stderr with the file path) and starts with the remaining valid sources. Declaring mcps or a nonempty mcp_tools makes the same malformed source fail activation, because the allowlist cannot be trusted.
  • The instance mcp.json is always a generated snapshot of the merged user-level configuration. In-session pi mcp add edits the instance copy, and the next /profile use or /profile reload overwrites it with the profile's snapshot.
  • Any field you omit keeps plain Pi behavior.
  • label and description are display metadata. defaultProvider and defaultModel (declared together) set the startup model; defaultThinkingLevel sets its thinking level; instructions is appended to the system prompt.
  • subagents optionally supplies native pi-subagents model/thinking defaults and exact role overrides. It does not load pi-subagents or change which roles or tools are available. Role descriptions are metadata, not child prompts; advertise controls parent-prompt listing, not whether a role can run. /profile status shows declared inputs, while /subagents-models inspects the native live mapping. See the subagent behavior contract and pi-subagents model documentation.
  • skills, extensions, mcps, and tools reference installed resources by name or glob; profiles never copy resources. tools covers non-MCP tools only (built-ins and extension tools).
  • mcp_tools selects tools inside MCP servers by literal server and tool name — globs are rejected. Omit a server to leave it unchanged, use [] to deny all of its tools while keeping the server enabled, or list names to allow only those. A literal selector that matches nothing stays restrictive without warning; a server that is unknown, disabled, or project-only fails activation with candidates.
  • mcps names user-level servers from ~/.config/mcp/mcp.json, ~/.agents/mcp.json, ~/.agents/mcp/mcp.json, and <agentDir>/mcp.json. Omit it to leave all servers as configured; use [] to disable every user-level server. Project-level servers (.pi/mcp.json) are read by Pi itself and are never narrowed. Legacy SSE servers cannot be selected.
  • Older profiles expressed MCP tool access through mcp__* or <server>_* entries in tools; use mcp_tools instead.
  • Every omitted field keeps plain Pi behavior.

The instance's mcp.json is generated by the launcher. Running pi mcp add inside a session only edits that generated copy, and the next profile switch or reload overwrites it — edit your real MCP configuration instead.

examples/ contains the full example above and the starter ask.

Commands

Command What it does
/profile Show the available profiles and pick one (interactive selector; prints the list outside the TUI).
/profile use <name> Switch profiles now. The session reloads with the new resources; a failed switch rolls back. The choice is remembered for the next launch.
/profile reload Re-read the active profile file after editing it.
/profile status Report the active profile, resolved resources and paths, overlay, MCP server state, and conflicts.
/profile overlay disable|enable skill|extension|mcp|tool <name-or-glob> Narrow or restore resources for this session only.
/profile overlay clear Drop the overlay and use the profile as written.

All forms work in every mode, including non-interactive ones (--mode rpc|text|json); the bare selector degrades to the profile list where no interactive UI exists. The overlay is a runtime-only narrowing: it is never written to a catalog file and never survives a restart. Tools follow the same disable/enable model as the other resource kinds: a tool disable entry narrows the profile's resolved tool references — or the runtime's full available tool set when the profile declares no tools. All of these work in every mode, including non-interactive ones (--mode text, --mode json, --mode rpc). An overlay lives only in the current runtime: it is never written to your profile files and is gone after a restart. Disabling MCP servers with an overlay is not possible on the built-in default profile — it has no server list to narrow.

Migration: undeclared resource fields

Earlier releases treated an omitted skills or extensions field as an empty selection, hiding that kind. Omission now keeps Pi's native visibility for that kind, so a profile that relied on the old behavior can expose more resources after upgrading.

To hide a kind, declare it explicitly empty instead of omitting it:

{
  "skills": [],
  "extensions": []
}

The authoritative selection contract is Sparse skill and extension selection.

Docs

License

MIT