pi-soly

Project management + workflow framework for pi-coding-agent. Plans, state, MANDATORY rules, self-review, multi-question picker, native footer + welcome chrome — one npm install, zero config. The LLM drives the workflow inline via the soly_workflow tool —

Packages

Package details

extensionskill

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

$ pi install npm:pi-soly
Package
pi-soly
Version
2.2.1
Published
Jul 8, 2026
Downloads
9,532/mo · 2,458/wk
Author
lowern1ght
License
MIT
Types
extension, skill
Size
1.9 MB
Dependencies
7 dependencies · 2 peers
Pi manifest JSON
{
  "extensions": [
    "./index.ts"
  ],
  "skills": [
    "./skills"
  ]
}

Security note

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

README

⚡ pi-soly

The project management + workflow engine for pi-coding-agent.

Plans · State · Rules · Multi-question picker. One npm install. Zero config.

npm version npm downloads CI License: MIT Built with Bun

Install · Commands · Rules & Docs · Architecture · Releases


⚡ Install

pi install npm:pi-soly

Restart pi (/reload), and you have:

  • Project management — plans, state, phases, decisions
  • Workflow engine — runs inline (no subagent plugin). The model proposes the next step and drives it via the soly_workflow tool on your plain-language intent; the verbs soly discuss · plan · execute · verify · pause/resume still work as text
  • Self-review loopsoly verify re-reviews the work until "No issues found."
  • Goal-aware verification — at the end of every soly execute (task / plan / phase plan-level), the worker reads PLAN.md's ## Goal + ## Acceptance and judges each item against git diff. A ## Status section is appended to PLAN.md with a PASS / BLOCKED verdict. On BLOCKED the worker halts before calling soly done — so you can't ship a plan whose goal isn't actually met.
  • Visual chrome — native footer, equalizer working spinner with live telemetry, gradient welcome banner
  • Rules & docs modal/rules and /docs open a fuzzy list + preview panel (no chat dumps)
  • Mandatory rules — strict-mode directives injected every turn
  • Multi-question pickerask_pro tool for the LLM (single/multi-select, free-text, skip)
  • Decision deckdecision_deck tool: full-screen TUI cards for comparing design options by code shape
  • HTML artifactshtml_artifact tool serves self-contained HTML from a per-session browser gallery (live-updating, one stable URL)
  • Skill-based execution — LLM reads the soly-framework skill on demand

The LLM drives execution inline, in the main session — no external subagent plugin. Say what you want in plain language ("let's plan this", "start executing") and the model calls the first-party soly_workflow tool for you; the soly <verb> text form still works as a fallback. You focus on the work.

Known install issue (upstream pi install)

pi install currently does not install transitive peerDependencies (it skips them the way --omit=optional would). pi-soly's MCP stack depends on @modelcontextprotocol/ext-apps, which in turn peer-requires @modelcontextprotocol/sdk (declared non-optional upstream). After pi install npm:pi-soly you may see:

Error: Cannot find module '@modelcontextprotocol/sdk/types.js'
Require stack:
- ~/.pi/agent/npm/node_modules/@modelcontextprotocol/ext-apps/dist/src/app-bridge.js

Workaround (one-time, after each pi install of pi-soly or any pi-soly-related upgrade):

cd ~/.pi/agent/npm && npm install

This makes plain npm resolve the transitive peer deps that pi install skipped. After this, restart pi (/reload) and the MCP features work.

Tracked upstream — fix is expected on the pi side, not here.


🎯 Why pi-soly?

Without pi-soly With pi-soly
Re-invent plan/state/resume from scratch /plan, /execute, /resume, /inspect ready
Forget rules mid-session ## ⚠️ MANDATORY header in every system prompt
Wonder which rules eat context /rules stats — Claude-memory-style breakdown
Wonder which docs eat context /docs stats — same for intent docs
Ask the LLM the same clarifying question 5 times ask_pro multi-question picker

📋 Commands

Workflow — plain-text verbs (type soly <verb>, not slash)

# === Plan mode (recommended for new work — each plan is a git branch) ===
soly new feat/auth-jwt       # create branch + .agents/plans/<name>/ + stub PLAN.md
soly discuss feat/auth-jwt   # interactive discussion of the plan
soly plan feat/auth-jwt      # flesh out PLAN.md via ask_pro
soly execute feat/auth-jwt   # execute the plan inline in this session
soly done feat/auth-jwt      # commit, push, open draft PR via gh
soly verify                  # self-review loop until "No issues found." (soly verify stop to exit)
soly pause                   # save a handoff; soly resume to pick it back up
soly status                  # current position + progress (no LLM round-trip)

