@nhalm/pi-specd
Spec-driven development workflow for pi
Package details
Install @nhalm/pi-specd from npm and Pi will load the resources declared by the package manifest.
$ pi install npm:@nhalm/pi-specd- Package
@nhalm/pi-specd- Version
1.1.1- Published
- May 4, 2026
- Downloads
- 210/mo · 210/wk
- Author
- nhalm
- License
- unknown
- Types
- extension
- Size
- 173.8 KB
- Dependencies
- 1 dependency · 1 peer
Pi manifest JSON
{
"extensions": [
"./extensions/specd-loop"
]
}Security note
Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.
README
pi-specd
Automates specd workflow iterations in pi. Each iteration runs in a fresh context to avoid context window bloat.
Overview
specd is a spec-driven development framework. You describe what to build, agents implement autonomously, and audits verify against specs. This extension automates the implementation loop in pi.
Quick Start
Install from npm:
pi install npm:@nhalm/pi-specd
Or install from GitHub:
pi install git:github.com/nhalm/pi-specd
Initialize specd in your project:
# In pi, in your project directory
/specd:setup
Existing nhalm/specd projects can migrate instead:
/specd:migrate
Then plan and run the loop:
# Plan (interactive — happens in the parent pi chat)
/specd:plan
# Run the loop (automated)
/specd:loop
# Check status
/specd:status
Concepts
| Concept | File | Purpose | Committed? |
|---|---|---|---|
| Specs | specs/*.md |
What to build (behavior + contracts) | Yes |
| Agent guidelines | AGENTS.md |
How agents should approach the project | Yes |
| Project facts | PROJECT.md |
Build/test commands, conventions | Yes |
| Work queue | specd_work_list.yaml |
Concrete tasks for agents | No (ephemeral) |
| Review queue | specd_review.yaml |
Ambiguous findings awaiting decision | No (ephemeral) |
/specd:setup creates all of the above and adds the ephemeral files to .gitignore.
How a run looks
Each command runs work in a separate sub-agent session — a brand-new pi agent with its own conversation and context. That sub-agent runs to completion and disposes itself; nothing it sees or says leaks back into the parent pi chat unless the extension chooses to surface it.
How that sub-agent's progress is shown depends on whether you're running pi inside tmux.
Inside tmux: live side pane
When pi detects $TMUX, every sub-agent run opens a horizontal side pane (tmux split-window -h) running a small viewer process. That viewer uses pi's own UI components — the same ones pi's interactive mode renders — so the side pane looks exactly like a regular pi chat: tool-call cards, syntax-highlighted code, streaming markdown, the works.
The pane is not just a log. It's interactive:
- Sub-agent activity (every tool call, every assistant message, every thinking block) renders into the pane in real time.
- The pane has its own input box pinned to the bottom. Type into it and press Enter to talk to the sub-agent mid-run — your message gets steered into the running session (interrupting the current turn) or queued as the next prompt if it's between turns. Useful for nudging the agent: "actually skip the changelog removal", "delete that file too", "answer in JSON instead", etc.
- For
/specd:loop, the same pane is reused across all phases — review intake, every implement cycle, audit. Activity history scrolls; you can scroll back through completed cycles. - The parent pi chat stays usable, but typing there talks to the parent agent, not the sub-agent. Cross-pane discipline matters: type into the child pane to steer the child; type into the parent pane for parent-level concerns.
Outside tmux: rolling-log widget
If you're not running pi inside tmux, the side pane isn't available. Instead, the sub-agent's recent activity appears as a multi-line widget above the editor in the parent pi pane: tool calls with their args, file paths, streaming response snippets. The last six entries are kept; older activity scrolls off. You can't steer the sub-agent in this mode — that requires the side pane's input box.
Ctrl+C and abort
While a sub-agent is running, Ctrl+C in the parent pi pane aborts the in-flight sub-agent. The side pane has its own input box, but it isn't wired to abort — Ctrl+C typed inside the side pane is just keyboard input destined for that input box. (Escape used to be an abort key as well; it was removed.)
- For
/specd:migrate, an abort tears the side pane down immediately and cancels the migration. - For
/specd:loop, an abort stops the current phase and pi shows a confirm dialog: Continue with the loop? Choosing yes moves on to the next phase (next cycle, audit, etc.); choosing no ends the loop entirely. This lets you skip a stuck implement cycle without scrapping the whole loop.
When a sub-agent finishes
/specd:migrate:
- Side pane closes.
- The sub-agent's structured summary (files modified / created / deleted / caveats / technical notes) is handed to the parent pi agent via a hidden trigger message. The parent agent then relays the summary to you in its own voice in the main pi chat. The trigger itself is not displayed; you only see the parent's response.
/specd:loop:
- Pane stays open after the loop completes (audit included), so you can scroll back through everything that happened. When a run finishes cleanly, the parent sends a
specd:donecontrol event and the pane renders a "complete — close pane to dismiss" banner; the pane stays open until you close it. A 5-minute fallback fires if the parent crashes without sendingspecd:done. - Final status appears in the main pi chat.
Sub-agent tool surface
Sub-agents are restricted to the standard built-in tools: read, bash, edit, write. Extension tools that pi may have loaded for the parent (e.g. @mjakl/pi-subagent's subagent) are intentionally hidden from the sub-agent so it doesn't try to delegate to agents that aren't configured in its context.
Commands
/specd:setup
Initialize specd in a new project. Detects build/test commands and conventions.
/specd:migrate
Migrate an existing nhalm/specd project to specd-loop format (removes spec versions, status lifecycle, and changelogs). Runs in a sub-agent. After it finishes, the parent pi agent delivers a summary in chat. Tmux side pane is interactive while it runs.
/specd:plan
Interactive planning. Runs in the parent pi session itself, not in a sub-agent — the planning brief is injected as a user message and pi takes a turn, asking clarifying questions, writing specs, and updating specd_work_list.yaml. There's no side pane for plan.
/specd:loop [options]
Run the full automated loop: review intake → implement (looped) → audit. Each phase runs as its own sub-agent (fresh context per phase / per cycle). One side pane is reused for all phases.
| Option | Description |
|---|---|
--skip-audit |
Skip the audit phase |
--max-cycles=N |
Override max implement iterations (default: 5) |
- Halt on no-commit: if an implement cycle finishes but the agent didn't land a new commit (verified via
git rev-list HEAD ^${headBefore} --count≥ 1, which also rejects an--amendof the previous commit), the loop halts entirely — it does not skip the item. The work item stays incomplete and the loop surfaces a recovery message pointing atgit status, blocked hooks, and the per-phase transcript path. Re-run/specd:loopto retry.
/specd:status
Show the work list: ready items, blocked items, pending reviews, and the next action to take.
Review items
Any of the three loop phases — review intake, implement, or audit — can produce a finding when it hits an ambiguous situation. When that happens the loop pauses and surfaces the finding. Edit specd_review.yaml and add a decision: field to each finding. The path to the file is printed when the loop pauses.
Common decisions:
Fix the code→ adds a work item to fix the codeUpdate the spec→ updates the spec, then adds a work itemIgnore→ deletes the finding, no actionKeep as is→ deletes the finding, code is correct
When you run /specd:loop again, the review intake interprets your decisions and updates accordingly.
Requirements
- pi (
@mariozechner/pi-coding-agent) installed and configured. - The working directory must contain
AGENTS.md,PROJECT.md, andspecs/README.md./specd:setupcreates all three. - For the side-pane viewer experience, pi must be running inside a tmux session. Otherwise the rolling-log widget fallback is used (no in-flight steering).
Troubleshooting
- "Cannot verify commits: this directory is not a git repository" — the loop verifies progress via
git rev-list, so the project must be a git repo. Rungit init(and make at least one commit) before re-running/specd:loop. - Cycle ended without a commit — the loop halts and surfaces a recovery hint. Check
git statusfor leftover staged or unstaged changes; check whether apre-commit/commit-msghook blocked the commit; and read the full transcript at the path printed in the recovery message. Fix the underlying issue, then re-run/specd:loopto pick up the same item. - Spec file missing — a work item references
specs/<name>.mdbut the file doesn't exist. Run/specd:planto (re)create the spec, or remove the work item fromspecd_work_list.yaml. - Version-mismatch warning at preflight — the project's
.pi-specdfile records a different extension version than the installed extension. Re-run/specd:setupto refresh the marker (and pick up any new template behavior). - Per-phase log files — every phase (review intake, each implement cycle, audit) writes its full transcript to
${TMPDIR}/specd-loop/<phase>-<timestamp>.log(on macOS,TMPDIRis something like/var/folders/.../T; on Linux it's typically/tmp). The loop prints the exact path when it surfaces an error, but they're useful for any post-hoc investigation. - Sub-agent crash diagnostics — set
SPECD_DEBUG=1(e.g.SPECD_DEBUG=1 pi) to also write any sub-agent unhandled rejection or uncaught exception to${TMPDIR}/specd-debug.log. Off by default so normal runs don't leave files in/tmp. - Pinning a sub-agent model — set
SPECD_MODEL=<model-id>before launching pi to override the inherited model. Example:SPECD_MODEL=claude-sonnet-4-6 pi. Useful for deterministic loops. Accepts a bare model id or canonicalprovider/modelId. If the reference is empty or doesn't unambiguously match a configured model, sub-agents fall back to pi's currently-configured model. - Loop crashed mid-cycle — when
/specd:loopnext runs, it'll detect the crash and ask whether to resume. Saying yes finishes the cycle (marks the in-flight item complete and continues with the next); saying no discards the checkpoint and starts fresh. The checkpoint lives at.specd-loop-checkpoint.json(gitignored).
License
MIT