npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

pi-roles

v0.2.3

Published

Role-based session configuration for pi coding agent. Launch a session as a named role and hot-swap roles mid-session, with optional pi-intercom and pi-mcp-adapter integration.

Readme

pi-roles

Role-based session configuration for pi coding agent. Launch a session as a named role (architect, planner, marketing-strategist, …) and hot-swap roles mid-session — without restarting Pi.

pi-roles is to top-level pi sessions what pi-subagents is to sub-agents: same .md + YAML frontmatter convention, same project/user scope rules, drop-in flow. The extension is agnostic of which roles exist — roles are just markdown files you create.

pi --role architect              # launch as architect
PI_ROLE=planner pi               # or via env

/role list                       # inside the session
/role planner                    # swap role mid-session, keep history
/role planner --reset            # swap role and clear history
/role current
/role reload                     # re-read the active role file from disk

When you swap roles, the session's system prompt, model, thinking level, and active tool set are replaced according to the new role's definition. Conversation history is preserved by default.


Install

pi install npm:pi-roles

Then restart pi. The extension is auto-discovered; the --role flag and /role command become available.

To try without installing:

pi -e git:github.com/lojacobs/pi-roles

Why this exists

When you build a multi-agent dev workflow with specialized roles — architect (design), planner (decompose), orchestrator (dispatch), or any equivalent for marketing, research, ops — the top-level role is a property of the whole session, not of an individual sub-agent dispatch. You want different system prompts, different models, different tool restrictions per role, and you want to switch between them without restarting.

pi-roles is the cleanest way to do that. No shell aliases, no separate workspace directories, no forking pi-subagents into something it isn't.


Role files

Roles are markdown files with YAML frontmatter, identical in shape to pi-subagents agent files:

---
name: architect
description: Defines the WHAT. Owns architecture and specs. Never codes.
model: anthropic/claude-opus-4-7
thinking: high
tools: read, grep, find, ls, write, edit
intercom: send             # optional, per-role override
extends: base-reviewer     # optional, role inheritance
---

# Role

You are the Architect. Your job is to define WHAT the system should
do, never HOW to build it...

(everything below the frontmatter is the system prompt body)

Frontmatter reference

| Field | Required | Behavior when omitted | |---|---|---| | name | yes | — must match the filename without .md | | description | yes | — shown in /role list and selectors | | model | no | keeps the session's current model | | thinking | no | keeps the session's current thinking level (off, minimal, low, medium, high, xhigh) | | tools | no — see below | inherits from parent (if extends) or keeps current active set | | intercom | no | falls back to the global intercomMode setting | | extends | no | role inherits from another role |

tools — the tri-state

Three explicit states with three different meanings:

| YAML | Meaning | |---|---| | tools: read, bash | set — exactly these tools, nothing else | | tools: (present, empty) | disable all tools — read-only conversation, no actions | | field absent | inherit — from parent role (extends), else keep session default |

You can also include MCP tool refs in the same field, mirroring pi-subagents:

tools: read, grep, mcp:chrome-devtools, mcp:github

mcp:server-name entries require pi-mcp-adapter to be installed. If it's not, the entry is logged and skipped — the role still loads.

model — provider/id format

Matches Pi's CLI --model syntax:

model: anthropic/claude-opus-4-7
model: openai/gpt-5
model: deepseek/deepseek-v4-pro

If the model isn't available (no API key, unknown provider), the role load surfaces a warning and the session keeps its current model.

intercom — per-role override

Values: off, receive, send, both. Defaults to the global intercomMode setting (which itself defaults to off). See pi-intercom integration below.

extends — role inheritance

extends: architect

A child role inherits everything from its parent and overrides selectively. Chains are supported (A extends B extends C); cycles are detected at load time and produce a hard error.

Merge rules:

  • model, thinking, description, intercom: child wins if set, else parent value.
  • tools: see the tri-state above. Set overrides; empty disables; absent inherits.
  • Markdown body: parent's body is prepended to child's body with a separator. Useful for "stricter variant" patterns (architect-strict extends architect).
  • name: never inherited — always the child's own filename.

Discovery

Roles are looked up in this order, first match wins for any given name:

