Day 4

Multi-project and multi-feature workflow

You ship
4 or more features shipped in parallel, the public site as a second app, and your throughput measured.

What you'll build today

After Day 3, WorkBot takes requests through a form and an API, lists them, and counts them in an admin console. You shipped those features one ticket at a time with one Claude Code session, so you spent much of the day waiting while the agent worked.

Today you run 4 sessions at once. Each one works in its own worktree, a second checkout of the same repository on its own branch, so the agents never edit each other's files. You watch them side by side in Ghostty and step in when one needs a decision. Together they add a page for each request, status changes, filters, and the company's policies written as Markdown.

You also give Claude Code instructions that load only in the folder where they apply, and you start the public site as a second app. Along the way you learn to merge parallel work that collides. By the end, 4 more features are on production, the public site builds beside WorkBot, and you know whether parallel sessions are faster for you.

By the end of the day you can

  • Use git worktrees to run several Claude Code instances in parallel on the same repository
  • Set up Ghostty tabs and splits for work across several projects and features
  • Write effective CLAUDE.md files at the project level and the folder level
  • Ship 4 or more features in parallel in a single session

Topics

Git Worktrees

  • What worktrees are: several working directories from the same git repository
  • Why they matter for AI development: each Claude Code instance needs its own working directory
  • Creating a worktree for an existing branch: git worktree add ../feature-x feature-x
  • Managing worktrees: listing, removing, pruning
  • Naming worktrees and branches by one convention, so a team can tell them apart
  • Gotchas: the git state all worktrees share, lock files, and a separate node_modules in each worktree

Ghostty for Multi-Project Workflow

  • One tab or window per project, to switch quickly between different codebases
  • One split pane per feature, to watch several Claude Code instances at once. Zoom one split when it needs the whole tab
  • Notifications that tell you where to look, so you can work on something else while agents build. Ghostty bounces the dock icon and marks the tab title when an agent in a pane you are not watching needs input
  • Configuration in a file: keybinds for splits and tabs, committed with your dotfiles

Putting It Together: Worktrees + Ghostty + Parallel Claude Code

  • The full setup: create a worktree per feature, open each in a Ghostty split, and run Claude Code in each
  • Monitoring several agents: checking progress, answering their questions, reviewing their output
  • Merging parallel work: resolving conflicts when several features land

CLAUDE.md

  • Project-level CLAUDE.md: conventions, an architecture overview, common commands, project-specific instructions
  • Folder-level CLAUDE.md: context for one module. For example, src/app/api/CLAUDE.md describes the API route pattern
  • What to include: file naming conventions, import patterns, testing patterns, deployment instructions
  • What to leave out: the obvious, and information that changes often
  • Improving CLAUDE.md as you work: add what you learn, and edit the files with /memory

Prompt Engineering for Claude Code

  • Writing better prompts: say exactly what you want, give context, and name the files
  • When to use /compact: it summarizes a long session to free context
  • Context management: how Claude Code tracks the conversation, and when to start a fresh session
  • Advanced patterns: break a complex task into steps, use plan mode to agree on a plan before a large change, give examples
  • Getting more from each session: ask for explanations, ask for alternatives, iterate

Build

Features shipped today

  • WorkBot: 4 or more features shipped in parallel across worktrees, and the public site scaffolded as a second app in the same repository

Work on 2 projects, WorkBot and its public site:

  1. Create 3 or 4 worktrees for different features of WorkBot
  2. Set up a Ghostty tab with split panes, one Claude Code instance per worktree
  3. Write CLAUDE.md files for each project, one at the project level and at least one at the folder level
  4. Run all the Claude Code instances in parallel
  5. Ship 4 or more features in a single session
  6. Merge all the features, resolve any conflicts, and deploy

Track your throughput: the features shipped per hour with parallel agents, against one agent at a time.

Step by step

Set up worktrees and splits

