Agent Plan is a local, project-scoped planning platform for AI coding agents.
It gives a project a structured planning workspace in .planner/, then exposes that workspace through multiple surfaces:
- a core TypeScript library (
@agent-plan/core); - a local HTTP/WebSocket server and React dashboard;
- a Pi adapter with a grouped
/planner ...command; - a Claude Code MCP server with
planner-*tools; - a Claude Code
/planner ...slash command router; - a CLI (
agent-plan) for setup, MCP startup, and project initialization.
The goal is to make planning durable, inspectable, and shared across agents without coupling the core planning model to any one harness.
This project is under active development.
Current focus:
- Pi integration is available through a grouped
/plannercommand. - Claude Code integration is available both as a self-hosted plugin (marketplace) and via MCP + a generated
/plannerslash command. - The canonical project data directory is
.planner/. - Agent Plan intentionally does not read, migrate, or use
.plan/; that directory belongs to other tools such as GSD/get-shit-done.
Agent Plan stores structured planning data in the target project:
my-project/
.planner/
manifest.json
project.json
features.json
requirements.json
phases/
<phase-id>.json
resume.json
handoff-archive/
generated/
PLAN.md
features/
phases/
JSON files are the source of truth. Markdown files under .planner/generated/ are generated views for humans and agents.
The public planning hierarchy is:
project → features → phases → tasks
Requirements currently exist as internal/project seed data and are not exposed as public Claude Code commands in Phase 1.
The core planning model lives outside Pi, Claude Code, or any other harness. Adapters should call shared planning logic rather than owning business rules.
Each agent session (a Claude Code or Codex MCP connection, a Pi session) keeps its own focus:
- Tasks: a task in progress belongs to the session that started it.
- Side tasks: when a session switches to a temporary task (
task_switch,task_deviation), the task to return to is recorded for that session only. Another session's recommendation never saysRESUME REQUIREDfor it and never offers the set-aside task, so one agent's detour does not become another agent's order. - Resume focus: each session has its own current phase, in-progress tasks, next steps and notes (
.planner/.local/resume-sessions.json, the 20 most recent sessions are kept). A session that has none yet starts from the project-level focus. The guard bypass stays project-wide.
A caller with no session (the web UI, scripts) sees the whole project, as before. Work recorded before sessions were tracked is shown to every session. A checkpointed task that no live side task points at is still offered to every session, so paused work is not lost.
Task starts claim ownership atomically. Repeating a start succeeds only for the
owning caller; another caller gets started: false with
TASK_OWNED_BY_ANOTHER_SESSION. A stdio MCP restart creates a new caller identity.
After confirming the previous caller has stopped, use planner-session-recover
with { task: "P001(F001)/T001", confirmed: true } (Pi: session_recover with
taskId). The task can be the old active task or a pending return task. Recovery
transfers the old caller's owned tasks, complete deviation stack and saved focus
into the fresh caller without changing task statuses or checkpoints. Read context
and call task-start normally afterward. No client-side owner-ID mapping is needed.
Recovery refuses a registered process that is still alive, a process on another
host whose exit cannot be checked, or a destination caller that already owns work.
Older releases have no process record; for those sessions, explicit confirmation
is the operator's assertion that the old caller has stopped. This operation is
available through MCP/Pi and the core; the read-only /api/v1 remains unchanged.
docs/setup-claude-code.md— Claude Code MCP + slash-command setup.docs/setup-codex.md— Codex MCP + skill setup.docs/setup-opencode.md— OpenCode MCP +/plannercommand setup.docs/setup-zed.md— Zed MCP setup (custom context server, no extension required).docs/planner-schema.json— public JSON schema for the.planner/workspace (generated from@agent-plan/coreZod schemas).docs/api-v1.md— stable, versioned read API and liveentity-changedevents for programs outside Agent Plan.AGENTS.md— operational rules for agents working on Agent Plan itself.
Agent Plan is distributed to AI coding harnesses through a self-hosted plugin marketplace. Plugins are static bundles (JSON + Markdown + shell scripts) living in the top-level plugins/ directory, separate from the npm packages in packages/.
A plugin does not reimplement planning logic. It wires a harness to the shared planning core (@agent-plan/mcp, the MCP stdio server, backed by @agent-plan/core) and provides harness-specific integration: command/skill routing where the harness supports it, lifecycle notifications where available, and the MCP server declaration.
plugins/
claude-code/ Claude Code plugin (ready)
.claude-plugin/plugin.json plugin manifest
.mcp.json @agent-plan/mcp stdio server (npx)
skills/planner/SKILL.md /planner routing (derived from _shared/)
hooks/hooks.json SessionStart non-blocking notify
scripts/notify-session-start.sh
codex/ Codex plugin (ready: MCP + skill)
plugin.json portable Agent Plugins manifest
.codex-plugin/plugin.json Codex compatibility manifest
mcp.json / .mcp.json @agent-plan/mcp stdio server (npx)
skills/agent-plan/SKILL.md Agent Plan skill (derived)
skills/planner/SKILL.md $planner alias skill (derived)
opencode/ OpenCode bundle (ready: MCP + commands)
skills/agent-plan/SKILL.md Agent Plan skill/guide (derived)
_shared/ single-source-of-truth templates
planner-skill.md.in
notify-session-start.sh.in
.claude-plugin/marketplace.json marketplace catalog (repo root, per Claude Code spec)
.agents/plugins/marketplace.json Codex marketplace catalog (repo root)
Per-harness behavior:
- The planner is disabled by default; nothing auto-starts.
/planner load— enable the planner, start the web dashboard (LAN-bound, dynamic port), emit a recap (status + handoff + Web UI address)./planner stop(alias/planner disable) — disable the planner and stop the web.- The Web UI address is shown only on the
loadrecap or via/planner web status— never appended to every message. - Planner operations (handoff, plan CRUD) are not code edits and are always allowed regardless of task state.
- Claude Code and OpenCode support
/plannerrouting. OpenCode also installs flat autosuggest shortcuts such as/planner-loadand/planner-task-start. - Codex currently exposes Agent Plan through MCP tools and the
agent-plan/plannerskills ($plannerappears in the Codex skill picker); custom/planner ...slash-command registration is not part of the public Codex plugin/config surface.
/plugin marketplace add ovidius72/agent-planner
/plugin install agent-plan@agent-plan-marketplace
The CLI setup below installs the Codex marketplace plugin automatically at user
scope when the codex CLI is available. Manual equivalent:
codex plugin marketplace add https://github.com/ovidius72/agent-planner \
--ref main \
--sparse .agents/plugins \
--sparse plugins/codex
codex plugin add agent-plan@agent-planThe plugin version is bumped by the release scripts together with the npm packages — pnpm release for the stable channel and pnpm release:next for the next prerelease channel (the plugin has its own version track, independent from the npm package versions). The Claude Code plugin manifests, Codex plugin manifests, .claude-plugin/marketplace.json, and .agents/plugins/marketplace.json are updated, so marketplace clients detect the new version and refresh the plugin files. The MCP server auto-updates independently because plugin MCP declarations run npx -y @agent-plan/mcp, which fetches the latest published @agent-plan/mcp from npm.
As a user — after a new release is merged to main, refresh in Claude Code:
/plugin marketplace update
Then restart Claude Code in the project so the MCP server re-launches with the new @agent-plan/mcp.
For Codex, run:
agent-plan setup codex --user --forceThen restart Codex and verify with planner-version. If the planner web UI is
missing recently released dashboard sections, the active MCP process is usually
stale; planner-version shows the version Codex actually loaded.
As a maintainer — run the release script for the target channel (pnpm release for stable, pnpm release:next for next). It bumps the plugin versions in the Claude Code and Codex plugin manifests plus both marketplace catalogs. Do not edit the version fields by hand: the scripts own them, and an unchanged pinned version can make marketplace clients report "already at the latest" and skip the refresh.
claude --plugin-dir ./plugins/claude-code --debugOr add the repo itself as a local marketplace:
/plugin marketplace add ./
/plugin install agent-plan@agent-plan-marketplace
- Add a subdirectory under
plugins/<harness>/with the harness manifest/config files, MCP wiring, andskills/. - Add an entry to the
HARNESSEStable inscripts/sync-plugins.cjs. - Edit the templates in
plugins/_shared/(never edit derived files directly). - Run
pnpm plugins:syncto regenerate derived files (pnpm plugins:checkfor the CI drift guard).
See plugins/README.md and plugins/DECISIONS.md for the full design and decision record.
Prefer the plugin — the self-hosted marketplace plugin (see Plugins above) is now the recommended install path:
/plugin marketplace add ovidius72/agent-plannerthen/plugin install agent-plan@agent-plan-marketplace. The CLI-based setup below remains a valid manual alternative and is still used to register the MCP server, slash command, and write guard hook at user/project scope.
After publication, the intended installation is:
npm install -g agent-planThen configure Claude Code once at user scope:
agent-plan setup claude-code --userThis does three things:
- registers the Agent Plan MCP server in Claude Code user scope;
- writes the Claude Code slash command router:
~/.claude/commands/planner.md
- installs a Claude Code
PreToolUsetask guard hook in:
~/.claude/settings.json
After this, /planner ... is available from Claude Code projects and implementation tools are guarded when a project has an active .planner/.
Open a project with Claude Code:
cd my-project
claudeThen initialize planning explicitly:
/planner init
This creates:
my-project/.planner/
If a project is not initialized, Agent Plan tools should report that .planner/ is missing and suggest /planner init.
Claude Code supports a slash command /planner ... that routes natural command text to the underlying MCP tools.
/planner init— Initialize planner/planner show— Show planner overview/planner repair— Repair planner integrity/planner load— Re-enable planner/planner disable— Disable planner for this session
/planner project discuss— Run project discovery/planner project language— Set persistent language preferences
/planner feature list— List features/planner feature add <name>— Create a feature/planner feature show <id>— Show a feature/planner feature update <id>— Update a feature/planner feature delete <id>— Delete a feature
/planner phase list— List phases/planner phase add <title>— Add a phase/planner phase show <id>— Show a phase/planner phase discuss <id>— Discuss a phase/planner phase update <id>— Update a phase/planner phase delete <id>— Delete a phase
/planner task list— List tasks/planner task add <title>— Add a task/planner task show <id>— Show a task/planner task discuss <id>— Discuss a task/planner task update <id>— Update a task/planner task delete <id>— Delete a task/planner task start <id>— Mark a task in-progress/planner task complete <id>— Mark a task done
/planner handoff list— List phases with a handoff/planner handoff prepare— Tell the agent to create/update the handoff/planner handoff show— Show the current handoff/planner handoff write— Write handoff from planner data/planner handoff clear— Delete the current handoff
/planner export— Export plan summary as Markdown/planner export-full— Export full detailed plan as Markdown/planner web start|stop|status— Manage the web UI
/planner bypass— Authorize edit/write without a task (15 min)/planner clear-bypass— Revoke the bypass
The MCP server exposes public tools using the planner-* namespace. These tools are called by AI agents (Claude Code, Codex, Zed, OpenCode), not by humans. Human users should use /planner ... where the harness supports custom commands (Claude Code and OpenCode), or the agent-plan skill / natural-language planner requests in Codex.
Current Phase 1 tools include:
planner-initplanner-showplanner-description-freshness— non-mutating child-to-parent drift preview with exact stale refsplanner-repairplanner-loadplanner-disableplanner-web
planner-project-discussplanner-project-language
planner-feature-listplanner-feature-addplanner-feature-showplanner-feature-updateplanner-feature-delete
planner-phase-listplanner-phase-addplanner-phase-showplanner-phase-discussplanner-phase-updateplanner-phase-delete
planner-task-listplanner-task-addplanner-task-checklist-add(append one step; next C{n}, stable id)planner-task-checklist-remove(remove one step by C{n}/id/title; renumber C1..Cn)planner-task-checklist-toggle(tick/untick a step by C{n}/id/title; no list rewrite)planner-task-showplanner-task-discussplanner-task-updateplanner-task-deleteplanner-task-startplanner-task-complete
planner-handoff-listplanner-handoff-prepareplanner-handoff-showplanner-handoff-writeplanner-handoff-verifyplanner-handoff-clear
planner-handoff-list indexes active handoffs. planner-handoff-show <phaseRef> also recovers the latest terminal archive after a phase becomes done, rejected, or canceled, preserving discoverability of closeout content and linked .planner/docs/ references.
planner-export(with optionalfullboolean for detailed hierarchical output)
planner-authorize-bypass(temporary bypass so Edit/Write work without a task in-progress)planner-clear-bypass
Requirements are intentionally not exposed as planner-requirement-* in Phase 1.
The current Phase 1 count is 38 public planner-* tools.
Use this once per machine/user:
agent-plan setup claude-code --userThis keeps the MCP server and slash command available across projects.
It does not create .planner/ in any project.
Use this when you want a repository-local Claude Code configuration, for example for a team, a pinned version, or local development:
agent-plan setup claude-code --projectThis creates or updates:
.mcp.json
.claude/commands/planner.md
.claude/settings.json
The settings file contains a Claude Code PreToolUse hook for Edit|Write and the shared guard-bypass flow.
Example .mcp.json:
{
"mcpServers": {
"agent-plan": {
"command": "npx",
"args": ["agent-plan", "mcp"]
}
}
}Project-local setup also does not initialize .planner/. Run /planner init when you want planning enabled in that repo.
Install Agent Plan globally from npm:
npm install -g agent-planThen configure Codex once at user scope:
agent-plan setup codex --user --forceUse --force when repairing an existing Codex install. It rewrites the
agent-plan MCP entry and removes legacy per-tool approval tables such as
[mcp_servers.agent-plan.tools.planner-task-recommend], which can otherwise
make Codex ask for permission on every planner tool call.
For a single project, run this inside that project instead:
agent-plan setup codex --project --forceThis writes Codex MCP configuration to .codex/config.toml or
~/.codex/config.toml, installs the agent-plan and planner skills, and for
user scope registers/installs the Codex marketplace plugin when the codex CLI is
available. Use --local only when testing an unpublished checkout build; in
that mode the Codex marketplace source is the local repository checkout.
Restart Codex after setup so already-running sessions reload the Agent Plan MCP
process. Verify the runtime from inside Codex with planner-version; the loaded
@agent-plan/mcp version should match the released npm version you expect.
Install Agent Plan globally from npm:
npm install -g agent-planThen configure OpenCode once at user scope:
agent-plan setup opencode --user --forceFor a single project, run this inside that project instead:
agent-plan setup opencode --project --forceThis writes OpenCode MCP configuration plus /planner command routing under
OpenCode's command configuration key.
OpenCode also gets flat shortcut aliases such as /planner-load,
/planner-task-start, and /planner-web-start for command-list discovery.
The generated command templates are compact and do not paste the full planner
guide on every invocation. Use --local only when testing an unpublished
checkout build.
For unpublished local changes, use the built local CLI:
pnpm --filter @agent-plan/core build
pnpm --filter @agent-plan/server build
pnpm --filter @agent-plan/mcp build
pnpm --filter agent-plan buildProject-local local setup:
node /Users/antonio/projects/agent-plan/packages/agent-plan/dist/index.js setup claude-code --project --local
node /Users/antonio/projects/agent-plan/packages/agent-plan/dist/index.js setup codex --project --local
node /Users/antonio/projects/agent-plan/packages/agent-plan/dist/index.js setup opencode --project --localUser-scope local setup:
node /Users/antonio/projects/agent-plan/packages/agent-plan/dist/index.js setup claude-code --user --local
node /Users/antonio/projects/agent-plan/packages/agent-plan/dist/index.js setup codex --user --local
node /Users/antonio/projects/agent-plan/packages/agent-plan/dist/index.js setup opencode --user --localThe CLI package is agent-plan.
agent-plan help
agent-plan --version # alias: -v
agent-plan mcp
agent-plan init [name] [--description <text>] [--goal <text>] [--json]
agent-plan serve [--root <.planner dir>] [--port <n>] [--host <h>] [--reuse] [--json]
agent-plan stop [--root <.planner dir>] [--json]
agent-plan export [--full]
agent-plan setup claude-code --user
agent-plan setup claude-code --projectReport the installed CLI package:
agent-plan --version # alias: agent-plan -vReport the versions loaded by each harness:
# Pi
/planner version
# Claude Code plugin
/planner version
# Claude Code or Codex through MCP
planner-version
The MCP result identifies the loaded @agent-plan/mcp and @agent-plan/core packages. Pi also identifies the loaded @agent-plan/pi-adapter and @agent-plan/server packages. To inspect Pi's installed package directly from a shell:
npm --prefix "$HOME/.pi/agent/npm" list @agent-plan/pi-adapter --depth=0Starts the stdio MCP server.
This is what Claude Code launches after setup.
Initializes .planner/ in the current working directory.
cd my-project
agent-plan initThis is equivalent in intent to running /planner init from an agent UI.
For programs, --description and --goal set the project fields when the planner is created, and --json prints one line: {"status":"created"|"exists","root":...,"name":...}. With --json the command never prompts (the folder name is the default name). An existing planner is never changed: it reports "exists" with exit code 0.
Starts the planner web server for a .planner/ folder and prints its address. It runs until stopped (Ctrl-C or SIGTERM).
agent-plan serve # ./.planner on 127.0.0.1:3030
agent-plan serve --port 0 --json # any free port; one JSON line on stdout
agent-plan serve --root /path/to/.planner --host 0.0.0.0--json prints {"url","localUrl","lanUrl","host","port","root","reused"} (with the real port when --port 0). A missing .planner/ or an invalid port exits with code 1 and a message on stderr.
While a server runs it writes .planner/.local/server.json (pid, address, root, start time, version, kind) and removes it when it stops. The file is git-ignored, and a record whose process is gone or whose address no longer answers /health is ignored. Every server writes it, whether it was started by agent-plan serve, by planner-web / planner-load, or by the Pi adapter. When two servers run for one folder, the first keeps the record.
agent-plan serve --reuse --json # a server is already running for this folder: print its address (reused: true) and exit
agent-plan stop # stop the server that `agent-plan serve` started for this folderserve --reuse starts a server only when none is running. stop only stops a server started by agent-plan serve (kind: "standalone"). A server running inside another program (an agent's MCP server, the Pi adapter) is kind: "embedded": stop refuses (exit 1) because signalling it would end that program; stop it from there (planner-web stop, /planner stop). stop exits 0 when nothing is running.
Generates a Markdown export of the plan and writes it to .planner/EXPORT.md.
agent-plan export # summary report
agent-plan export --full # full hierarchical detail (features → phases → tasks)In Pi and Claude Code the same report is available via:
/planner export
/planner export-full
The web UI also exposes an Export dropdown with Summary and Full options that download the generated Markdown file.
Configures Claude Code integration.
Useful options:
--user install at Claude Code user scope
--project install in the current project; this is the default
--local point config to the local built CLI instead of npx/global package
--force overwrite an existing agent-plan MCP entryPi exposes Agent Plan as one grouped command:
/planner
/planner init— Initialize planner in this project/planner show— Show planner overview/planner repair— Repair planner integrity/planner load— Re-enable planner and start web UI/planner disable— Disable planner and stop web UI for this session (alias:/planner stop)
/planner project discuss— Run project discovery/planner project language— Set persistent language preferences
/planner feature list— List features/planner feature add— Create a feature/planner feature show— Show a feature/planner feature update— Update a feature/planner feature delete— Delete a feature
/planner phase list— List phases/planner phase add— Add a phase/planner phase show— Show a phase/planner phase discuss— Discuss a phase/planner phase update— Update a phase/planner phase delete— Delete a phase
/planner task list— List tasks/planner task add— Add a task/planner task show— Show a task/planner task discuss— Discuss a task/planner task update— Update a task/planner task delete— Delete a task/planner task start— Mark a task in-progress/planner task complete— Mark a task done
/planner handoff list— List phases with a handoff/planner handoff prepare— Tell the agent to create/update the handoff/planner handoff show— Show the current handoff/planner handoff write— Write handoff directly from planner data/planner handoff clear— Delete the current handoff
/planner web start— Start the web UI/planner web stop— Stop the web UI/planner web status— Show web UI status
/planner export— Export plan summary as Markdown/planner export-full— Export full detailed plan as Markdown
/planner bypass— Authorize edit/write without a task in-progress (15 min)/planner clear-bypass— Revoke the guard bypass
The planner is disabled by default at Pi startup. No enablement or web-UI prompt is shown — nothing auto-starts. To enable the planner, the user (or agent) runs /planner load; to disable it, /planner stop (alias /planner disable).
Why this exists:
- Pi sessions should be quick to resume without blocking prompts;
- the planner must not start automatically — only on explicit request;
- the same model applies consistently across harnesses (Pi, Claude Code, Codex).
When the planner is loaded, the startup resume summary includes the dashboard URL (LAN address + port). The Web UI address appears only in that load recap or via /planner web status — never appended to every message.
If no feature/phase/task is actually in-progress, the resume summary must not invent a current focus from the handoff. In that case, the handoff is treated as a previous-session hint to validate against the current plan state, ordering, and dependencies.
Agent Plan now persists explicit planning order for:
- features →
feature.number - phases →
phase.number - tasks →
task.number
This order is displayed as stable human-friendly labels:
F001,F002, ...P001,P002, ...T001,T002, ...
Why this exists:
- UUIDs are stable but hard to reason about visually;
- resume, handoff, export, and Work Tree must agree on the same ordering;
- teams need a clear sense of sequence and priority, not just identity.
For older projects, the numbering is normalized automatically from the current planner structure and persisted back into .planner/.
Older flat slash commands such as planner-task-start were removed from Pi's global command registration to avoid autocomplete noise. Pi users should use the grouped /planner ... form.
Agent Plan includes a local web UI served by plan-server and used by the Pi adapter.
The web UI visualizes:
- project summary;
- features;
- phases;
- tasks;
- status rollups;
- accepted decisions;
- handoff state.
The planner-web MCP tool fully manages the web lifecycle (start / status / stop) in-process, binding LAN (0.0.0.0) with a dynamic OS-assigned port. Every start/status response returns the reachable address plus typed running/address/localUrl/lanUrl/host/port/mode metadata (Pi parity). The same lifecycle is exposed in the Pi adapter as agent tools (planner-web, planner-load, planner-stop) and as /planner web / /planner load / /planner stop slash commands.
Agent Plan now creates a project-local ignore file at:
.planner/.gitignore
It ignores transient planner artifacts such as:
*.bak*.tmp.*
Why this exists:
PlanStoreuses atomic writes and backup files for safety;- backup/temp artifacts should not pollute
git status; - planner recovery should stay safe without requiring manual cleanup.
At Pi session start, orphan .bak and *.tmp.* files are also cleaned up asynchronously in the background. This is automatic; there is no manual command to run.
Handoffs are entity-scoped: each phase carries its own phase.handoff
field (stored inline in the phase JSON), not a standalone file. The legacy
.planner/HANDOFF.md is deprecated. The last 5 cleared handoffs per phase
are archived under .planner/handoff-archive/ for recovery.
Slash commands (/planner handoff ...):
/planner handoff list— list phases with a non-emptyphase.handoff/planner handoff show <P00x(F00x)>— read one exact phase handoff and its resume-readiness status/planner handoff write <P00x(F00x)>— route agents through prepare/write; direct unsynchronized writes are disabled/planner handoff prepare— tell the agent to prepare a candidate for one explicitly confirmed phase/planner handoff clear <P00x(F00x)>— archive and clear a phase handoff
MCP tools:
planner-handoff-listplanner-handoff-showplanner-handoff-writeplanner-handoff-prepareplanner-handoff-verifyplanner-handoff-clear
Lifecycle: a handoff is archived when its phase reaches any terminal outcome. A confirmed write persists a candidate with resumeReady: false; the agent must show and read the complete persisted body, compare it again with all required sources, then call the verify tool with the shown content hash. Only resumeReady: true permits a completeness claim. On resume it remains context to validate against current plan state, not a lock—task_start is never blocked by a pending handoff.
New handoffs are compact resume capsules targeting at most 8,000 inline characters (24,000 remains only as an absolute compatibility ceiling). Inline sections are: Current focus, Current and partial state, Preservation constraints, Supporting documents, Blockers and risks, and How to resume. The verbose completeness audit and cold-start inventory are retained once as structured metadata and never embedded in Markdown. Oversized writes auto-externalize the full body to one planner-owned .planner/docs/handoff-*.md document and complete the write; there is no dead-end size error. Supporting .planner/docs/*.md references render as new-tab links in shared formatted content and open the path-safe viewer at /docs/view (traversal/symlink rejected); the viewer includes a dependency-free textarea editor with live preview and an explicitly confirmed save (confirmed=true). Editor decision: @uiw/react-md-editor and CodeMirror 6 were evaluated and rejected to avoid bundle/maintenance cost; the baseline textarea plus existing preview is the shipped editor.
Agent Plan relies on explicit task lifecycle transitions.
Before implementation work:
/planner task start <task-id>
Before temporarily changing focus:
task_switch(from_task, to_task, reason, what_was_being_done, resume_location, how_to_resume)
This deliberately allows necessary non-priority work while changing the source task to paused with a durable checkpoint. Temporary switches form a LIFO return stack; completing the temporary task emits RESUME REQUIRED and makes the preserved source the next recommendation. Use task_pause when no temporary target is being started.
After completed work:
/planner task complete <task-id>
Phase and feature statuses are derived from child task/phase state. Agents should not directly mutate parent status unless there is a specific reason.
Why this matters:
- the dashboard header and Work Tree use active task state;
- feature/phase rollups are derived from child tasks;
- resume focus and handoff quality depend on correct task lifecycle transitions;
- if an agent edits code without moving a task to
in-progress/done, the whole planner tree becomes stale.
For this reason, Agent Plan provides dedicated lifecycle tools and blocks the wrong path:
- use
task_start/planner-task-start//planner task startto begin or resume work; - use
task_pause/planner-task-pauseto save why work stopped, what was underway, the exact resume location, and how to continue; - use
task_switch/planner-task-switchto override normal feature → phase → task priority without losing the active task context; - use
task_complete/planner-task-complete//planner task completeto finish work and surface any required return target; - do not use
task_updateto move a task directly toin-progress,paused, ordone.
Agent Plan never blocks a tool call and never asks the user to confirm one because of task state. When a call changes the project's code (a file inside the project, outside .planner/) and no task is in-progress, the agent gets a warning telling it which task to start. The call goes through either way.
- Planner changes never need a task: CRUD on the project, features, phases, tasks, requirements, decisions and handoffs, and any write under
.planner/. - Writes outside the project never warn:
/dev/null,~/.claude/..., temp folders, other repositories. - Read-only commands never warn:
git pull, build, test, search, inspection. - An authorized temporary bypass silences the warning for its window.
Recommended workflow:
- Start the task normally:
/planner task start <task-id>
- If the user explicitly wants work without opening a task, authorize a temporary bypass:
/planner bypass
-
Do the edit/write work.
-
Revoke the bypass when you want normal discipline back:
/planner clear-bypass
The same flow is available through low-level tools:
- Pi/runtime tools:
plan_authorize_bypass,plan_clear_bypass - Claude/MCP tools:
planner-authorize-bypass,planner-clear-bypass
The bypass is stored in .planner/resume.json as guardBypassUntil, so it is shared across harnesses and auto-expires.
agent-plan setup claude-code (and the Claude Code plugin) installs a PreToolUse hook for Edit|Write|NotebookEdit|Bash. It never blocks and never prompts: when a call changes project code while no task is in-progress, it adds a warning to the agent's context and sets no permission decision, so Claude Code's normal permission flow is unchanged. Bash counts only when the command writes (redirect, tee, sed -i, cp/mv, rm, tree-rewriting git) into the project.
To silence the warning for a while, authorize a bypass:
/planner bypass
or via MCP:
planner-authorize-bypass (default 15 minutes)
Revoke:
/planner clear-bypass
planner-clear-bypass
The bypass is harness-agnostic (stored in resume.json), so Pi, Claude Code, Codex and other adapters all respect it.
packages/
agent-plan/ CLI: agent-plan mcp/init/setup
plan-core/ schemas, persistence, rendering, status logic
plan-server/ local HTTP/WebSocket server
plan-web-ui/ React dashboard
plan-mcp/ MCP stdio server for Claude Code
pi-adapter/ Pi extension adapter
plugins/
claude-code/ Claude Code plugin (marketplace bundle)
codex/ Codex plugin bundle (MCP + skill)
opencode/ OpenCode setup/plugin bundle (MCP + commands)
_shared/ single-source-of-truth templates for plugins
.claude-plugin/marketplace.json self-hosted marketplace catalog (repo root)
scripts/
release.cjs unified release helper (pnpm release)
sync-plugins.cjs regenerate plugin derived files from _shared/
copy-web-ui.sh copy Vite build into server/adapter web-ui-dist
Important docs:
PROJECT.md
ROADMAP.md
AGENTS.md
plugins/README.md
plugins/DECISIONS.md
docs/multi-agent-strategy.md
docs/setup-claude-code.md
Install dependencies:
pnpm installBuild/check all packages:
pnpm checkBuild MCP and CLI only:
pnpm --filter @agent-plan/mcp build
pnpm --filter agent-plan buildSmoke test MCP tools locally:
node packages/agent-plan/dist/index.js mcpFor automated MCP smoke testing, use the MCP SDK client to call listTools; the expected Phase 1 count is currently 38 public planner-* tools.
These behaviors are mainly relevant to contributors extending the adapters:
- Pi caches its injected planner context block between turns and rebuilds it only on the first turn or after planner writes. This reduces repeated I/O and large prompt regeneration on steady turns.
- Pi appends a reminder after successful
edit/writework when a task is active, nudging the agent to calltask_completewhen implementation is truly finished. - The write guard is intentionally harness-agnostic: the shared source of truth is
.planner/resume.json, not a Pi-only in-memory flag. - The startup resume summary must mention the dashboard URL when the web UI is active, and must treat handoff targets as hints rather than current focus when nothing is actually in progress.
Check that the slash command exists:
User scope:
~/.claude/commands/planner.md
Project scope:
.claude/commands/planner.md
Then restart Claude Code in the project.
This is expected if .planner/ exists, tasks exist, and no task is in-progress.
Run:
/planner task start <task-id>
Then retry the implementation action.
For project-local setup, check:
.mcp.json
For user-scope setup, check Claude Code's MCP list:
claude mcp listIf needed, re-run:
agent-plan setup claude-code --user --force.planner/is project-local and explicit.- Markdown is generated, not the source of truth.
- Core planning logic must remain harness-agnostic.
- Pi, Claude Code, and future agents are adapters over the same planning model.
- Installation should be global/user-level when possible; project initialization should remain explicit.
- Public naming uses
planner-*for MCP tools and/planner ...for human command UX.
This repository is a pnpm workspace. Only some packages are published to npm.
Published (public npm):
@agent-plan/core— schemas, persistence, ordering, status rollups, rendering@agent-plan/mcp— MCP stdio server@agent-plan/server— local HTTP/WebSocket serveragent-plan— CLI (init,mcp,setup claude-code,setup codex,setup opencode,export,guard pre-tool-use)@agent-plan/pi-adapter— Pi extension adapter
Private (not published):
@agent-plan/web-ui— Vite application, served as a build artifact, not a standalone npm package
- Node.js and pnpm installed
npm loginperformed (orNPM_TOKENconfigured) on the account that owns the@agent-planscope
From the repository root:
pnpm install
pnpm release:validaterelease:validate runs the full build and the TypeScript check:
pnpm build
pnpm checkpackages/plan-server/web-ui-dist/ and packages/pi-adapter/web-ui-dist/ contain the built dashboard (a copy of the Vite build of packages/plan-web-ui). They are tracked in git by design, so please do not delete, untrack or git-ignore them:
- The published
@agent-plan/serverand@agent-plan/pi-adapterpackages ship them, and a plain checkout serves the dashboard without building it. scripts/copy-web-ui.shfinds where to copy the build by looking for these folders. Without them,pnpm buildfails on a fresh clone and in CI.
Never edit them by hand. pnpm build regenerates both copies. When you change packages/plan-web-ui/src, commit the regenerated bundle in the same PR as the UI change. If web-ui-dist/ shows up as modified and you did not change the UI, someone has an uncommitted UI change: ask before touching it.
Before publishing, inspect what would actually be packaged:
pnpm release:pack-dry-runImportant: use pnpm pack (or pnpm release:pack-dry-run), not npm pack.
pnpm pack/pnpm publish rewrite workspace:* dependency ranges to the real
published versions inside the tarball. npm pack leaves workspace:* verbatim,
which makes the resulting tarball uninstallable.
The expected tarball contents for each public package are:
dist/**/*.js,dist/**/*.d.ts,dist/**/*.d.ts.mapREADME.mdLICENSEpackage.json
src/, tsconfig.json, and dist/.tsbuildinfo must NOT appear in the tarball.
Publishing is automated by GitHub Actions. The workflow .github/workflows/publish.yml runs on pushes to main and next: main publishes the stable latest channel after a release PR merge, while next publishes prereleases under the next dist-tag. It publishes all five public packages in dependency order using pnpm publish (which rewrites workspace:* ranges to the resolved versions). Merging into develop does not publish — develop is staging. After a successful stable publish from main, the workflow creates the canonical annotated tag vX.Y.Z; prerelease publishes never create stable tags.
Do not run npm publish manually per package: it would publish stale workspace:* ranges that npm cannot install.
Use the canonical runner instead of repeatedly chaining broad commands:
pnpm verify:focused -- --package plan-mcp
pnpm verify:focused -- --test packages/plan-mcp/test/mcp-harness.test.mjs
pnpm verify:finalFocused mode runs one package or test file. Final mode captures complete logs under .planner/.local/verification/, prints only concise summaries or bounded failure excerpts, and reuses a successful result while the repository content fingerprint is unchanged. The final gate covers build, typecheck, coverage, plugin synchronization, browser E2E, and a clean mkdtemp installation from freshly packed public packages.
All public packages share a single unified version per release. Releases are driven by the release script (scripts/release.cjs).
From a clean develop branch, up to date with origin:
pnpm release # patch (default)
pnpm release -- minor # minor
pnpm release -- major # major
pnpm release -- 1.0.0 # explicit version
pnpm release -- --dry-run # preview onlyThe script does everything:
- Pre-flight — clean working tree, on
develop, up to date withorigin/develop. - Compute the unified target version — fetch canonical
vX.Y.Ztags and bump the latest stable tag. While tag history is being bootstrapped, fall back to the unified stable version onorigin/main. Develop prerelease suffixes such as-next.Nnever affect the stable base; explicit versions retain a downgrade guard. - Create
release/v<version>fromdevelopand bump all 5 packages to that version. - Verify —
pnpm install+ the canonicalpnpm verify:finalgate (bounded logs, build, typecheck, coverage, plugin sync, Playwright, and freshly packed/installed artifact smoke); rolls back the branch on failure. - Commit, push, and open a PR →
main.
Merge the release PR into main to trigger publish.yml (npm publish + stable vX.Y.Z tag). Then sync develop:
git switch develop && git pull && git merge origin/main && git pushSee AGENTS.md §12 (Branching & Release) for the full rules.
For day-to-day iteration, the repo also publishes a next npm dist-tag from
the next branch:
pnpm release:next # bump the prerelease counter (0.2.19-next.10 -> 0.2.19-next.11)
pnpm release:next -- --dry-run # preview onlyscripts/release-next.cjs increments the -next.N prerelease counter on the
current branch and pushes; publish.yml publishes the result to npm with the
next dist-tag. Install it with:
npm i @agent-plan/core@nextThe plugins (plugins/claude-code/.claude-plugin/plugin.json,
plugins/codex/plugin.json, plugins/codex/.codex-plugin/plugin.json, and the
repo-root marketplace catalogs) have their own version track but are bumped by
both release scripts so marketplace clients can detect refreshed plugin files
on either channel. Stable Git tags always use the unified npm package version,
not the independent plugin version.
After publishing, end users install once:
npm install -g agent-planThen configure an agent harness, e.g. for Claude Code at user scope:
agent-plan setup claude-code --userProject initialization stays explicit and is done later inside a project with
/planner init or agent-plan init.