| Scope | Path | Marker in /role list | |---|---|---| | project | <repo>/.pi/roles/<name>.md (or any ancestor) | [project] | | user | ~/.pi/agent/roles/<name>.md | [user] | | built-in | bundled with the package | [built-in] |

When a project-scope role shadows a user-scope role of the same name, the user-scope entry is listed under a separate "Shadowed" heading in /role list output so you know it exists but won't load.

The default roleScope is both (project + user + built-in). Override via settings:

// ~/.pi/agent/settings.json
{
  "pi-roles": {
    "roleScope": "both",        // "user" | "project" | "both"
    "defaultRole": "architect", // optional; falls back to role-assistant
    "intercomMode": "off",      // "off" | "receive" | "send" | "both"
    "titleModel": "openai/gpt-4o-mini"
  }
}

Built-in role-assistant

pi-roles ships one built-in role: role-assistant. It's the default fallback when no defaultRole is configured and you don't pass --role or PI_ROLE.

The role-assistant:

  1. Lists the roles available on your machine (project + user + built-in) on its first turn.
  2. Shows the exact command to switch to one (e.g. /role architect).
  3. Offers to help you build a new role: it asks the questions, drafts the markdown, shows it for your approval, writes it to project or user scope (your choice), and then prints the command for you to launch it (/role <new-name> --reset).

You can override the built-in by dropping a role-assistant.md into your project or user roles directory — the same priority rules apply.

You can also set any other role as your default:

{ "pi-roles": { "defaultRole": "architect" } }

If defaultRole points to a missing role, the built-in role-assistant is used and a warning is shown.


Slash command

/role <subcommand> — Tab-completes role names against the current scope.

| Form | Behavior | |---|---| | /role <name> | Switch to <name>. Preserves history. Re-reads the file from disk (no caching). | | /role <name> --reset | Switch to <name> and clear history (equivalent to /new + apply role). | | /role list | List discovered roles with scope markers and shadowing info. | | /role current | Show the currently active role's name, extends chain, description, and source path. | | /role reload | Re-read the currently active role's file from disk and re-apply. Useful while you're iterating on a prompt. |


CLI flag and env var

pi --role architect "Help me design the auth schema"
PI_ROLE=architect pi

Resolution order: --role > PI_ROLE > defaultRole setting > built-in role-assistant.


Session name and footbar

Each session is named <role-name> (and, once the title-generation phase ships, <role-name> — <intent>, where <intent> is a short summary of your first user message). The role-name prefix updates when you /role to a different role.

The session name is set via Pi's native pi.setSessionName() API, so:

  • It shows in Pi's session selector and /resume listings.
  • pi-intercom automatically uses it as the session target — making cross-session messaging work out of the box.

The role indicator also appears in Pi's footer (via ctx.ui.setStatus), composing cleanly with pi-powerline-footer if you have it installed. No extra dependency required.

Title generation model (planned). The titleModel setting is reserved for the future intent-summarization step; it has no effect today. The current release sets the session name to the bare role name and updates the prefix on swap.


pi-intercom integration

pi-intercom is an optional peer dependency. pi-roles works without it; intercom features are no-ops when it's not installed.

When it is installed, the global intercomMode setting controls whether roles get the intercom tool added to their active tool set, plus a small system-prompt addendum telling the LLM how and when to use it:

| Mode | Behavior | |---|---| | off | Default. No intercom tools, no prompt mentions. | | receive | Role can be targeted by other sessions but won't proactively send. | | send | Role can send to other sessions but doesn't expect inbound coordination. | | both | Full bidirectional coordination — intercom tool active, prompt encourages use. |

