Skip to content
Michi v2026.05.20
Save the Tokens

Implement a Task or Story

You have one bounded change to make — a new flag, a small feature, an enhancement to something that already works. The tool is /michi-workshop. The same six phases as any Michi work apply — Explore → Brainstorm → Plan → Execute → Verify → Document — compressed into one pass.

  • Explore: Read the relevant code before writing any.
  • Brainstorm: Settle the approach. Wrong approach found mid-implementation costs rework.
  • Plan: Write down what you’ll do, agree on it, and answer: how will I know it’s done, how will I verify it, how will I know nothing broke.
  • Execute: TDD — failing test first, then implementation, then full suite.
  • Verify: Run the full suite, not just the new test.
  • Document: Commit message for trivial work; journal entry for anything with a non-obvious decision.

Use /michi-workshop for a bounded change you can take from intent to done in one session. If Explore reveals the work is larger — a design decision, a schema change, multiple subsystems — escalate to /michi-planning.

This is an abridged transcript of a workshop session adding a complete command to a CLI todo app. The CLI talks to a separate API backend — orienting across that boundary is part of the work. What follows shows the shape of a workshop conversation — orient, plan, course-correct, implement, verify, debrief — not every step.

You: /michi-explore peek

Agent: Oriented at M-level. The todo app has two parts: a CLI front-end and an API backend — a small REST service over a database. The CLI commands live in src/commands/; none of them touch the database directly, they all go through src/api-client.js. Stable codebase — recent work added list filtering and due-date sorting, no open epics. What would you like to work on?

You: I want to add a complete command to the todo CLI — mark a todo as done. /michi-workshop

Agent: Workshop mode. Let me orient first.

