# Daily developer workflow: Things3, one worktree per task, Claude Code > [!summary] TL;DR > Capture everything in Things3 (Monday query: `P0 + High Mental Energy`), isolate each task as one git worktree plus one tmux session plus one Claude Code session, and gate every change with `make check` (`gofumpt`, `goimports`, `golangci-lint`, `go test -race -count=1 ./...`). The shell function `cf` grew into `af`, a Go CLI that manages the worktree-tmux-agent triple as a workstream with a suspend/resume/done lifecycle. The AI's output is a draft; the test suite is the ground truth. ## Key points - This is a snapshot of the version of the setup that works in May 2026. - Everything possible goes into Things3, a capture-first inbox triaged on weekends, not a real-time tracker; the inbox currently holds around 970 items. - Tags do the actual work: `P0` / `P1` / `P2` (because "Today" can't be trusted; every snoozed thing looks like today), `High Mental Energy` / `Low Mental Energy`, and role tags (`architect`, `coder`, `mentor`, `communicator`, `researcher`) for batching context. - The query opened on Monday morning: `P0 + High Mental Energy`. Everything else can wait. - A task is a branch, and a branch gets its own file tree and its own AI conversation. - Git worktrees check out one branch per directory at `~/Workspace/.worktrees/<repo>/<branch>/`; tmux runs one named session per task. - Claude Code gets a deterministic session ID (uuid5 over `repo/branch`), so the same task always resumes the same conversation, even after a reboot. - `cf issue-42` does the whole setup, `cfr` resumes, `cfd` tears it down; the shell function is now growing a Go successor called `af`. - `af` calls the worktree-plus-tmux-plus-agent triple a workstream; state lives at `~/.local/share/af/v1/sessions/<name>/state.toml`, so there are no hidden tmux env vars and no fragile shell state. - The worktree layout, including subagent sub-worktrees at `<branch>--<slot>` on sibling branches, is pinned in ADR-038; the multiplexer is tmux-only; agents are `claude`, `pi` (default), or `codex` behind a single Go interface. - `make check` runs `gofumpt`, `goimports`, `golangci-lint` (every linter on, no exceptions), and `go test -race -count=1 ./...`. If any of it is red, the work isn't done. - Claude Code accelerates the middle TDD step; the AI's output is a draft and the test suite is the ground truth. No unread code ships. - Two Obsidian vaults (personal and work, PARA-style) are searched with `qmd`: BM25 keyword search, vector embeddings, and LLM reranking, via CLI or MCP. - `af`'s core is implementation-complete and runs the day; heavy development is in agent-session sync between VM and host, PR-state TTL caching, and an `af review` command (ADR-073). - `af` is single-user, single-machine, and not packaged for release. ## Capture: Things3 Everything possible goes into Things3. It's a capture-first inbox triaged on weekends, not a real-time tracker. The inbox currently holds around 970 items, which is somewhere between "honest capture" and "avoidance." The tags do the actual work: - `P0` / `P1` / `P2`: I don't trust "Today" because every snoozed thing looks like today. - `High Mental Energy` / `Low Mental Energy`: important-but-hard tasks die when you lie to yourself about which is which. - Role tags (`architect`, `coder`, `mentor`, `communicator`, `researcher`): useful for batching context. The query I open on Monday morning: `P0 + High Mental Energy`. Everything else can wait. ## Isolation: one worktree per task A task is a branch, and a branch gets its own file tree and its own AI conversation: - Git worktrees check out one branch per directory at `~/Workspace/.worktrees/<repo>/<branch>/`. - tmux runs one named session per task. - Claude Code gets a deterministic session ID (uuid5 over `repo/branch`), so the same task always resumes the same conversation, even after a reboot. This started as a shell function called `cf` (claude-focus), documented in [[resources/documentation/Claude Focus Workflow|Claude Focus Workflow]]. `cf issue-42` does the whole setup; `cfr` resumes; `cfd` tears it down. The shell function is now growing a Go successor called `af` (agentic-flow / automatic-flow / as-fuck, pick your mood). Same job, but with proper lifecycle semantics, layered config, and a test suite instead of accumulating bash edge cases. `af` calls the worktree-plus-tmux-plus-agent triple a **workstream**. The lifecycle commands: ``` af create issue-42 → active af suspend issue-42 → suspended (tmux down, VM destroyed if any) af resume issue-42 → active again af done issue-42 → completed (or abandoned) ``` State lives at `~/.local/share/af/v1/sessions/<name>/state.toml`, so there are no hidden tmux env vars and no fragile shell state to babysit. The worktree layout, including subagent sub-worktrees at `<branch>--<slot>` on sibling branches, is pinned in ADR-038. Multiplexer is tmux-only; agents are `claude`, `pi` (default), or `codex` behind a single Go interface. `af`'s core is implementation-complete and runs my day. The heavy development is in newer areas: agent-session sync between VM and host, PR-state TTL caching, and an `af review` command (ADR-073) that drives a configurable PR review through any agent. ## Development: TDD with Claude as draft generator Inside a worktree, the loop is intentionally boring: 1. Write the failing test. 2. Write the minimum implementation. 3. Refactor. 4. Run `make check`. `make check` runs `gofumpt`, `goimports`, `golangci-lint` (every linter on, no exceptions), and `go test -race -count=1 ./...`. If any of it is red, the work isn't done. Claude Code accelerates the middle step: I describe the problem, it sketches an approach, I push back on the sketch, it implements, I read every diff. The AI's output is a draft; the test suite is the ground truth. I don't ship code I haven't read. For multi-issue work, `af` spawns subagents in their own sub-worktrees so they don't fight over files. Overkill most days; essential a few times a month. ## Notes: Obsidian plus qmd Two Obsidian vaults, personal and work, structured PARA-style. I search across them with `qmd`, a local-first tool run via CLI or MCP that combines BM25 keyword search, vector embeddings, and LLM reranking. In practice it's `grep` for a corpus I can't remember the shape of: "find the note where I was thinking about GLS leak detection" gives three results, pick the right one, full document in hand. The piece not built yet: `af create` should stub out a note per workstream in the work vault, linked from `state.toml`. Right now I keep the link manually, which means I sometimes don't. ## What is still rough - Inbox triage. Capture is working; triage is not. No tool fixes this, only doing it does. - `af` and `cf` overlap. Both exist on my machine; long-lived `cf` sessions are not migrated to `af` yet, so I run both. - Obsidian linking is designed but not implemented. - Notes-to-blog pipeline. Getting from a good Obsidian note to a published post has enough manual friction that this post is its own counterexample: three drafts and a slop-cleaning pass before shipping. `af` is single-user, single-machine, and not packaged for release. It solves my problem and the design is settled enough that I'd rather build the remaining features than productize the parts that work. ## FAQ ### How do I keep AI coding tasks from interfering with each other? One task, one branch, one worktree, one tmux session, one agent conversation. Worktrees check out one branch per directory at `~/Workspace/.worktrees/<repo>/<branch>/`, and for multi-issue work `af` spawns subagents in their own sub-worktrees so they don't fight over files. ### What is a workstream in af? The worktree-plus-tmux-plus-agent triple. `af create` makes it active, `af suspend` takes it down (tmux down, VM destroyed if any), `af resume` brings it back, `af done` completes or abandons it. State lives at `~/.local/share/af/v1/sessions/<name>/state.toml`. ### How does af resume the same Claude Code conversation after a reboot? Claude Code gets a deterministic session ID computed as uuid5 over `repo/branch`, so the same task always resumes the same conversation, even after a reboot. ### What does make check run? `gofumpt`, `goimports`, `golangci-lint` (every linter on, no exceptions), and `go test -race -count=1 ./...`. If any of it is red, the work isn't done. ### How do you search across two Obsidian vaults? Two PARA-style vaults, personal and work, searched with `qmd` via CLI or MCP: BM25 keyword search, vector embeddings, and LLM reranking. It's `grep` for a corpus you can't remember the shape of. ### Is af available to install? No. `af` is single-user, single-machine, and not packaged for release. It solves one person's problem, and the design is settled enough that the remaining features are worth more than productizing the parts that work. ### Should I still read every diff when Claude Code writes the code? Yes. The AI's output is a draft; the test suite is the ground truth. I don't ship code I haven't read. ## Related - [[resources/documentation/Agents/Agents Workflow|Agents Workflow]] (series hub) - [[resources/documentation/Agents/Agents - One Workstream per Task|One Workstream per Task]] (one workstream per task) - [[resources/documentation/Agents/Agents - Plan First, Fresh Sessions, Write It Down|Plan First, Fresh Sessions, Write It Down]] (the on-disk canon: `PROGRESS.md`, `TODO.md`, `CLAUDE.md`) - [[resources/documentation/Agents/Agents - Second Brain with Obsidian and AI|Second Brain with Obsidian and AI]] (the Obsidian and `qmd` retrieval side) - [[resources/documentation/Claude Focus Workflow|Claude Focus Workflow]] (the `cf` command this system grew out of) ## Sources