pi-orbit

Isolated named orbit profiles for Pi coding agent — switch working directory, model, thinking level, tools, env, and skills in one command

Packages

Package details

extension

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

$ pi install npm:pi-orbit
Package
pi-orbit
Version
0.1.0
Published
Aug 28, 2026
Downloads
145/mo · 145/wk
Author
krosskinetic
License
MIT
Types
extension
Size
43.2 KB
Dependencies
0 dependencies · 2 peers
Pi manifest JSON
{
  "extensions": [
    "./extensions/orbit.ts"
  ]
}

Security note

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

README

pi-orbit

Isolated, named orbit profiles for the Pi coding agent. Each orbit bundles a working directory, model, thinking level, active tool set, optional env vars, and an optional skills directory. Switching to an orbit "goes to" its path and activates its profile — a one-command project manager.

Commands

Command What it does
/orbits Interactive picker — lists all orbits (the active one marked) with each orbit's config (model / thinking / tools / skills / env) shown as sub-bullets, and switches to the chosen one
/orbits <name> Switch to orbit name
/orbits default Back to the Default Orbit (no orbit — baseline model / thinking / tools / env)
/add-orbit Interactive wizard — walks through every config.json field (name, cwd, model, thinking, tools, skills, env) and creates the orbit

Plus a startup flag: pi --orbit <name> applies the orbit's profile when Pi launches.

The picker renders each orbit as one line: name (active) — cwd, with the full config shown as indented, muted sub-bullets in the adjacent description column (model:, thinking:, tools:, cwd:, plus skills: / env: keys when set, and any ! config problems). Enter switches, Esc cancels. In non-TUI modes /orbits without an argument prints usage instead.

Orbits vs. the Default Orbit

The default orbit is always available and means "no orbit at all". On a plain boot Pi snapshots the baseline (model / thinking) into .default.json; switching to default restores it. A plain pi (no --orbit) never auto-activates an orbit, even if one was active before.

Behavior on /orbits <name>

  • default — resets to the no-orbit baseline in place and starts a fresh session.
  • Same directory (process.cwd() already equals the orbit's cwd) — applies the profile in place and starts a fresh session.
  • Different directory — cwd is deliberately not switched mid-process (Pi binds it at launch). Instead Pi opens a new Terminal window rooted at the orbit's absolute path running pi --orbit <name>, shuts the current Pi down (its session is auto-saved and recoverable via /resume), and closes the old Terminal window. The new-window behavior uses osascript/Terminal.app and is macOS-only; on other platforms /orbits <name> prints the command to run instead.

Installation

pi install -l .        # local
# or, from a git checkout:
pi install -l ./orbit-project-manager

Once published, install it globally with Pi:

pi install npm:pi-orbit

For just the current project, use pi install -l npm:pi-orbit. Pi discovers the extension through this package's pi.extensions manifest.

Creating an orbit

Orbits live under ~/.pi/agent/orbits/ — one directory per orbit:

~/.pi/agent/orbits/
├── backend/
│   ├── config.json
│   └── skills/          # optional — any dirs listed in `skills`
│       └── my-skill/SKILL.md
├── frontend/
│   └── config.json
├── .active.json         # last orbit switched to (managed by pi-orbit)
├── .current.json        # orbit active in the live process (deleted = Default Orbit)
└── .default.json        # baseline snapshot (managed by pi-orbit)

config.json schema

{
	"name": "backend",
	"cwd": "/abs/path/to/backend",        // required, absolute (or ~/...)
	"model": "provider/model-id",         // e.g. "deepinfra/deepseek-ai/DeepSeek-V4-Flash-0731"
	"thinking": "medium",                 // off|minimal|low|medium|high|xhigh|max
	"tools": ["$ALL$"],                   // "$ALL$" (or omitted) = every tool; else an allowlist
	"skills": ["./skills"],               // relative to the orbit dir, scanned for SKILL.md
	"env": { "KEY": "value" }             // applied to process.env so bash calls see them
}

Notes:

  • model splits on the first slash (model ids may contain slashes).
  • tools — omit, or use ["$ALL$"], to get every tool; any explicit list is an allowlist. Unknown tool names are skipped with a warning.
  • skills directories are scanned for SKILL.md and merged additively with your global and project skills.
  • No context field by design — the fresh session auto-loads AGENTS.md from its working directory, and the orbit's skills supply the rest.
  • Env vars an orbit overwrote are restored when you switch back to the Default Orbit.

Status line

While an orbit is active, Pi's status line shows orbit:<name> (accent-colored when the cwd matches, warning-colored when the orbit targets a different directory).

Development

npm install
npm run typecheck
npm test

The pure logic in src/orbit-scan.ts is unit-tested in test/ without a live Pi runtime.

Package layout

  • extensions/orbit.ts — Pi entry point (flag, hooks, /orbits)
  • src/orbit-paths.ts — state file locations
  • src/orbit-types.ts — shared types + constants
  • src/orbit-scan.ts — config scanning, validation, persistence (pure)
  • src/orbit-runtime.ts — applying profiles to the live Pi process, switching

License

MIT