# APM Agent Instructions
## Repo structure
_Fill in your project's structure here._
State machine: transitions defined in `apm.toml` under `[[workflow.states]]`
## Roles
Every Claude session in this repo is either a **Main Agent** or a
**Worker** (subagent). Read your initial prompt to detect which you are.
**Role detection**
- If your initial prompt contains "You are a Worker agent assigned to ticket #N"
→ you are a **Worker**. Skip to the Worker section below.
- Otherwise → you are the **Main Agent**. Follow the Main Agent section below.
### Main Agent
You are a project-management companion to the supervisor. The supervisor creates tickets (with context, dependencies, epics), reviews specs and code, and handles merges; you help with those tasks on request. Workers are dispatched by `apm work` or the web UI — not by you. Do not spawn workers, run the dispatcher, or change code unless explicitly asked by the supervisor.
**Supervisor-only transitions.** The following state changes are reserved for the supervisor — do not run them even when the state machine allows it, and even when you just created the ticket:
- `new → groomed` — grooming is the supervisor's review gate; leave new tickets in `new` after creation
- `specd → ready` and `specd → ammend` — spec acceptance is a supervisor review
- `implemented → ready` / `implemented → ammend` / `implemented → closed` — implementation acceptance is a supervisor review
- `blocked → ready` — unblocking requires the supervisor's answer
- Any `apm epic close` — epic PRs are opened by the supervisor
Transitions you *may* initiate for your own tickets: `new → closed` (cancel a ticket you just created in error), and any state change the workflow marks `actionable = ["agent"]` when you are the assigned agent.
**Override.** The supervisor can ask you to perform any supervisor-only transition explicitly. If they do, run it and note in your response that you are acting at their direction. The exclusion list above applies only to actions you initiate on your own.
**When asked to ammend a ticket.** Your role ends after writing the amendment requests. Specifically:
1. Transition `specd → ammend`
2. Add each amendment request with `apm spec <id> --section "Amendment requests" --add-task "..."`
3. Stop — do not transition to `in_design`, do not address the amendments yourself
The spec revision is worker work. Leave the ticket in `ammend` for a worker to pick up.
### Worker
You have been assigned a single ticket. Implement it, run tests, and mark it
implemented. Do not spawn further workers or act as delegator. If blocked by a
capability limitation (not a missing decision), see `apm.worker.md` →
**Capability limitations** for the clean exit procedure.
## Ticket format
Tickets are Markdown files with TOML frontmatter (between `+++` delimiters):
```toml
id = 1
title = "Short title"
state = "new"
branch = "ticket/0001-short-title"
author = "agent-name"
created_at = "2026-01-01T00:00Z"
```
Body sections (`## Spec` required):
- `### Problem` — what is broken or missing
- `### Acceptance criteria` — checkbox list, each independently testable
- `### Out of scope` — explicit exclusions
- `### Approach` — implementation plan
- `## History` — auto-managed transition log
## Development workflow
1. Read the relevant spec files before implementing anything
2. Make the minimal change that satisfies the acceptance criteria
3. Add or update tests — all acceptance criteria should be covered
4. Run your project's test suite — all tests must pass before calling `apm state <id> implemented`
## Identity
Generate a unique session name at the start of every session. Use a fixed
string — do not use `$()` substitution inline, as it triggers permission
prompts. Pick a name of the form `claude-MMDD-HHMM-XXXX` (e.g.
`claude-0325-1430-a3f9`) and export it before running any apm command:
```bash
export APM_AGENT_NAME=claude-0325-1430-a3f9
```
Hold the same name for the entire session. Do not regenerate mid-session.
Engineers set `APM_AGENT_NAME` to their own username when working directly.
## MAIN WORKTREE RULE
**Never run `git checkout` in the main working directory.**
The main directory is always on `main`. This is a hard rule — breaking it
confuses the user and corrupts the working state.
All branch work — spec editing, code changes, everything — happens inside a
**permanent git worktree** provisioned by `apm state <id> in_design` or
`apm start <id>`. Once you have a worktree path, use `git -C <worktree-path>`
to run git commands there without leaving your current directory.
## Startup
1. `apm sync` — refresh local cache from all `ticket/*` branches
2. `apm next --json` — find the highest-priority ticket you can act on now
3. `apm list --state in_progress` — check for in-progress tickets (resume if any match your agent name)
If `apm next` returns null and you have no in-progress tickets, there is nothing
to do. Report back to the supervisor.
## Working a ticket
The ticket's state determines what to do next:
**state = `groomed`** — write the spec:
1. `apm show <id>` — read the full ticket
2. `apm state <id> in_design` — claim the ticket and provision its worktree;
prints two lines: the state-change line, then the worktree path
3. Write each spec section using `apm spec` (each `--set` auto-commits to the
ticket branch; no manual `git add`/`git commit` needed). Use `--set` only
when the section is empty or contains just the initial placeholder; use
`--append` (or `--add-task` for checkbox sections) when the section
already has content you must preserve.
```bash
apm spec <id> --section Problem --set "..."
apm spec <id> --section "Acceptance criteria" --set "- [ ] ..."
apm spec <id> --section "Out of scope" --set "..."
apm spec <id> --section Approach --set "..."
```
Note: `apm new` opens `$EDITOR` after creating a ticket. Agents should always
pass `--no-edit` to skip the interactive editor: `apm new --no-edit "<title>"`.
4. If blocked on an ambiguity: write the question in `### Open questions` with
`apm spec <id> --section "Open questions" --append "..."` (use `--append`
to preserve any earlier questions), then `apm state <id> question`
5. `apm set <id> effort <1-10>` — assess implementation scale (do this after writing the spec, not before)
6. `apm set <id> risk <1-10>` — assess technical risk
7. `apm state <id> specd` — submit spec for supervisor review
**state = `ammend`** — revise the spec:
1. `apm show <id>` — read the Amendment requests carefully
2. `apm state <id> in_design` — claim the ticket and provision its worktree;
prints two lines: the state-change line, then the worktree path
3. Address each item using `apm spec` to update sections. **Use `--append`,
not `--set`, when adding to a section that already has content** (most
sections by this point will). `--set` overwrites and would erase prior
decisions, including checked-off amendment items the supervisor expects
to see preserved. For `Acceptance criteria` and similar checkbox sections
use `--add-task` to add a new item. Mark each amendment off with
`apm spec <id> --section "Amendment requests" --mark "..."`. Each `apm spec`
call auto-commits; no manual `git add`/`git commit` needed.
4. `apm state <id> specd` — resubmit only when all amendment boxes are checked
**state = `in_design`** — spec is actively being written or revised:
The ticket is claimed by another agent. Do not pick up an `in_design` ticket
on your own. If the supervisor asks you to take it over, follow the "When
asked to take over another agent's ticket" section below.
**state = `ready`** — implement:
1. `apm show <id>` — re-read the full spec before touching any code
- Check `## History`: if the ticket was previously `in_progress`, a worktree
and partial work already exist on the branch — pick up from there
2. `apm start <id>` — claims the ticket (sets `agent` = your name, state →
`in_progress`), provisions or reuses the permanent worktree; prints its path
To hand the ticket to an autonomous background worker instead:
```
apm start --spawn <id> # worker runs under project allow list
apm start --spawn -P <id> # worker runs with --dangerously-skip-permissions
```
The worker provisions the worktree, implements, and transitions to implemented autonomously.
The supervisor gets control back immediately.
3. Commit all code changes to the ticket branch inside the worktree:
```bash
wt=<path printed by apm start>
git -C "$wt" add <files>
git -C "$wt" commit -m "<message>"
```
4. Update `## Spec` if the approach evolves during implementation
5. `apm state <id> implemented` — this pushes the branch and opens the PR automatically; do not open a PR manually
6. If blocked mid-implementation (missing information, upstream decision needed):
write the question in `### Open questions` with `apm spec <id> --section
"Open questions" --append "..."`, commit it, then `apm state <id> blocked`
— **do not use `apm state <id> ready`**, that transition no longer exists
from `in_progress`
**state = `blocked`** — implementation is blocked on a supervisor decision:
1. The previous agent wrote questions in `### Open questions` before blocking
2. Wait — this state is actionable by supervisor only
3. Once the supervisor transitions to `ready`, pick it up with `apm start <id>`
and continue from the existing worktree/branch
## When asked to take over another agent's ticket
`apm assign` is a supervisor action. Do not run it on your own — only when the
supervisor explicitly asks you to take a ticket over. When they do:
1. `apm show <id>` — read the full ticket including history
2. `apm assign <id> <your-username>` — reassign ownership to yourself
3. If the worktree doesn't exist yet: `apm state <id> in_design` (spec states) or `apm start <id>` (implementation states) to provision it
4. Continue from where the previous agent left off
5. Do not discard or overwrite previous spec work or open questions
## Spec quality bar
Every spec must have all four required subsections before moving to `specd`:
- **Problem** — what is broken or missing, and why it matters
- **Acceptance criteria** — checkboxes; each one independently testable
- **Out of scope** — explicit list of what this ticket does not cover
- **Approach** — how the implementation will work
Do not check acceptance criteria boxes until the implementation is verified.
#### Subsection markers
`####` headings within a section (e.g. inside `### Approach`) are purely for
readability — they are **not** targetable by `apm spec`. Do not use
`--section "Approach > Phase 2"`; that syntax is not implemented and will
error. To update content within a long section, use `--section Approach --set
"..."` with the full replacement text, or `--append` to add content at the
end. Never fall back to editing the ticket file directly.
## Spec discipline
- Set `effort` and `risk` after writing the spec, before transitioning to `specd` — you only have enough context once the spec is complete
- Do not proceed on assumptions: write questions, change state to `question`
- Once a question is answered, reflect the decision in `### Approach`
- Do not delete answered questions or checked amendment items — they are the
decision record. Use `apm spec --append` (or `--add-task` for checkbox
sections) to add new content to a non-empty section; reserve `--set` for
sections that are still empty or contain only the initial placeholder.
## Branch discipline
Every ticket has a single branch — `ticket/<id>-<slug>` — for its entire
lifecycle, created automatically by `apm new`. Never create or rename branches
manually.
- All spec edits and code changes go to `ticket/<id>-<slug>` via the worktree
- `apm start <id>` provisions the permanent worktree; use `git -C <wt>` to commit
- APM manages frontmatter and `## History` — never edit them directly
- Do not delete the ticket branch until the ticket is `closed` — APM uses
branch presence to detect merge state
## One ticket per agent process
Work one ticket at a time per agent process. For parallelism, use separate
agent processes with separate clones or worktrees.
## Shell discipline
Claude Code's permission system matches the **start** of the command string.
Compound calls defeat this matching and generate permission prompts. Keep each
Bash call to a single operation.
**Do not chain commands:**
```bash
# Wrong — && chains defeat allow-list matching
apm sync && apm list --state ready
# Right — one call per operation
apm sync
apm list --state ready
```
**Do not use `$()` subshells:**
```bash
# Wrong — triggers "command substitution" security check
apm spec 1234 --section Problem --set "$(cat /tmp/problem.md)"
# Right — write content with the Write tool, then reference by file
apm spec 1234 --section Problem --set-file /tmp/problem.md
```
**Do not use background jobs (`&`):**
```bash
# Wrong — & defeats pattern matching
apm state 1234 implemented & apm state 5678 implemented & wait
# Right — sequential calls
apm state 1234 implemented
apm state 5678 implemented
```
**Use `git -C` for all git operations in worktrees:**
```bash
# Wrong — cd && git triggers "bare repository attack" check
cd "$wt" && git add .
# Right
git -C "$wt" add <files>
```
**Use `bash -c` for multi-step commands that must share a directory:**
```bash
# Right — single bash call, matches Bash(bash *)
bash -c "cd $wt && <your-test-command> 2>&1"
```
## Creating tickets
Every `apm new` invocation must seed the ticket's Problem section with
enough context that a downstream worker can pick it up without having to
re-derive the analysis. A bare title is not enough — it forces the next
agent to re-investigate the repo, and the supervisor loses the reasoning
that motivated the ticket.
Always pass `--context` (and `--no-edit`, to skip the interactive editor):
```bash
apm new --no-edit --context "<problem statement with concrete usage sites, measurements, or constraints>" "<title>"
```
The `--context` string is written into `### Problem` verbatim. Include
whatever made you file the ticket: the failing test, the grep results,
the measured regression, the file:line usage sites, the upstream decision
this depends on. If the context is too long to fit in a shell argument,
create the ticket with a short `--context` placeholder, then replace the
Problem section with `apm spec <id> --section Problem --set-file <path>`.
If you only have a title and no usable context yet, the ticket is not
ready to be filed — leave a note for the supervisor instead of creating
a skeleton ticket.
## Side tickets
When you notice an out-of-scope issue during implementation, capture it without interrupting your current work:
```bash
apm new --side-note "Brief title" --context "What you observed and why it matters"
```
Then immediately resume the current ticket. The supervisor will triage the side ticket separately.