st
Overview
Maintain a durable plan file in the repo (default: .step/st-plan.jsonl) using in-place JSONL v3 persistence with dual lanes:
eventlane for mutationscheckpointlane for periodic full-state snapshots
Plan items use typed dependency edges (deps: [{id,type}]) plus notes and comments, and render deterministically through show/read views.
Workflow
- Resolve repository root and plan path.
- If the run has 3+ dependent steps, likely spans turns, or already uses
update_plan, adopt$stas the durable source of truth before editing. - Initialize plan storage with
scripts/st_plan.py initif missing. - Rehydrate current state with
scripts/st_plan.py show(or focused views viaready/blocked). - Apply plan mutations through script subcommands (
add,set-status,set-deps,set-notes,add-comment,remove,import-plan); do not hand-edit existing JSONL lines. - After each mutation command, consume the emitted
update_plan: {...}payload and publishupdate_planin the same turn. - Use
emit-update-planto regenerate the payload from durable state when needed. - Export/import snapshots when cross-session handoff is needed.
Commands
Run commands from the target repository root.
CODEX_SKILLS_HOME="${CODEX_HOME:-$HOME/.codex}"
CLAUDE_SKILLS_HOME="${CLAUDE_HOME:-$HOME/.claude}"
ST_PLAN="$CODEX_SKILLS_HOME/skills/st/scripts/st_plan.py"
[ -f "$ST_PLAN" ] || ST_PLAN="$CLAUDE_SKILLS_HOME/skills/st/scripts/st_plan.py"
ST_QUERY="$CODEX_SKILLS_HOME/skills/st/scripts/st_query_fast.sh"
[ -f "$ST_QUERY" ] || ST_QUERY="$CLAUDE_SKILLS_HOME/skills/st/scripts/st_query_fast.sh"
uv run "$ST_PLAN" init --file .step/st-plan.jsonl
uv run "$ST_PLAN" add --file .step/st-plan.jsonl --id st-001 --step "Reproduce failing test" --deps ""
uv run "$ST_PLAN" add --file .step/st-plan.jsonl --id st-002 --step "Patch core logic" --deps "st-001"
uv run "$ST_PLAN" set-status --file .step/st-plan.jsonl --id st-001 --status in_progress
uv run "$ST_PLAN" set-deps --file .step/st-plan.jsonl --id st-002 --deps "st-001:blocks,st-003:blocks"
uv run "$ST_PLAN" set-notes --file .step/st-plan.jsonl --id st-002 --notes "Need benchmark evidence"
uv run "$ST_PLAN" add-comment --file .step/st-plan.jsonl --id st-002 --text "Pausing until CI clears" --author tk
uv run "$ST_PLAN" ready --file .step/st-plan.jsonl --format markdown
uv run "$ST_PLAN" blocked --file .step/st-plan.jsonl --format json
uv run "$ST_PLAN" show --file .step/st-plan.jsonl --format markdown
uv run "$ST_PLAN" emit-update-plan --file .step/st-plan.jsonl
uv run "$ST_PLAN" export --file .step/st-plan.jsonl --output .step/st-plan.snapshot.json
uv run "$ST_PLAN" import-plan --file .step/st-plan.jsonl --input .step/st-plan.snapshot.json --replace
Operating Rules
- Keep exactly one
in_progressitem unless--allow-multiple-in-progressis explicitly used. - Track prerequisites in each item's typed
depsarray; dependencies are part of the canonical JSONL schema. - Parse CLI deps as comma-separated
idorid:typetokens; missing type normalizes toblocks, and type must be kebab-case. - Require dependency integrity:
- dependency IDs must exist in the current plan,
- no self-dependencies,
- no dependency cycles.
- Allow
in_progressandcompletedonly when all dependencies arecompleted. - Normalize user status terms before writing:
open,queued->pendingactive,doing->in_progressdone,closed->completed
- Mutation commands (
add,set-status,set-deps,set-notes,add-comment,remove,import-plan) automatically print anupdate_plan:payload line after durable write. - Lock sidecar policy: mutating commands require the lock file (
<plan-file>.lock, for example.step/st-plan.jsonl.lock) to be gitignored when inside a git repo; add it to.gitignorebefore first mutation. - Mutations rewrite the JSONL file atomically (
temp+fsync+os.replace) and compact to a canonicalreplaceevent plus checkpoint snapshot at the current seq watermark. import-plan --replaceatomically resets state in the same in-place write model.- Prefer concise, stable item IDs (
st-001,st-002, ...). - Prefer
show --format markdownfor execution: it groups steps intoReady,Waiting on Dependencies,In Progress, and terminal/manual buckets.
Fast Query Helper (jq + rg)
- Use
scripts/st_query_fast.shfor low-latency read-only queries against large logs. - Requires both
jqandrgonPATH. - Examples:
"$ST_QUERY" --file .step/st-plan.jsonl ready"$ST_QUERY" --file .step/st-plan.jsonl blocked"$ST_QUERY" --file .step/st-plan.jsonl show"$ST_QUERY" --file .step/st-plan.jsonl show st-002
Sync Checklist ($st -> update_plan)
- After each
$stmutation (add,set-status,set-deps,set-notes,add-comment,remove,import-plan), parse the emittedupdate_plan: {...}line and publishupdate_planin the same turn. - If no emitted payload is available (for example after
initor shell piping), run:uv run "$ST_PLAN" emit-update-plan --file .step/st-plan.jsonl
- Preserve item ordering from
$stinupdate_plan. - Map statuses:
in_progress->in_progresscompleted->completedpending,blocked,deferred,canceled->pending
- Keep dependency edges only in
$st(deps); do not encode dependencies inupdate_plan. - If an item has
dep_state=waiting_on_deps, never publish that step asin_progressinupdate_plan. - Before final response on turns that mutate
$st, re-check no drift by comparing:uv run "$ST_PLAN" show --file .step/st-plan.jsonl --format json- the latest emitted
update_planpayload.
Validation
- Run lightweight CLI sanity checks:
uv run "$ST_PLAN" --helpuv run "$ST_PLAN" emit-update-plan --file .step/st-plan.jsonluv run "$ST_PLAN" show --file .step/st-plan.jsonl --format json
References
- Read
references/jsonl-format.mdfor event schema, status/dependency state vocabulary, and snapshot import/export shapes.
