@ifi/pi-spec
Native spec-kit workflow for pi with a /spec command, TypeScript scaffolding, and spec-driven prompts.
Package details
Install @ifi/pi-spec from npm and Pi will load the resources declared by the package manifest.
$ pi install npm:@ifi/pi-spec- Package
@ifi/pi-spec- Version
0.5.1- Published
- Apr 28, 2026
- Downloads
- 1,857/mo · 644/wk
- Author
- ifiokjr
- License
- MIT
- Types
- extension
- Size
- 155.1 KB
- Dependencies
- 0 dependencies · 5 peers
Pi manifest JSON
{
"extensions": [
"./extension/index.ts"
]
}Security note
Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.
README
@ifi/pi-spec
Native spec-driven workflow for pi, inspired by github/spec-kit.
@ifi/pi-spec is a pi extension package, not a shell wrapper and not a general-purpose JavaScript
library. Its job is to bring the core spec-kit workflow into pi as a native TypeScript experience:
- one
/speccommand instead of a pile of separate commands and shell entrypoints - deterministic local scaffolding under
.specify/ - deterministic feature artifacts under
specs/###-feature-name/ - native git/repo detection, branch naming, and feature numbering in TypeScript
- prompt handoff back into pi via
pi.sendUserMessage(...) - project-owned templates that can be customized locally after initialization
The package deliberately keeps the mental model of spec-kit, but replaces its shell orchestration with normal pi tools and normal pi conversations.
Install
pi install npm:@ifi/pi-spec
Or install the full oh-pi bundle:
npx @ifi/oh-pi
Purpose
The purpose of this package is to make spec-first development feel native inside pi.
In practice that means:
- Requirements come first
- You write or refine a spec before planning and implementation.
- The workflow is explicit
/spec:specify,/spec:plan,/spec:tasks,/spec:implementare separate steps with clear outputs.
- The repository owns the workflow state
- Important artifacts live in normal files in your repo, not in hidden runtime state.
- Pi stays in control of the work
- Instead of calling external shell scripts, pi reads templates, edits files, runs tests, and explains what it did.
- Teams can customize locally
- The package seeds
.specify/templates/, then gets out of the way.
- The package seeds
Goals
The design goals for @ifi/pi-spec are:
- Native pi UX — use pi's existing tools, prompting, and slash-command system
- Spec-kit compatibility of concepts — keep the same major phases and familiar artifact layout
- Type-safe implementation — perform repo detection, path calculation, and branch generation in TypeScript
- Idempotent scaffolding — create missing files without constantly overwriting local customizations
- Low surprise — make state visible through files and
/spec:status - Good defaults, flexible templates — ship usable templates while letting projects evolve them
Non-goals
This package intentionally does not try to be:
- a 1:1 shell-script port of upstream spec-kit internals
- a hidden autonomous pipeline that silently runs every step for you
- a generic npm library with a stable programmatic JS API
- a hook runner that auto-executes
.specify/extensions.ymlscripts behind your back
The stable API surface is the slash command and the on-disk workflow structure.
The API I chose
Public API surface
The package has one primary public entrypoint:
/spec [subcommand] [freeform input]
Supported subcommands:
Canonical /spec subcommands exposed by the extension. Keep README command lists and exported type
metadata in sync with this source of truth: status, help, init, constitution, specify,
clarify, checklist, plan, tasks, analyze, implement, list, and next.
That is the intentional public API.
There is not a separate public JS/TS library API right now. Internal modules like
workspace.ts, scaffold.ts, or prompts.ts are implementation details for contributors, not a versioned
integration surface for consumers.
Core workflow steps:
Workflow steps that hand work back into pi for feature execution. These ordered steps are
constitution, specify, clarify, checklist, plan, tasks, analyze, and implement.
Keep contributor-facing docs aligned with the same sequence.
Why one /spec command is the right API
I chose one command with subcommands instead of many top-level commands like /specify, /clarify,
/plan, /tasks, etc. for a few reasons:
It matches the workflow mental model
- All of these actions are part of one lifecycle.
- Grouping them under
/specmakes that lifecycle obvious.
It avoids namespace clutter in pi
- A spec workflow can easily consume half a dozen top-level slash commands.
/spec ...keeps the command surface organized.
It is easier to discover
/spec:help,/spec:status, and/spec:nextmake the system self-explanatory.- Users only need to remember one root command.
It preserves upstream familiarity without copying the shell UX
- The step names still map cleanly to spec-kit concepts.
- But the runtime behavior is pi-native instead of script-native.
It centralizes context resolution
- Repo detection, active-feature resolution, scaffold creation, and prompt generation all happen in one place.
- That reduces edge cases and keeps behavior consistent.
Why the API is file-centric
The second part of the API is the filesystem contract:
.specify/for reusable workflow state and templatesspecs/###-feature-name/for per-feature artifacts
I think this is the correct design because it keeps the workflow:
- reviewable in git
- easy to inspect manually
- easy to customize
- resilient across agent restarts
- tool-agnostic at the file layer
In other words, the source of truth is not some in-memory session object; it is the repo itself.
Exact command behavior
Below is the practical contract for each subcommand.
| Command | Purpose | Model handoff | Filesystem side effects |
|---|---|---|---|
/spec or /spec:status |
Show current workflow state | No | None |
/spec:help |
Show available commands and guidance | No | None |
/spec:init |
Create the base workflow scaffold | No | Creates missing .specify/ files |
/spec:constitution [principles] |
Create or revise the project constitution | Yes | Ensures base scaffold exists |
/spec:specify <feature description> |
Create the next numbered feature workspace | Yes | Ensures scaffold, creates specs/###-.../, may create/switch git branch |
/spec:clarify [focus] |
Ask and resolve high-impact ambiguities in the active spec | Yes | Ensures scaffold exists |
/spec:checklist [domain] |
Generate or refine requirement-quality checklists | Yes | Ensures scaffold exists |
/spec:plan [technical context] |
Build the implementation plan and design artifacts | Yes | Ensures scaffold, creates plan.md if missing |
/spec:tasks [context] |
Generate an executable tasks.md |
Yes | Ensures scaffold exists |
/spec:analyze [focus] |
Run a read-only consistency review | Yes | Ensures scaffold exists |
/spec:implement [focus] |
Execute tasks and update completion state | Yes | Ensures scaffold exists; prompts if checklists are incomplete |
/spec:list |
List known feature directories | No | None |
/spec:next |
Show the next recommended step | No | None |
Input rules
The command accepts freeform text after the subcommand.
Examples:
/spec:constitution Security-first, testable, low-complexity defaults
/spec:specify Add usage-based billing alerts for workspace admins
/spec:plan Use TypeScript, Vitest, and direct pi tool access
/spec:analyze Focus on contradictions between spec.md and tasks.md
/spec:implement Start with the MVP story and update tasks as you go
Notes:
/spec:specifyeffectively requires a real feature description.- Other workflow steps accept freeform guidance and can also run with minimal or no extra guidance.
- When pi has UI input capabilities available, the extension can prompt for missing input instead of failing immediately.
Active feature resolution
For steps that operate on a feature (clarify, checklist, plan, tasks, analyze, implement), the
extension resolves the active feature using this order:
- current branch name if it matches a numbered feature directory
- a single known feature directory, if there is only one
- a UI selection prompt, if multiple features exist and the UI supports selection
- otherwise the latest numbered feature directory
This keeps the common path simple while still working in multi-feature repos.
Files and directories created by the package
Base workflow scaffold
/spec:init creates the base workflow scaffold if it is missing.
.specify/
├── README.md
├── extensions.yml
├── memory/
│ ├── constitution.md
│ └── pi-agent.md
└── templates/
├── agent-file-template.md
├── checklist-template.md
├── constitution-template.md
├── plan-template.md
├── spec-template.md
├── tasks-template.md
└── commands/
├── analyze.md
├── checklist.md
├── clarify.md
├── constitution.md
├── implement.md
├── plan.md
├── specify.md
└── tasks.md
What these are for:
.specify/README.md— local explanation of the workflow as installed in this repo.specify/extensions.yml— compatibility/config surface; pi inspects it manually when relevant rather than auto-running hooks.specify/memory/constitution.md— canonical governance/principles file.specify/memory/pi-agent.md— pi-native replacement for agent-context update scripts.specify/templates/— local, editable workflow templates copied from the packaged defaults
Per-feature workspace
/spec:specify <description> creates a numbered feature workspace:
specs/
└── 001-my-feature/
├── spec.md
├── checklists/
├── plan.md
├── research.md
├── data-model.md
├── quickstart.md
├── contracts/
└── tasks.md
Not every file exists immediately.
Current behavior:
spec.mdis scaffolded during/spec:specifyplan.mdis scaffolded during/spec:planif it is missing- other files are referenced by the workflow and created as the step needs them
Idempotency rules
Scaffolding is intentionally conservative:
- missing files are created
- existing files are left alone
- bundled templates are copied into the repo once, then become the repo's copies to edit
That is important because the package should seed a workflow, not keep fighting your local customization.
How to use it in practice
1) Initialize the workflow
/spec:init
Use this when introducing the workflow to a repo for the first time.
What happens:
.specify/is created if missing- default templates are copied in
- constitution and pi-agent memory files are created if missing
- a report is rendered in pi explaining what was created
2) Define the project's constitution
/spec:constitution Security-first, testable, backwards-compatible changes by default
Use this to establish the rules the workflow should follow.
Typical outcomes:
- the constitution file is created or updated in
.specify/memory/constitution.md - related templates may be aligned with those rules
- future workflow steps can refer back to the same governance file
3) Create a feature spec
/spec:specify Add SSO login for enterprise tenants
What happens:
- the next feature number is computed
- a branch name is generated from the description
specs/###-feature-name/is createdspec.mdis scaffolded- if git is available and you are not already on that feature branch, the extension creates and switches to it
- pi receives a prompt instructing it to follow the local
specifytemplate using the prepared paths
This is the key step that turns a vague idea into a concrete feature workspace.
4) Clarify open questions
/spec:clarify
or
/spec:clarify Focus on tenant boundaries, auth edge cases, and failure states
This step is meant to remove the highest-impact ambiguities before planning.
5) Generate a requirement-quality checklist
/spec:checklist Authentication quality gates
This is not supposed to generate implementation TODOs. It is meant to verify that the spec is precise, complete, and testable.
6) Build the implementation plan
/spec:plan Use TypeScript, Vitest, and existing auth services; avoid new infrastructure
What happens:
plan.mdis created if missing- pi is instructed to use the local
planworkflow template pi-agent.mdis treated as the pi-native context artifact instead of shell-generated agent files
7) Generate tasks
/spec:tasks
or
/spec:tasks Prioritize the MVP path and keep tasks grouped by user story
This step should produce a tasks.md with a strict checkbox-oriented execution plan.
8) Analyze for contradictions
/spec:analyze
This step is intentionally read-only. It is there to catch inconsistencies between the spec, plan, checklists, and tasks before coding begins.
9) Implement
/spec:implement
or
/spec:implement Start with story 1, update tasks.md as each item completes
Behavior worth knowing:
- checklist files are summarized before implementation
- if incomplete checklist items exist and the UI supports confirmation, pi asks whether you want to continue
- the implementation prompt reminds pi to mark completed tasks as
[x]
10) Inspect progress any time
/spec:status
/spec:next
/spec:list
Use these when you want visibility rather than action:
/spec:statusshows artifact presence, checklist summaries, current branch, and known features/spec:nextrecommends the next workflow command/spec:listlists all numbered feature directories inspecs/
Example end-to-end session
/spec:init
/spec:constitution Security-first, testable, low-complexity defaults
/spec:specify Build a native spec workflow package for pi
/spec:clarify
/spec:checklist Requirements quality for the initial MVP
/spec:plan Use TypeScript, Vitest, and direct pi tool access
/spec:tasks Group work by independently testable user stories
/spec:analyze
/spec:implement
That sequence is the intended happy path.
Native behavior vs upstream spec-kit
This package is inspired by upstream spec-kit, but the runtime model is different on purpose.
What is preserved
- the phase names and overall lifecycle
- the numbered feature directory convention
- the use of templates to guide each phase
- the idea of constitution/spec/plan/tasks/checklist artifacts
What changed
- shell scripts are replaced with TypeScript helpers
- repo/branch/path preparation happens inside the extension
- workflow execution is handed back to pi as a normal prompt-driven task
.specify/memory/pi-agent.mdreplaces agent-update shell behavior.specify/extensions.ymlis preserved as a file, but not auto-executed as hooks
Why this is the correct adaptation for pi
Because pi already has:
- tools for file IO
- tools for running validation commands
- a conversation model for asking clarifying questions
- slash commands for entering workflows
Using shell wrappers would add indirection without adding capability. Native TypeScript makes the workflow:
- easier to test
- easier to reason about
- more portable across environments
- less dependent on shell behavior differences
- more aligned with how pi already works
Internal implementation overview
These modules are useful for contributors, but they are not the promised external API.
extension/index.ts— command registration, dispatch, prompting, and model handoffextension/workspace.ts— repo detection, feature numbering, branch slugging, and path buildingextension/scaffold.ts— idempotent scaffold/template creationextension/prompts.ts— native workflow prompt builder and step-specific notesextension/status.ts— status reporting and checklist summarizationextension/git.ts— minimal git adapter used by the workflowextension/assets/templates/— vendored workflow and file templates adapted from spec-kit
I split the implementation this way because the workflow naturally has four concerns:
- command API and UX
- filesystem/workspace logic
- prompt-generation logic
- status/reporting logic
Keeping those concerns separate made the package easier to test thoroughly.
Customization
After initialization, you can customize the workflow by editing files in your repo:
.specify/memory/constitution.md.specify/memory/pi-agent.md.specify/templates/*.md.specify/templates/commands/*.md
This is another core design choice: the workflow should become your repo's workflow, not remain locked inside the npm package.
Summary
If I had to describe the package in one sentence:
@ifi/pi-specis a native pi implementation of a spec-first workflow whose public API is one/speccommand plus a deterministic.specify/andspecs/###-feature-name/file layout.
I think that is the correct API because it is:
- small enough to remember
- explicit enough to inspect
- compatible enough to feel familiar to spec-kit users
- native enough to feel right inside pi
- testable enough to maintain over time