# === Phase mode (legacy — still works for existing projects) ===
soly plan 3                  # generate PLAN.md for phase 3 (numeric form)
soly execute 3               # execute phase 3 (or `soly execute 3.02` for one plan)
soly migrate phases-to-plans # one-shot: import each .agents/phases/<NN>-slug/plans/PLAN.md
                             #   as a `migrate/legacy-<NN>-slug` branch with .agents/plans/legacy-<NN>-slug/PLAN.md

Why plans instead of phases? A global phase counter (1, 2, 3, ...) means two developers each starting a "phase 11" write to the same path. With plans, each is a git branch (feat/auth-jwt, fix/login-redirect, …) with its own .agents/plans/<name>/PLAN.md — no collisions, clean isolation, and the branch list itself is the registry of what's in flight.

State inspection (/soly)

/soly              # interactive modal picker (live preview per item, ⏎ to open)
/soly position     # where am I in the plan
/soly state        # current STATE.md content
/soly roadmap      # all phases
/soly progress     # phases/plans/tasks done vs total
/soly phases       # list phases
/soly plan [N]     # show plan for phase N

Rules & Docs

/rules             # interactive list
/rules stats       # context breakdown (always-on vs glob-matched)
/rules analytics   # token analytics + warnings + duplicates
/rules show <name> # show rule body
/rules reload      # re-read all rules
/rules enable <name> / disable <name>

/docs stats        # context breakdown (inline vs preview vs phase-specific)

Setup

/soly init                # scaffold .agents/ (templates: minimal|web-app|library|cli)
/soly-status              # one-screen health report
/soly-log                 # recent notifications

Debug

/why              # rules + project state that grounded the last turn
/rulewizard       # interactive guide: rule vs .editorconfig vs linter

🧠 Rules & Docs

Two system-prompt injections, both opt-in and fully observable.

Rules — .agents/rules/ or ~/.agents/rules/

Markdown files with frontmatter. Three modes:

---
description: TypeScript code style
always: true            # loaded every turn
---

Always use `strict` mode. Never use `any`...
---
description: React component rules
globs: ["**/*.tsx", "**/*.jsx"]   # loaded only when prompt mentions matching file
---

Hooks only at top level. Use memo only for expensive renders...

System prompt injection (every turn, after before_agent_start):

## ⚠️ MANDATORY: soly project rules

**These rules are NON-NEGOTIABLE. Before writing or editing ANY code,
re-read the rules above that apply to the file path you are about to
modify. If a rule contradicts your instinct, the rule wins.**

See context breakdown anytime: /rules stats.

Docs — .agents/docs/ or ~/.agents/docs/

Zero-point intent docs (your vision, business context). Loaded as preview only (180 chars per doc) — cheap. Add inline: true to opt-in to full body injection.

---
title: Core principles
inline: true     # full body loaded every turn (expensive!)
---

Our core principles are...

See context breakdown: /docs stats.


🎤 Multi-Question Picker

ask_pro tool for the LLM. Tabbed UI: single-select, multi-select, recommended ⭐, free-text Other.

ask_pro({
  questions: [{
    header: "Auth",
    question: "How should we store the OAuth refresh token?",
    options: [
      { label: "Encrypted in SQLite",  description: "Survives restart, single-device.", recommended: true },
      { label: "OS keychain",          description: "Native, multi-device via iCloud." },
      { label: "Plain env var",         description: "Simplest, dev only." }
    ]
  }]
})

The LLM calls ask_pro when it needs structured input. Tab through questions, pick ⭐ options, confirm. Per-option preview shows a side panel (fenced code is syntax-highlighted); freeText: true makes a typed-answer question; multi-select takes minSelect/maxSelect; press s to skip a question.


🃏 Decision Deck

decision_deck tool for the LLM. A full-screen TUI deck — one framed card per option, each with a syntax-highlighted code snippet and pros/cons — for design/architecture forks where the choice hinges on seeing the concrete shape, not a label.

decision_deck({
  title: "State management",
  prompt: "How should modules communicate?",
  options: [
    { title: "Direct calls", summary: "Call modules directly.", pros: ["simple"], cons: ["coupling"] },
    { title: "Event bus", code: "const bus = new Bus()\nbus.emit('x')", lang: "ts",
      pros: ["decoupled"], cons: ["harder to trace"], recommended: true }
  ]
})

Flip cards with ←/→ (or 1-N), choose with Enter, Esc to cancel. Native TUI — no browser, no server.


🖼 HTML Artifacts