Several agents can only work at once if each one has its own copy of the files, so the day starts there. A worktree gives each session its own folder and branch, while all of them share one repository underneath.

Study first

  • The git worktree commands add, list, remove and prune. Worktrees share one object store, and only the working files are separate.
  • Ghostty's layout for today, with one tab for the project and one split per worktree. Learn to zoom one split to fill the tab. A bell mark appears on a tab when an agent in a split you are not watching needs attention.
  • Claude Code's /compact, from Day 2, and when a fresh session works better than a long one.

Build

  1. Create one worktree per ticket, branched from main. In the reference run, the next 4 tickets from the Day 3 backlog are WB-12 to WB-15 (WB is the Linear team key), so the first command is git worktree add ../workbot-wb-12 -b wb-12 main. Do the same for WB-13, WB-14 and WB-15, and run pnpm install in each, because every worktree has its own node_modules.
  2. Open a Ghostty tab with 4 splits, and start a Claude Code session in each split, inside its worktree.
  3. Start each session with the same kind of brief. Give it the ticket id and its acceptance criteria, pasted or read through the Linear MCP (Model Context Protocol) server from Day 3, and the branch name. Tell it to run pnpm check and open the pull request when it is done.
  4. Watch for the bells. When a session asks for a decision, answer it, and when its context fills up, run /compact.

Done when

  • git worktree list shows 4 worktrees on 4 branches, and each split has a session working in one of them.
Technical notes
  • pnpm keeps one shared store, so an install in a new worktree writes links, not packages.
  • .env.local and .next are separate in each worktree too. Copy the env file over, and Next.js recreates .next on the next build or dev run.
  • Two dev servers cannot share port 3000, so run pnpm dev --port 3002 in the second worktree, and so on.

Write folder-level instructions

With 4 agents working in different parts of the code, the root instructions would grow long if they held every local rule. Claude Code loads the root CLAUDE.md at launch, and it loads a CLAUDE.md in a subdirectory the first time it reads or edits a file there. A rule that matters in one folder can therefore live in that folder.

Study first

  • How CLAUDE.md files load, which explains that root files load at launch, subdirectory files load on demand, and Claude Code joins them all together.

Build

  1. Write src/app/api/CLAUDE.md. Say that a route is a folder with route.ts, types.ts and route.test.ts, and that its schemas are the contract. List the status codes, and say that handlers call src/lib and hold no logic of their own.
  2. Write content/policies/CLAUDE.md once WB-15, in the next part, has created that folder. Say there is one policy per file, list the front matter fields, and describe how to write a policy.
  3. Add a line to the root AGENTS.md saying these files exist.

Done when

  • A route scaffolded with Day 2's /api-route skill has the 3 files that src/app/api/CLAUDE.md describes, and passes pnpm check.
  • A 9th policy file, written with the front matter that content/policies/CLAUDE.md describes, passes pnpm test, after WB-15 has added the first 8.
Technical notes
  • A subdirectory file loads only in sessions that touch that folder, so its rules take up no context anywhere else.
  • Keep each one under 10 lines, because a rule that applies to the whole repository belongs in the root file.

Build 4 tickets in parallel

These are the 4 tickets the sessions work on, and each one becomes its own pull request. WB-12, WB-13 and WB-14 all change the same module, src/lib/requests.ts, so expect conflicts when you merge them.

Study first

  • refresh() from next/cache, in the Next.js reference. A Server Action calls it to refresh the router in the browser, so the page shows the data the action changed.
  • The use cache directive and generateStaticParams. "use cache" caches reads of content that changes only with a deploy. generateStaticParams prerenders one page for each known slug, the name that identifies a page in its URL.