I have enough context. Here’s what I found:

  • Commands: src/commands/*.js, one file per command, each registered with Yargs.
  • A todo has id (UUID), title, status (open or done), and an optional list name.
  • The CLI reaches the backend only through src/api-client.js. The API already exposes PATCH /todos/:id for partial updates, and status is a writable field.
  • So this is a CLI-side change — a new command calling an endpoint the API already has. No backend change.
  • Closest model to follow: delete.js — resolves the target, calls the API client, reports.

Surface assumptions: complete sets status: "done" via PATCH. A todo that is already done is a no-op — report it, don’t error.

Two clarifications before planning: should complete accept more than one todo at once? And is completing a todo low-stakes enough to just do it, or do you want a confirmation step?

You: Multiple, yes. No confirmation — completing a todo is reversible and low-stakes, just do it.

Agent: Got it. Here’s the concrete plan:

complete <id...> — one or more todo ids as positional arguments. For each id: fetch the todo, PATCH status: "done" if it is open, skip with a note if it is already done, print an error line if the id is not found. One result line per id; an unknown id does not abort the rest.

Tests cover: a single id, multiple ids, an already-done todo (no-op), an unknown id (non-fatal error), and the API-client call shape.

Verification: full CLI test suite green, plus a live run against the dev API marking a real test todo done.

You: That works — one change. Make it --id (repeatable) instead of positional ids. I want to add a --list <name> selector later so I can complete a whole list at once, and mixing positional ids with a named selector gets awkward. So complete --id abc --id def, with room for --list.

Agent: Sensible revision — updating the plan:

  • --id <uuid> (repeatable) replaces the positional ids; at least one selector required.
  • The handler resolves the list of target ids first, then runs a per-id complete loop — so a --list selector can be added later by feeding the same loop, no rework.
  • Everything else holds: already-done is a no-op, an unknown id is a non-fatal error line.

Starting implementation.

[The agent reads delete.js as the reference model, creates complete.js and __tests__/complete.test.js, adds completeTodo() to the API client, registers the command in the Yargs entry point, and writes 11 tests covering the plan’s cases. Full suite: 64 CLI tests, all green. Lint clean on changed files.]

Agent: 11 new tests, all green. 64 CLI tests total, all green. Lint clean on changed files. Running the live check now.

Agent: Live run against the dev API: complete --id <test-todo-id> marked the todo done; a second run on the same id reported “already done” and made no PATCH call; an unknown id printed an error line and exited cleanly.

Proposed commit message: feat(cli): add complete command — --id (repeatable); marks todos done via the API; already-done is a no-op, unknown id is non-fatal

You: /michi-debrief

Agent: This is small, workshop-scale work — I’ll keep the debrief light: a short journal entry, no separate artifact. What it captures: the complete command shipped; the decision to use --id over positional args and why (room for a later --list selector); and the resolve-then-loop handler shape that makes --list a clean drop-in. STATUS.md re-read cold — nothing stale from this change. The --list selector is logged as a natural next workshop.

Debrief done — journal entry in.

You have one thing to build. Not a multi-milestone epic — just a bounded change: a new flag, a small feature, an enhancement to something that already works. You want to take it from intent to done in a single focused pass, without ceremony that doesn’t earn its place.

This is the task or story use case. The tool is /michi-workshop. The cycle is the same six phases as any other Michi work — Explore → Brainstorm → Plan → Execute → Verify → Document — compressed into one pass.

Workshop doesn’t skip the cycle. It compresses it. Here’s what each phase looks like at task scale.

Before writing a line of code, read the relevant code. Understand where this change lives, what depends on it, what conventions the surrounding code follows.

For a bounded task this is usually a short pass — a few files, a few minutes. But it’s not skippable. The most common reason a small change balloons into a larger one is that the implementation started before the context was clear. Explore is the antidote.

Workshop calls this “Orient.” No separate /michi-explore session needed — the orient pass is built into the workshop rhythm.

Once you know where you’re working, settle how you’ll do it. This is usually brief — a moment, not a phase. What’s the interface change? What’s the data shape? Does this touch anything load-bearing?

If the approach isn’t obvious, think it through explicitly before planning. A wrong approach discovered mid-implementation is much more expensive than one caught here.

Plan — state what you’ll do and get agreement

Section titled “Plan — state what you’ll do and get agreement”

Write down what you’re about to do and confirm it before you start. For small work this might be three bullets. For a more complex task it might be a short list of numbered steps with an explicit scope boundary.

Answer three questions up front:

  • How will I know it’s done? — the acceptance criteria
  • How will I verify it? — the check you’ll run
  • How will I know nothing broke? — the regression check

These three questions are not formality. They are what separates a workshop from a guess. If you can’t answer them before you start, you haven’t finished planning.

The plan-and-agree step also gives the human a chance to catch misinterpretations before the code is written. A misread scope caught in the plan costs seconds. The same misread caught after implementation costs rework.

Implement against the plan. Write the test first, then the code that makes it pass.

Keep the loop tight: write a test, make it pass, check nothing else broke. Don’t batch changes. The goal is a continuous green baseline — every small step is verified before the next one starts.

Log decisions as you make them. When you choose one approach over another, write it down — in the journal, in the commit message, or in a ## Decisions block if the plan warrants it. Small decisions feel obvious in the moment and disappear fast.

Verify — run the suite, not just the new test

Section titled “Verify — run the suite, not just the new test”

When implementation is done, the verification question is not “does my new test pass.” It’s “does everything still work.”

Run the full test suite. Check the three questions you answered in Plan. If the check you committed to requires a specific command or setup, run it — don’t substitute a simpler proxy.

“Unit tests pass” is not “nothing broke.” Level A (automated) verification is necessary but often not sufficient. A bounded change to a feature with integration touchpoints may need a quick manual check. Run it.

For trivial work, a good commit message is enough. For anything with a non-obvious decision or a tricky edge, write a journal entry: what you built, what you decided, what you discovered.

The journal entry doesn’t need to be long. The goal is that a future session — yours or anyone else’s — can read it and not re-discover what this one learned.


A new capability (a flag, an endpoint, a command that didn’t exist) means you’re defining an interface as well as implementing one. Explore often includes thinking through the interface: what name, what arguments, what errors, what docs. Plan should capture the interface contract explicitly.

A small enhancement to existing code means the interface is mostly fixed — you’re extending or adjusting behavior. Explore focuses more on understanding the existing implementation than on designing a new surface. Still state the intended behavior change explicitly in Plan.

Low C/U tasks are common and bounded — adding a parameter to a function you know well, extending a config file, wiring a new route to an existing handler. Workshop flows naturally; the cycle is fast.

High C/U tasks are bounded in scope but load-bearing or unfamiliar. A small change to a payments module, an edit in a subsystem you’ve never touched, a change to shared infrastructure — these are high-C/U even if the change is small.

Workshop still applies, but tighten the posture: shorter turns, more checkpoints, explicit interpretation checks before each edit. Confirm the approach with the human before implementing. Don’t assume a common interpretation of an unfamiliar pattern — clarify it.

The heuristic: workshop is about ceremony, not risk. Less ceremony is fine. Less rigor is not.


Scope creep. “While I’m in here, I’ll also fix…” A bounded change stays bounded. When you notice related work, surface it — “I see X while implementing Y; do you want that addressed?” — and let the human decide. Don’t silently expand the scope. Don’t silently skip it either.

Not escalating when the work outgrows the workshop. If Explore reveals that this “small change” requires a design decision, a schema migration, or changes to multiple sub-systems, that’s an epic, not a workshop. Self-escalation is the correct move: stop, flag it, switch to /michi-planning. Workshop scope is not a commitment to stay in workshop.

Skipping the regression check. The most common shortcut. Running only the new test and calling it done. The full suite catches things the new test can’t — interactions with existing behavior, shared state assumptions, edge cases in adjacent code. Run it.

Docs or analysis instead of code. If asked to build, build. A workshop that produces a plan doc or a research note instead of the working change has not delivered the use case. Research and exploration have their own use case — see the Research and Explore guide.


A developer is adding a --dry-run flag to a CLI tool that processes files in bulk. The change is bounded — one flag, one behavior branch — but the tool is in active use.

Explore: Read the argument parsing code, the main processing loop, and the output formatter. Understand what “doing nothing” looks like in context — is dry-run a no-op on I/O, or does it run the processing and skip the write? Find out before planning.

Brainstorm: Settle the semantics. Dry-run runs the full processing pipeline, skips the file writes, and prints what would have changed. That’s the contract.

Plan: State it: add --dry-run flag to the CLI args, thread a dryRun boolean through to the write step, substitute a log call for the write when dryRun is true. Acceptance criteria: --dry-run produces expected output with no files modified. Regression check: full suite.

Execute: TDD. Write a test that invokes the CLI with --dry-run and asserts no files were written. Watch it fail. Implement the flag and the branch. Watch it pass. Run the full suite.

Verify: Full suite green. Manual check: run the tool on a test directory with --dry-run, confirm output matches expectation, confirm no files changed.

Document: Commit message captures the interface contract. Journal entry notes the dry-run semantics decision (full processing, skip writes) — that interpretation wasn’t obvious and may come up again.

Total time: one focused pass. No planning doc needed. The journal entry is two paragraphs.


Workshop is for bounded work. Escalate to the full epic cycle when:

  • The scope expands during Explore or Brainstorm into multi-phase work
  • The change requires a design decision that needs human alignment before any code
  • The implementation reveals a deeper problem (a design flaw, a missing abstraction, a data model issue)
  • The task is high-C/U and the stakes are high enough that short turns and checkpoints aren’t enough

Escalating is not a failure. It’s the correct response to discovering that the work is larger than it appeared. Switch to /michi-planning, plan the milestone properly, and run the full cycle.

See the Epic or Project guide for how the full cycle works.