html_artifact tool for the LLM — soly's local "artifacts". Renders HTML (a full document or just body content, themed light/dark) and serves it from a per-session gallery SPA — a sidebar of every artifact this session, an iframe viewer, a filter box, a light/dark toggle, and live SSE updates — on one stable localhost URL, opened in your browser. Pass id to update an artifact in place; pass assets to write sibling files (images/css/json) the HTML references; restyle everything via .agents/artifact-theme.css. (Falls back to opening the file directly if the server is disabled.)

html_artifact({
  title: "API examples",
  html: "<h2>Usage</h2><pre><code>client.send(msg)</code></pre>"
})

Use it when a visual, rendered result beats terminal text (example galleries, comparisons, diagrams). The gallery URL lives only while the pi session runs. /artifacts reopens the gallery anytime (modal: Enter opens an artifact, g the gallery, x delete, /artifacts clear clears); a ▦ N footer indicator shows the live count. Config under artifacts (open, dir, server, theme, retentionDays).


🏗 Architecture

┌──────────────────────────────────────────────────────────────┐
│                   pi-coding-agent (peer dep)                 │
└────────────────────────┬─────────────────────────────────────┘
                         │
        ┌────────────────┴────────────────┐
        ▼                                 ▼
  ┌────────────┐                  ┌─────────────┐
  │  ask_pro   │                  │  soly_read  │
  │  picker    │                  │  soly_log_  │
  │  (tool)    │                  │  decision   │
  └────────────┘                  └─────────────┘
        │                                 │
        └─────────────────┬───────────────┘
                          │
                          ▼
                ┌──────────────────┐
                │  Workflow engine │
                │                  │
                │  /plan /execute  │
                │  /resume /inspect│
                │  /discuss /quick │
                │  /soly /why      │
                │  /rules /docs    │
                └────────┬─────────┘
                         │
            ┌────────────┼────────────┐
            ▼            ▼            ▼
       .agents/STATE  phases/<N>/   rules/
       (current     CONTEXT,      docs/
        position)   PLAN,         (system
                    RESEARCH)     prompt)
                         │
                         ▼
                ┌──────────────────┐
                │  soly-framework  │
                │  SKILL.md        │
                │                  │
                │  LLM loads on    │
                │  demand \u2014 no  │
                │  subagent layer  │
                └──────────────────┘

State lives in .agents/ — portable, git-friendly, human-readable. (Projects from before the rename used .soly/; soly no longer reads it — run mv .soly .agents.)

.agents/
├── ROADMAP.md           # phase table
├── STATE.md             # current position + decisions log
├── docs/                # 0-point intent docs (preview-loaded)
├── rules/               # rules (glob-matched or always-on)
└── phases/
    └── 01-foundation/
        ├── 01-CONTEXT.md       # domain + decisions for this phase
        ├── 01-RESEARCH.md      # what we looked up
        └── tasks/              # unified model: one dir per task
            └── auth-login-a3f9/
                ├── PLAN.md     # frontmatter: id, kind, status, depends-on
                └── SUMMARY.md

Legacy projects (standalone NN-MM-PLAN.md files / a features/ dir) still load and run alongside the unified phases/<N>/tasks/ layout.


📚 Events

Event When What we do
session_start session opens Install soly-framework skill, build initial state
before_agent_start every turn Inject rules + docs sections into system prompt
tool_call (edit/write) LLM edits file Track edited files (silent — used by /why)
turn_end turn finishes Refresh rules/state, hot-reload changes
session_shutdown session closes Flush iterators, cleanup

🛠 Development

Requirements

Setup

git clone https://github.com/lowern1ght/pi-soly.git
cd pi-soly
bun install

Test + typecheck

bun test          # run the test suite
bun run typecheck # tsc --noEmit
bun run ci        # both

Live-reload in pi

pi install ./packages/pi-soly
# edit files → /reload in pi to pick up changes

🚢 Releases

Tag-based, fully automated. Push a pi-soly-v* tag, get a publish.

./scripts/release.sh pi-soly 1.9.1
git push github master
git push github pi-soly-v1.9.1 --force

CI runs on a self-hosted GitHub Actions runner:

Trigger Job Action
Push to master test bun install + bun test + bun run typecheck
PR to master test same
Push tag pi-soly-v* testpublish tests + npm publish to npmjs

The publish job uses GitHub Environment npm-publish so NPM_TOKEN is only exposed during the publish step. Zero secrets in workflow YAML.


🤝 Compatibility

  • pi-coding-agent ≥ 0.78
  • Node ≥ 20 (pre-installed on the runner)
  • Bun ≥ 1.3 (pre-installed on the runner)
  • OS — Linux, macOS, Windows (anywhere Bun runs)

📜 License

MIT — see LICENSE.


Built by @lowern1ght · Powered by pi + Bun

⭐ Star on GitHub · 📦 View on npm · 🐛 Report a bug