Build

  1. WB-12 adds the detail page. Build /requests/<id>, which shows the request in full with badges for team, priority and status, and answers an unknown id with a 404. Link each title on the list to its page.
  2. WB-13 adds status changes. On the detail page, add one button for each other status, and bind each button to a Server Action that updates the request and calls refresh().
  3. WB-14 adds filters. Show them on /requests?team=&status= as rows of links, so a filtered list has its own address, and parse the query with a schema that ignores unknown values.
  4. WB-15 adds policies. Write 8 company policies, such as expenses and travel, as Markdown files with front matter, and read and validate them in one module. List them at /policies, and render each one at /policies/<slug>.
  5. Merge the pull requests in order, one at a time. Before you open each later pull request, rebase its branch on main, and resolve the conflicts in the requests module by hand. They are small and expected.
  6. After the last merge, run git worktree remove on each folder, then git worktree prune.

Done when

  • All 4 pull requests are merged with CI green.
  • On production, a request's status changes from its page, a filtered list loads from its address, and a policy renders from its file.
A request's page
The detail page shows the request in full, with one button for each status it can move to.
Filtered requests
The list filtered to one team. The filters are links, so the address carries the filter.
The policies
In the reference run, 8 policies come from Markdown files, each owned by a team.
One policy
A policy page. The front matter shows above, and the typography plugin styles the Markdown body.
Technical notes
  • The status buttons share one form, and each button has its own formAction, setStatus.bind(null, id, status). The action checks the status against the schema's enum before it writes.
  • The filter schema uses .optional().catch(undefined) on each field. A query such as ?team=legal, which names no team, then shows the unfiltered list instead of an error.
  • The policy module reads the files inside "use cache" functions, so it parses a file once per cache lifetime, not on every request. generateStaticParams lists every slug, so the build prerenders a page for each policy.
  • react-markdown renders the body, and the typography plugin, @tailwindcss/typography, styles it through the prose class. Neither needs configuration.
  • The policy module refuses a path that is not a slug, such as ../package, before it reads any file.

Scaffold the public site

WorkBot also needs a public site that tells visitors what it does, and that site has different needs from the app. Add it as a second Next.js app in the same repository, with the same checks. The 2 apps share nothing yet, and Day 29 adds shared packages.

Study first

  • pnpm workspaces, for pnpm-workspace.yaml, the --filter flag, and how one lockfile covers every package.

Build

  1. Run create-next-app into site/ with --skip-install, name the app workbot-site, and give it port 3001 in its scripts.
  2. Add site to pnpm-workspace.yaml, and exclude it from the root tsconfig.json and ESLint config. Then make the root check script run pnpm --filter workbot-site check last.
  3. Build a landing page with the product in one sentence and 3 capabilities, and write a site/AGENTS.md that says what the site is and what it is not.

Done when

  • pnpm check at the root builds both apps, and pnpm --filter workbot-site dev serves the site on port 3001.
The public site
The public site's landing page shows the product in one sentence and 3 capabilities. Nothing on it needs a secret.
Technical notes
  • Each app has its own next.config.ts, tsconfig.json and ESLint config. The root ones exclude site/, so only one config checks each file.
  • The site has no database and no API routes, and nothing in it needs an environment variable.

Measure your throughput

The day's question is whether parallel sessions ship more features per hour than one session at a time. The site is a single feature of a different kind, so treat the comparison as a first measurement rather than a verdict.

Study first

  • How you timed the loop on Day 1, from creating a branch to merging its pull request, because today's numbers use the same clock.
  • The DevOps Research and Assessment (DORA) program's software delivery metrics, which group change lead time and deployment frequency under throughput. Change lead time runs from a commit to its deployment in production. Your clock starts at the branch instead, so it also counts the time spent building the change.

Build

  1. Measure the parallel time per feature. Take the time from starting the 4 sessions to merging the last of their 4 pull requests, and divide it by 4.
  2. Measure the sequential time for 1 feature, from starting the site's session to merging its pull request.
  3. Write both numbers, and the slowest step, in the Day 4 pull request descriptions.

Done when

  • You have 2 numbers, the time per feature in each mode, and the parallel number includes the time spent merging.

Resources