Your First Product with BoB
Your First Product with BoB
Section titled “Your First Product with BoB”The week above
/requirement. In BoB in One Day you handed the loop one requirement. Real products do not start with a requirement. They start with an idea. This week you take one small product from an idea to a tagged release: a vision, two capabilities, four requirements, a groomed cluster, a flight plan, two days of loop runs (some in parallel), and a release with a retrospective. Every command below comes from the product week explanation, which also covers why each layer exists.
What you will build
Section titled “What you will build”hello-links, a link shortener on Cloudflare Workers. POST /api/links with a URL
returns a short code, and opening /<code> redirects to the URL. By Friday it also
has a bearer token protecting the API and a visit count for each link.
The product is deliberately small, so the loop can finish two requirements in a day at Level 3. It is also real enough that the vision has something to say: who it is for, and what it will never do.
By Friday evening you will have:
docs/vision.md, the product’s written reason for existing;- two capability issues, each closed as
completedbecause every requirement under it closed; - four requirement issues, closed by the loop, each linked
Part ofits capability; - a flight plan issue with every item checked;
- an integration branch merged to
mainin one step; - a
v0.1.0tag, aCHANGELOG.mdand a GitHub Release; - a retrospective, plus one
decisionand onelessonissue.
Before you start
Section titled “Before you start”- Finish BoB in One Day first. This tutorial assumes you
have run
bob init,/requirementand/warp-driveonce and have read a chunk report. - Node.js and npm, for the Workers scaffold and the release tooling.
- A Cloudflare account is optional. The whole week runs against the local dev
server (
wrangler dev), and nothing is deployed. - tmux, for the parallel runs on Thursday.
bob forkchecks for it and names anything missing before it touches your repository. - About an hour of your time each day. Most of Wednesday and Thursday is the loop working while you do something else.
Issue numbers below assume a brand-new repository: the capabilities are #1 and #2,
the requirements #3 to #6, and the flight plan #7. If yours differ, use the
numbers your commands print.
Monday — the vision and the capabilities
Section titled “Monday — the vision and the capabilities”Stop 1. Create the project
Section titled “Stop 1. Create the project”Scaffold a Workers project, then let one command, bob ready --new, give it a
GitHub repository and wire it to BoB: the steps you took one at a time in BoB in
One Day.
bob doctorcd ~/projectsnpm create cloudflare@latest hello-linkscd hello-linksbob ready --newgit push -u origin HEADWhen npm create cloudflare asks, choose the Hello World example, Worker
only, TypeScript, yes to git, and no to deploying.
What you should see.
bob doctorends with a verdict line. Fix any drift it names before going on.- The scaffolder creates
hello-links/withwrangler.jsonc,src/index.tsand a first commit. bob ready --newcreates the privatehello-linksrepository and links it (--newbecause the directory already has files), wires.claude/, detects the stack from the Workers config and lands the manifest, then puts the project on bob viz. It ends withREADY, the bob viz URL and the next command.git pushpublishes the first commit.
What just happened. Provisioning read the code, not a questionnaire. The Workers config told it which registry items this project needs, so the Cloudflare tooling is already linked before you write a line.
Checkpoint.
bob readyprintsREADY, andgh repo viewshows thehello-linksrepository.
Stop 2. Write the vision
Section titled “Stop 2. Write the vision”Open Claude Code in the project (claude -a3) and run:
/vision/vision asks you questions: why the product exists, who uses it, where it is going,
what principles it keeps, and what it will not do. Answer briefly and honestly.
For hello-links, one owner shortening their own links, a good non-goal is “no user
accounts, no public sign-up”.
What you should see. A new docs/vision.md with sections for the why, the users,
the principles, the non-goals and a roadmap. The capabilities section is empty,
because none exist yet.
What just happened. The vision is a living document in the repository, not an
issue. It is never closed. Later commands read it: /capability traces each
capability back to it, and /groom notices when the vision implies something the
tracker does not have yet.
Checkpoint.
docs/vision.mdexists and names at least one non-goal. Commit it (git add docs/vision.md && git commit -m "docs: vision" && git push).
Stop 3. File two capabilities
Section titled “Stop 3. File two capabilities”A capability is one user-visible ability. hello-links has two:
/capability Short links/capability Manage linksRun them one at a time. For each one, /capability asks for user stories and
success metrics, then offers to write the requirements straight away. Say not
yet: you will write them tomorrow, once both capabilities exist.
What you should see.
- Two issues,
#1Short links and#2Manage links, each labelledcap, a priority (p2-highis fine) and anarea:label derived from the title:area:short-linksandarea:manage-links. - Each body lists user stories, success metrics and an empty requirements checklist.
What just happened. The capability sits between the vision and the work. It is
too big to build in one go and too specific to be a vision. Its area: label
matters later: every requirement you file under it inherits the label, so a whole
capability can be groomed, planned and run as one unit.
Checkpoint.
gh issue list --label capshows exactly two open issues, each with anarea:label.
Stop 4. Approve the capabilities
Section titled “Stop 4. Approve the capabilities”gh issue edit 1 --add-label approvedgh issue edit 2 --add-label approvedgh issue list --label capWhat you should see. gh issue list --label cap lists both capabilities, now
also labelled approved.
What just happened. Approving a capability is a scope decision: this ability belongs in the product, so break it into requirements. It is not an instruction to build. The loop never picks up a capability, only approved requirements. That is why approving both on Monday is safe: nothing runs until you approve the work under them.
Checkpoint. Both capabilities are open and labelled
capandapproved.docs/vision.mdis committed.
Tuesday — requirements, a groom and a flight plan
Section titled “Tuesday — requirements, a groom and a flight plan”Stop 5. Write four requirements
Section titled “Stop 5. Write four requirements”In Claude Code, file one requirement per line, each with its parent and, where it applies, what it waits for:
/requirement Create a short link (POST /api/links). Part of #1./requirement Follow a short link (GET /:code, 302 or 404). Part of #1. Depends on #3./requirement Protect the API with a bearer token. Part of #2./requirement Count visits and show them (GET /api/links/:code). Part of #2. Depends on #4 and #5./requirement drafts the acceptance criteria from your one line and shows them to
you. Tighten any criterion you could not test. For “Create a short link”, a good
criterion is “a POST with an invalid URL returns 400 and stores nothing”. When it
asks whether the requirement is approved, say yes.
What you should see.
- Issues
#3to#6, each labelledreq, a priority,approved, and thearea:label inherited from its capability. - Each body ends with
Part of #1orPart of #2.#4and#6also carry theirDepends online. - The capabilities’ requirement checklists now list their children.
What just happened. The two links are what later steps read mechanically.
Part of lets BoB derive a capability’s status from its children. Depends on
becomes an ordering edge in tomorrow’s flight plan, so #3 and #5 can run at the
same time while #4 waits for #3.
Checkpoint.
gh issue list --label req --label approvedlists four issues, andgh issue view 6shows bothPart of #2andDepends on #4 and #5.
Stop 6. Groom the cluster
Section titled “Stop 6. Groom the cluster”Four requirements written in one sitting always disagree in small ways. One says
links, another says urls. One returns JSON errors, another plain text. Groom
them together:
/groom area:short-links/groom area:manage-linksWhat you should see. A change report for each area: the requirement bodies it reconciled, the dependencies it confirmed or added, and a readiness verdict for each requirement. Groom edits issues and comments on them. It never touches code.
What just happened. Grooming is the last human-speed step before the loop runs at machine speed. Anything ambiguous now becomes a question the loop has to stop and ask on Wednesday, so read the report and fix what it flags.
Checkpoint. Every requirement is reported ready. A requirement the report marks not ready names what is missing, usually a vague acceptance criterion. Fix the issue body and run the same
/groomline again.
Stop 7. Build the flight plan
Section titled “Stop 7. Build the flight plan”bob plan build --from approved --branch week/hello-links --name "hello-links week one"What you should see. The command prints the new plan’s issue number (#7). Open
it on GitHub: a checklist of #3 to #6 in run order, with depends_on edges on
#4 and #6, and week/hello-links declared as the integration branch.
What just happened. The plan is the week’s order, written down once. On Wednesday the loop consumes the plan instead of rediscovering the queue at every step. Because the plan is an issue, you can reorder it or drop an item by editing it, and the loop follows the edit.
Checkpoint.
gh issue list --label flight-planlists one open plan, and its body names all four requirements.
Stop 8. Check the plan
Section titled “Stop 8. Check the plan”bob plan status 7What you should see. #3 and #5 are runnable (nothing blocks them), while
#4 and #6 are waiting on their dependencies. The critical path is three waves:
#3 and #5 first, then #4, then #6.
What just happened. Nothing ran. bob plan status only reads the plan and the
issues it names. It is the question to ask at any point this week: what can run now,
and what is it waiting for? The same view drives the loop: an item the status calls
waiting is never started.
Checkpoint.
bob plan status 7shows four open items, two of them runnable, and namesweek/hello-linksas the integration branch. If an item is missing, it was not labelledapproved: approve it and run thebob plan buildline again. The build is idempotent and refreshes the same plan.
Wednesday — the dev environment and the first wave, in parallel
Section titled “Wednesday — the dev environment and the first wave, in parallel”Stop 9. Bring the dev environment up
Section titled “Stop 9. Bring the dev environment up”bob dev up --verbosebob dev healthWhat you should see.
bob dev up --verbosereports that it generated adev.json, because the project has none yet. It then startswrangler devon a port from the project’s band, runs a health check, and ends with the local URL.bob dev healthrepeats the health check alone and reports healthy.
What just happened. dev.json is now the declared dev environment: the server
command, the port and, as soon as the loop adds a D1 table, the migrations and seed
data. Commit it. From now on every loop run starts by running bob dev up itself and
checks health between chunks, so a requirement is tested against the running app,
not only in unit tests.
Checkpoint. Opening the URL
bob dev upprinted shows the Worker’s Hello World response, anddev.jsonis committed onmain.
Stop 10. Fan out the first wave
Section titled “Stop 10. Fan out the first wave”Tuesday’s plan said #3 (create a link) and #5 (protect the API) depend on nothing.
Run them at the same time:
bob fork fork --from-flightplan 7 --dry-runbob fork fork --from-flightplan 7The --dry-run line comes first so you can check the wave before anything is created:
it lists the sessions it would spawn, one branch per requirement. The second line
spawns them.
What you should see.
- The dry run names exactly two items,
#3and#5.#4and#6are missing because they are still waiting on a dependency. - The real run creates two git worktrees next to your checkout, one tmux session
with a window per worktree, and a warp-drive session in each window, scoped with
--issueto its own requirement. It prints the tmux session name and the line to attach to it.
What just happened. Each session is an ordinary warp-drive run (plan, chunks, tests, commits, chunk reports), but in its own worktree, so the two never edit the same checkout. Neither can drift into the other’s requirement, because each is scoped to one issue. Attach to the tmux session to watch both at once, or leave them and come back after lunch.
Checkpoint.
bob fork statuslists two worktrees, each with a live warp-drive phase.
Stop 11. Collect the wave
Section titled “Stop 11. Collect the wave”When both windows report their requirement complete:
bob fork statusbob plan status 7bob fork drop --allWhat you should see.
bob fork statusshows both sessions finished.bob plan status 7now shows#3and#5done and#4runnable.#6still waits for#4.bob fork drop --allremoves both worktrees and their tmux windows. It refuses a worktree with uncommitted changes, and it never deletes a pushed commit.
What just happened. Two requirements landed in roughly the time of one. The plan did not need to be told: a closed issue counts as a finished dependency, so the next wave became runnable on its own.
Checkpoint.
gh issue view 3andgh issue view 5are closed, each with chunk reports linked, andbob plan status 7lists#4as runnable.
Thursday — the integration branch and finalize
Section titled “Thursday — the integration branch and finalize”Stop 12. Run the rest of the plan
Section titled “Stop 12. Run the rest of the plan”#4 and #6 depend on each other’s work, so they run one after the other, on the
integration branch the plan declared. Start Claude Code at Level 3 and hand it the
plan:
claude -a3/warp-drive --flightplan 7In a second terminal, watch it:
bob warp status --watchWhat you should see.
- The run’s first lines say it opened the stream
week/hello-linksfor flight plan#7, andbob warp statusshowsflight-plan #7 → stream week/hello-links. - The loop runs
bob dev upbefore the first chunk, then works#4, then#6, filing a chunk report per commit and ticking each plan item as its requirement closes. - When no plan item is left, the run ends by itself and files a session summary. It never picks up work outside the plan.
What just happened. A flight-plan run consumes the plan in order and nothing else.
Because the plan declares an integration branch, each finished requirement was merged
into week/hello-links instead of main. main still has Wednesday’s work and none
of Thursday’s.
Checkpoint.
bob plan status 7shows all four items done, andgit log --oneline main..week/hello-linkslists Thursday’s commits.
Stop 13. Finalize
Section titled “Stop 13. Finalize”bob warp finalize --dry-runbob warp finalizeWhat you should see.
--dry-runprints the exact git commands finalize would run: bring the branch up to date withmain, merge it, push. Nothing is changed.- The real run performs them at Level 3 and clears the stream. At Level 2 it opens one pull request for the whole branch instead, for you to review and merge.
What just happened. Thursday’s two requirements reached main together, in one
reviewable step, so main never had visits recorded without anywhere to show them.
Checkpoint.
git log --oneline origin/mainincludes Thursday’s commits, andbob warp session statusreports no active stream.
Stop 14. Check the capabilities are complete
Section titled “Stop 14. Check the capabilities are complete”/groomgh issue view 1gh issue view 2What you should see. /groom reports that both capabilities have every child
requirement closed, and closes each one with the completed label. gh issue view 1
and gh issue view 2 then show them closed, labelled completed.
What just happened. You never closed a capability yourself. Its status is derived
from its requirements: in progress while some are open, complete when all are closed.
A capability closed without completed would mean it was abandoned. The reconciler
never produces that state, so the label is a trustworthy record of what shipped.
Checkpoint. Both capabilities are closed with
completed, and the flight plan#7has every item checked.
Friday — release, retrospective and journal
Section titled “Friday — release, retrospective and journal”Stop 15. Cut the first release
Section titled “Stop 15. Cut the first release”git checkout main && git pullnpm install --save-dev commit-and-tag-versionnpm pkg set scripts.release=commit-and-tag-versiongit commit -am "chore: add the release script" && git pushbob release --dry-runbob release --channel stableThe first four lines add the release tooling once: commit-and-tag-version computes
the version and writes the changelog, and the release script is how bob release
finds it. Then look before you leap: --dry-run runs every safety gate and shows
what the release would do without doing it.
What you should see.
bob release --dry-runpasses its gates (onmain, a clean tree,HEADequal toorigin/main) and previews the new version. Withfeat:commits since the scaffold, that is a minor bump to0.1.0.bob release --channel stablecommitschore(release): 0.1.0 [skip ci]with a newCHANGELOG.md, tagsv0.1.0, pushes both, and publishes a GitHub Release whose notes are the new changelog section.
What just happened. The version came from the commit messages the loop wrote all
week. Conventional Commits are not a style preference in BoB: they are what makes the
release mechanical. If the gates had refused (a dirty tree, or main behind
origin), the release would have named the reason and changed nothing.
Checkpoint.
gh release view v0.1.0shows the release, andCHANGELOG.mdonmainlists the week’s features.
Stop 16. Hold the retrospective
Section titled “Stop 16. Hold the retrospective”/retrospective/retrospective walks you through the week: what went well, what did not, and what
to change. Answer honestly. The first flight plan usually teaches you something about
how you wrote dependencies.
What you should see. A Retrospective — <date> issue labelled session-summary,
plus one retro-action issue per action item you agreed.
What just happened. Action items are issues, not bullet points in a document. Next
week’s /retrospective reads the open retro-action issues first and asks what
happened to each, so nothing agreed on Friday is silently forgotten.
Checkpoint.
gh issue list --label retro-actionlists your action items.
Stop 17. Record one decision and one lesson
Section titled “Stop 17. Record one decision and one lesson”/journal decision bearer-token-not-accounts/journal lesson plan-dependencies-before-forkinggh issue list --label decisiongh issue list --label lessongh issue list --label retro-actionPick a real decision from the week. “Bearer token instead of user accounts” is the one the vision’s non-goal forced. Pick a real lesson too. “Declare dependencies before forking” is a common first one.
What you should see.
- A
decision: …issue labelleddecision, with context, the decision, the alternatives considered and the consequences. - A
lesson: …issue labelledlesson, ending with a Tooling Potential rating. - The three
gh issue listlines show where each record lives: decisions and lessons are knowledge, and retro actions are follow-up work.
What just happened. Reports are execution records, so they say what happened.
Decisions and lessons are knowledge records, so they say what to do next time. BoB
keeps the two apart: a chunk report is never labelled lesson, which keeps
--label lesson a list worth reading months from now.
Checkpoint.
gh issue list --label decisionandgh issue list --label lessoneach show your new issue, and the week’s tracker has no openreqleft.
Where you are now
Section titled “Where you are now”In one week you went from an idea to a released product, and every step left a
record: the vision in the repository; the capabilities, requirements, plan, reports,
decision, lesson and retro actions in the tracker; and the version in a tag. Next
week starts where this one ended. Run /what-next to see what is approved, or add a
third capability and plan it the same way.
Where to go next
Section titled “Where to go next”- A Week in the Life of a BoB Product: the same week, told around why each layer exists.
- Flight plans: reordering, gating and refreshing a plan.
- Parallel work with cdfork: waves, worktrees and cleanup.
- Warp-drive: every phase, flag and gate of the loop.
- Versioning: release channels, automatic releases on
merge, and
bob releasein depth.
Next tutorial: Where BoB Talks to You — Try each place BoB reaches you once — terminal, tmux, the desktop app, Telegram, claude.ai remote control and iBoB — then choose one by situation.