Skip to content
On this page

AI Coding Setup

How I structure worktrees, terminals, and windows to run several Claude Code sessions in parallel, plus the workflow I follow for anything non-trivial.

Worktree Layout

I run one git worktree per feature/ticket, laid out like this:

project-name/
├── .scratch/
├── A1/
├── A2/
└── A3/

Each A* folder is a separate worktree. The leading letter is a short project abbreviation, so I can tell worktrees apart across projects when several PhpStorm windows are open at once - A1 vs D1 vs U1, etc.

Setting one up: just ask Claude to create the worktree and adjust the app's ports (APP_PORT, VITE_PORT, FORWARD_DB_PORT, ...) so each worktree can run its own instance of the app side by side without port clashes.

.scratch/ sits once at the project root, next to the worktrees, not inside them. Every worktree gets a .scratch symlink pointing back to it, so exploratory notes and drafts survive regardless of which worktree you're currently in.

Statusline: pwd:port

A global Claude Code setting shows the last two path segments of the current directory in the terminal status line, plus the APP_PORT from .env if one is set:

personal-projects/A1:8081

This makes it obvious at a glance which worktree/port a given terminal is pointed at when you have many terminals open.

Goes into the statusLine key of the global ~/.claude/settings.json (applies to every project/worktree, since the port lookup happens per-directory anyway):

json
{
  "statusLine": {
    "type": "command",
    "command": "input=$(cat); dir=$(printf '%s' \"$input\" | jq -r '.cwd // .workspace.current_dir // empty'); short=$(printf '%s' \"$dir\" | awk -F/ '{n=NF; if (n>=2) print $(n-1)\"/\"$n; else print $n}'); port=\"\"; if [ -f \"$dir/.env\" ]; then port=$(grep -m1 '^APP_PORT=' \"$dir/.env\" 2>/dev/null | cut -d'=' -f2 | tr -d ' \\r\\n'); fi; if [ -n \"$port\" ]; then printf '%s:%s' \"$short\" \"$port\"; else printf '%s' \"$short\"; fi"
  }
}

What it does: reads cwd from the JSON Claude Code feeds the statusline command on stdin, shortens it to the last two path segments, and appends :<port> if the current directory has an .env with APP_PORT= set.

Nothing to adjust for a Laravel/Sail project - APP_PORT in .env is the Sail convention already used in Worktree Layout. Only touch the grep -m1 '^APP_PORT=' part if a project exposes its port under a different variable name or file (e.g. PORT= in a Node .env, or a docker-compose.yml instead).

Window Management (i3 + screen)

  • i3 manages the actual windows.
  • Inside i3, screen multiplexes several Claude Code sessions - typically 3-4 sessions per screen.
  • Around 10 screens open at a time, split across workspaces: 1-5 on the left, 6-9 + 0 on the right.

This gives a fast way to jump between many parallel work streams (across projects and worktrees) without hunting through window lists.

Workflow: Plan → Specs → Tickets → Implement

For anything non-trivial I follow the AI Hero workflow:

  1. Plan - agree on the overall approach with Claude first.
  2. Specs - turn the plan into specs.
  3. Tickets - break the specs into individual tickets.
  4. Implement - work through the tickets.

Claude never commits on its own. That keeps every change reviewable as an interactive diff/MR in the IDE before it lands.

Because the "implement" step already includes its own review pass and each ticket takes roughly 20-30 minutes end to end, it's usually worth working on 3-4 tickets in parallel - one per worktree (see Worktree Layout) - rather than strictly one after another.