Per-role override via the intercom: frontmatter field. Common pattern: architect and planner set intercom: both, orchestrator sets intercom: off (you don't want the orchestrator distracted by chatter while it dispatches).

Inter-session messaging is always between named sessions on the same machinepi-roles only opts roles in or out, it doesn't manage the broker, the protocol, or the message store. That's all pi-intercom.


pi-mcp-adapter integration

When pi-mcp-adapter is installed, you can list MCP tools alongside built-ins in the tools field with the mcp:server-name syntax:

tools: read, grep, write, mcp:chrome-devtools, mcp:github

This mirrors pi-subagents's convention exactly, so muscle memory transfers. If pi-mcp-adapter isn't installed, the mcp:* entries are logged and skipped — the role still loads with its built-in tools.

The first time you use a new MCP server, its tool metadata is cold-cached; you may need to restart Pi once for direct MCP tools to become available. This is a pi-mcp-adapter behavior, not something pi-roles controls.


Hot reload

/role reload re-reads the currently active role's file from disk and re-applies it. This is for iterating on a prompt without restarting your session.

/role <name> (without --reset) also always re-reads from disk — there's no hidden cache between switches.

For roles with extends, the entire chain is re-resolved on every load.

If you have Pi's auto-reload feature wired up via /reload, that triggers a full extension reload as well — your role re-applies from scratch.


Settings reference

// ~/.pi/agent/settings.json (global) or .pi/settings.json (project)
{
  "pi-roles": {
    "roleScope": "both",
    "defaultRole": "role-assistant",
    "intercomMode": "off",
    "titleModel": "openai/gpt-4o-mini",
    "warnOnMissingMcp": true
  }
}

| Key | Default | Description | |---|---|---| | roleScope | "both" | Discovery scope. "user", "project", or "both". | | defaultRole | "role-assistant" | Role applied at session start when no --role or PI_ROLE. | | intercomMode | "off" | Default intercom behavior for roles that don't set it explicitly. | | titleModel | null (auto) | Model used for session-intent summarization. Falls back to a small built-in or session's current model. | | warnOnMissingMcp | true | Whether to surface a warning when a role's mcp:* entry can't be resolved. |

Project settings beat global settings, per Pi's standard precedence.


What this extension does not do

  • Spawn sub-agents. That's pi-subagents. The two compose: use pi-roles for top-level session roles, pi-subagents for delegated workers within a role.
  • Define any built-in roles other than role-assistant. Roles are user content; the extension stays small.
  • Manage parallel sessions. Use multiple terminals or tmux. Coordination between parallel sessions is what pi-intercom handles, optionally.
  • Persist which role was active across pi restarts — except via --role / PI_ROLE / defaultRole. By design.
  • Restrict which tools a role can request. If a role lists bash, it gets bash. Permission boundaries are your call — pair with permission-gate.ts or a similar guard if you need them.

Design choices worth knowing

These are decided, not configurable, so the extension behaves predictably:

  • Markdown body fully replaces Pi's default system prompt. No silent merging — most non-coding roles are polluted by the default "expert coding assistant" framing, so by design the role body is authoritative. The handler returns { systemPrompt: <role body> } from before_agent_start and ignores the upstream chain value. If you want to keep Pi's default content (or compose with another extension), include the relevant text in your role body explicitly.
  • Role inheritance: model/thinking override; tools is tri-state (set/empty/absent); markdown body is prepended.
  • Cycle detection in extends is a hard error at load time, not a warning. A circular role is broken; refusing to load it is the only sane behavior.
  • /role <name> always re-reads from disk. No staleness between switches, ever.
  • --reset is explicit. The role-assistant prints the exact --reset command for you to run manually rather than auto-resetting; resetting is destructive enough to deserve a deliberate keystroke.
  • Title generation (planned, not yet implemented). The current release sets the session name to the bare role name; intent-summarization on first user message lands in a follow-up. --reset already clears the cached intent so the future implementation drops in cleanly.
  • Built-in role-assistant lives at the lowest discovery priority. Drop a same-named file in user or project scope to override it.
  • /role list shows shadowed entries with a (shadowed) marker — you can see what would load if the higher-priority file didn't exist.

Layout on disk

After install, your roles live wherever you like — typical setup:

~/.pi/agent/roles/
  architect.md
  planner.md
  orchestrator.md
  marketing-strategist.md
  campaign-manager.md

<repo>/.pi/roles/
  architect.md          # overrides the user one for this project

The extension itself ships only role-assistant.md (built-in scope) and the runtime code.


Examples

See examples/ for two reference role files:

  • architect.md — minimal: just system prompt + model + thinking.
  • orchestrator.md — fully loaded: every frontmatter field, including extends, intercom, MCP tools.

License

MIT. See LICENSE.

Credits

Inspired by and structurally indebted to pi-subagents (frontmatter convention, scope discovery), pi-prompt-template-model (per-trigger model/skill/thinking switching), and the preset.ts example in pi-mono. Thanks to those authors for both the patterns and the working code to learn from.