About workflow
workflow is a skill for running software work through brainstorm, plan, execute, review, and wrap phases. It keeps run state and artifacts in a Git-tracked folder, with defined roles, handoffs, and verification rules.
Key features
- 01Five-phase development process
- 02Git-tracked run artifacts and state
- 03Role-based work and model routing
- 04Ticket acceptance and verification steps
- 05Review cycles and resolution tracking
- 06Rules for handoffs and wrap-up
Use cases
- 01Structure a feature from idea to review
- 02Track execution tickets and blockers
- 03Coordinate model changes between phases
- 04Record review findings and fixes
Install
Copy the command and run it in a terminal.
npx skills add https:/ / github.com/ johnviklund/ j-skills --skill workflowAfter installing, type/workflowin Claude Code to confirm it loaded.
Bundled files
References and scripts installed along with SKILL.md.
MAINTAINING.mdMEMORY.mdREADME.mdROADMAP_ARCHIVE.mdROADMAP.mdROUTING-NOTES.mdROUTING.mdSKILL-IMPACT_ARCHIVE.mdSKILL-IMPACT.mdreferences/bootstrap.mddirection-stress-tests.mdlearning-worklog.mdphase-0-brainstorm.mdphase-2-plan.mdphase-3-execute.mdphase-4-review.mdrealign.mdtests.mdtodo.mdworktrees.mdwrap.mdscripts/check-run.pyrun-worktree.pyscripts/tests/test_check_run.pytest_run_worktree.pyDetails
From the project READMEWorkflow
⚠️ Invoke this skill first; the references are read through it, never on their own.
Four phases and a wrap: brainstorm → plan → execute → review → wrap. Each phase is a seat
(a job with an output contract) filled by whatever model currently earns it. Writer and reviewer
sit with different vendors on purpose — independence is the point. ROUTING.md maps seats to
vendors, models and efforts.
Invocation: workflow <command> [slug]; the card's command line carries the CLI's own skill
prefix if it has one.
Checkout: Before reading a run, follow references/worktrees.md. It resolves every phase and status to the run's checkout; execute opens isolation, wrap lands it.
The run — .workflow/<slug>/
One run = one folder, tracked in git, kept forever; its files are the state machine.
| Artifact | Written by | Holds |
|---|---|---|
brainstorm.md | brainstorm | the brief: problem, behaviours (B#), decisions, test seams, out of scope — status of record for the run |
plan.md | plan, then execute | findings + tickets (T#), each with acceptance lines and a verify command; execution state |
patch_plan.md | review | fix tickets for the current patch cycle |
review.md | review | coverage, the current cycle's findings and verdict, a ## Resolved table of earlier cycles |
learnings.md, wrap.md | any / wrap | tagged lessons; wrap's checkpoint, then the run's ≤ ~40-line summary |
Layout. The top level holds only the artifacts above; everything else goes in a subfolder by
kind, created when first needed: receipts/ (verification output, diffs, handoffs:
t3-verification.md) · screens/ (UI before/after: t3-topic-page-before.jpg) · notes/
(investigations, audits, runbooks, drafts) · scripts/ (one-off code, reviewed like any other) ·
data/ (small frozen *.json/*.csv; bulk data stays outside the repo) · prototypes/
(throwaway sketches) · understand/ (written only by the understand skill).
Every artifact header carries Status: — drafting (resume that phase) · complete · parked ·
done. A run whose brainstorm.md is parked or done is not live.
| State of a live run | Next |
|---|---|
brainstorm.md only | plan |
plan.md with a ticket awaiting-human and none other ready | the human's action named in that ticket, then execute |
plan.md with a ticket not done | execute |
every ticket done; no review.md, or code changed since its Base | review |
patch_plan.md with a ticket not done | execute (runs the patch plan) |
review.md with no open finding and no code change since its Base | wrap |
Slug: the command names one, or exactly one run is live — otherwise list the live runs,
lettered, and ask. Live runs in each resolved checkout: grep -l 'Status: *\(drafting\|complete\)' .workflow/*/brainstorm.md.
workflow status prints one line per non-done run — slug · phase · blocker or none · next command
(an awaiting-human ticket is the blocker, with its action). A command that doesn't fit the run's
state gets named and asked about.
Grounding — tiered reads
- Always: the run's live artifacts (
brainstorm.md,plan.md,patch_plan.md, the current cycle ofreview.mdplus its## Resolvedtable);ROUTING.md(the card's rows);AGENTS.md; theMEMORY.mdindex — open amemory/<slug>.mdpage only when its "Applies when" matches;git log --oneline -15;git status. - Targeted —
PRODUCT.md,DESIGN.mdwhen product or UI is in scope: the headings, then only the sections the work touches, recorded asDocs read: PRODUCT.md §Vocabulary · DESIGN.md §Tables. They are the anti-drift guard: read in full for new product direction,realign, design-departure proposals, and any ticket that might contradict them. - Targeted —
TODO.md,ROADMAP.md: only in brainstorm, wrap andtodo. - Never by default:
*_ARCHIVE.md,WORKLOG.mdbeyond its latest entry, other runs' folders,.workflow/archive/:grepthem and read only matching lines. For adonerun, read itswrap.mdalone.
Talking to the human (every phase)
The artifact is the record; chat is the receipt (the human reads on a phone). Everything the
human reads follows the Rules of the plain skill: invoke it once per phase before writing. Ids,
commands, paths and fixed line formats stay as they are. Above the closing card, at most ~12 lines:
-
Result — what the phase did, ≤3 plain lines.
-
Decisions needed — numbered, one decision each, and every question uses this shape, one row per option, never a run-on paragraph:
**1. <title>** <the question, ≤2 plain sentences> - ➡️ **a) <option>** — recommended: <why it wins, in the reader's terms> - b) <option> — <what it costs or risks, why it is the weaker pick> - c) <option> — <same>The ➡️ row is first and bold, so the recommendation is seen without reading on. Every option carries a reason: the winner says why it wins, each other says why it loses; "also fine" is not a reason. When two options truly tie, say so and say what would tip it. Keep each row to one or two lines and one blank line between questions, so "all defaults except 2b" answers it.
-
A negative result is one line ("
PRODUCT.md— no changes").
Clarify gate (every phase except brainstorm): before the first edit, when a misread is expensive — ambiguous scope, a command/state mismatch, schema/contract/deletion work, a silent assumption — ask one round of ≤3 questions and wait.
Budgets — thinking is unbounded, files are not: brainstorm.md ≤ ~80 lines, 8 behaviours;
plan.md ≤ ~120 lines, 8 tickets, 20 acceptance lines; review.md ≤ ~100; done wrap.md ≤ ~40.
Over budget: propose two runs and ask; record a refusal as Split declined by human: <when>.
Cut prose, never acceptance lines or checks.
Seats
Brainstorm partner (the grill; also todo, wrap) · default executor (logic tickets, P1–P3
fixes) · heavy executor (schema/SQL/contract tickets, P0 fixes, hardest multi-file work) ·
mechanical lane (tickets with an explicit expected text result) · operator (live or
irreversible writes, authorizations, hosted consoles: run by the human, or by the agent after
approval) · strict reviewer (the skeptic — plan, review, patch plans, realign; read-only except
realign).
Invariants:
- Cross-vendor review. The strict reviewer is a different vendor from the code's writer; a
same-vendor review is degraded and says so in
review.md. One step runs in one session only. - Availability first. Open the model picker at session start, walk
ROUTING.md's fallback chain in order, and name any switch. - Name the running model from a record, not memory (
references/phase-3-execute.md). - The human acts only where a human adds something (map in
ROUTING.md): code is checked by tests and the cross-vendor review, not diff reading; a user-visible change is tried by the human before its commit. The lane — not the severity — sets the seat, fix tickets included. - Sub-agents are read-only breadth, their findings verified; writing runs in the main session.
Every phase starts fresh, re-grounded from the run folder and git; the handoff is where the model
swap happens, and a reset (not compaction) is how. The CLI's literal commands for reset,
context meter and model picker are in README.md.
The closing card — workflow next
Every phase ends with this card as the turn's last output. A turn that waits for a chat answer (a
UI check, a clarify question, the plan's ticket-list round) ends on the Decisions list, no card.
Fill the model line from ROUTING.md's rows (a Trial entry replaces the primary, marked
(trial)) so the human never opens a file to pick a model.
▶ Next: ·
- Why: <one line, or the cycle and finding ids for a patch cycle>
- Reset: yes | no
- Model: · ·
- Fallback: ·
- Reads:
Run:
workflow <phase> <slug>
One field per row, as a bullet list, never a run-on line: markdown joins plain lines, so a row
without its bullet disappears into the paragraph. A blank line sits before the Run: label and
before the fence, and the command is always its own fenced text block, even when the card is
short, so it has a copy button.
Reads: names run files and receipts only; the CLI already loads AGENTS.md and its kin. Before
the card, commit and push from the resolved checkout per references/worktrees.md.
Resolve unexpected check-run.py worktree or branch warnings first, or ask about them.
Reset is yes at every handoff, no only for same-seat work continuing. A human-only step (an
operator ticket, an escalation) reads - **Model:** human · <the one action> with Reads: naming
the handoff. A finished run gets wrap's ✅ card (references/wrap.md).
Ground rules
- Verify against the code — and the data. Every interface, signature and column a phase relies on is checked in the real code; the brief's claims are hypotheses until then. An Outcome that depends on real data gets a read-only query before its behaviours are confirmed.
- Provenance header — every run artifact opens with five lines:
Command:,Created:(a brief or plan adds· <model>),Base:(git sha),Inputs:(<artifact> @ <its Base>ornone),Status:. At phase entry the input isStatus: completeand fresh:git diff --stat <Base>..HEAD -- <files it names>shows only this run's own ticket commits. Stale → name it and route to the phase that must rerun. - Receipts vs code. Receipts are
*.md,*.txt, and all of a run'sscreens/,prototypes/,understand/; every other file is code. "Code changed since X" =git diff --stat X..HEAD -- . ':(exclude)*.md' ':(exclude)*.txt' ':(exclude,glob).workflow/*/screens/**' ':(exclude,glob).workflow/*/prototypes/**' ':(exclude,glob).workflow/*/understand/**'is non-empty — the receipt-rule diff. Code outside.workflow/never reads anything inside it. - The human's edits. A dirty path that no run commit touched (
git diff --name-only <plan Base>..HEADomits it) is the human's own work, such as a config file the app rewrites on save. Leave it uncommitted and name it once in the phase report; it never stops a gate or makes the tree unclean. - Simplicity. The smallest diff that passes is the target: every added line is one more for review to read and the next run to keep. Search the repo for an existing helper before writing one, and say in the ticket report what the search found. A new abstraction needs two live callers.
- Commit after each verified ticket. Wrap archives a run (
Status: done); folders stay. - Secret scan before every push.
gitleaks git --log-opts="@{u}..HEAD" --redact -v --no-banner(no upstream:origin/<primary>..HEAD);--redactkeeps the value out of the transcript. Receipts are the usual source: a live query or log with a token in it. Exit 0 → push. A finding → no push; name file, line and rule, and ask: ➡️ a remove it from the unpushed commits and rotate it (a real value has already been in the session) · b false positive: add its fingerprint to.gitleaksignore; a pattern that will recur (an ID field, a public token) gets an allowlist in.gitleaks.tomlinstead, extending the default rules, proven by a rescan where the pattern is gone and a planted key is still caught. Scanner missing → no push; ask: ➡️ a install it · b push unscanned, noted on the card. - A run artifact is committed only on a passing check. Chain it:
python3 <skill>/scripts/check-run.py <slug> && git commit .... A pipe such as| tailhides check-run's exit code, and a review once went out that cited files and shas that do not exist. Write an artifact only after the reads it reports on have returned.
Command index
Read the one reference for the command; status and next need only this file and ROUTING.md.
| Command | Reference in references/ |
|---|---|
brainstorm <slug>, improve <feature> - goal: <goal>, park [slug] | phase-0-brainstorm.md |
plan | phase-2-plan.md |
execute | phase-3-execute.md (+ tests.md) |
review (+ patch cycle) | phase-4-review.md |
wrap | wrap.md |
learn, log | learning-worklog.md |
todo [idea] | todo.md |
bootstrap [PRD.md] | bootstrap.md |
realign | realign.md |
Maintaining this skill is covered in MAINTAINING.md.