Claude Code setup

How I actually run Claude Code

One folder for everything, a repo to coordinate it, a box that keeps running when I close the laptop, and the guardrails that catch mistakes before they ship.

Foundation

One folder, one repo to coordinate it

Every project lives under one folder. A separate ops/ repo tracks the others — which machines exist, which service each dependency lives in, and one card per active project, updated the moment something real changes.

~/dev/
~/dev/
├── project-1/
├── project-2/
├── project-3/
└── ops/
    ├── hosts.md          every machine, how to reach it
    ├── services.md       every dependency, where its key lives
    ├── projects/
    │   ├── project-1.md  stack, deploy step, open items
    │   └── project-2.md
    ├── docs/
    │   └── incidents.md  forensic history, kept separate
    └── claude-config/    symlinked into ~/.claude — next

Config topology

Rules that live in one place, or none at all

Shared configcurrent setup
  • + One edit updates rules, hosts, and service maps everywhere
  • + Ops knowledge lives in one place, not scattered per repo
  • − Depends on the symlink existing
  • − Can't be handed off without carrying the ops repo
Isolated project
  • + Fully portable — clone it anywhere, no external dependency
  • + Safe to open-source without exposing infra notes
  • − Rules must be duplicated by hand, and will drift
  • − Loses the habit of routing questions back to one source

Mechanism

What's actually loaded, and when

Always loadedglobal CLAUDE.md, hosts.md + services.md, memory index — every session
Scopedthis project's card, auto-loaded — other projects' cards only if a task asks
On demandCHANGELOG.md, docs/incidents.md — opened only when a task needs them
Memory layertyped memory files, cross-cutting, opened only when relevant

The baseline is small on purpose. Adding a sixth project adds one more on-demand card, not six more always-loaded files.

In practice

A schema change, three projects away

Task

Change project-1's schema

services.md

"project-2 reads project-1's DB directly"

already documented

Flagged

project-2's dashboard — at risk

Clone and explore project-1's repo — not needed. The coupling was already written down in one of the three always-loaded files.

Persistence

Claude Code that survives disconnection

Diagram: Claude Code that survives disconnection — Mac and Phone connect over Tailscale and key-only SSH into a VPS, where systemd keeps a tmux session alive hosting the Claude Code CLI (through symlinks and a local git clone) and the Vercel CLI, which sync to GitHub and Vercel respectively.

Memory

Context that survives the session

  • Userrole, expertise, how they like to work
  • Feedbackcorrections and confirmed approaches, with why
  • Projectwho's doing what, kept current, not permanent
  • Referencepointers to where things live, not the content itself
memory/feedback-example.md
---
name: feedback-example
description: pattern learned from a correction
metadata:
  type: feedback
---

Rule the correction implied, generalized beyond
the one instance.

Why: the reasoning given at the time, so future
edge cases get judged the same way, not re-litigated.

Guardrails

Nothing ships on trust

  • Lint, typecheck, and build — automatic, not on request
  • No console.log, no empty catch blocks
  • No secrets in code, ever
  • Every caught exception logged or re-thrown
  • All 5 UI states covered before a task is "done"

Changelog

A dated log, not a version number

project-1/CHANGELOG.md
## 2026-08-21
### Fixed
- Sensitive env var audit — corrected vars that
  should have been marked sensitive

## 2026-08-16
### Changed
- Renamed database to match the project name

Deploy loop

Stops on a failed check. Never ships around one.

deploy
$ git push origin main

▸ pull          read-only key, scoped to one repo
▸ build
▸ health check  poll each service's real route
▸ advance       marker moves forward, only on all-pass

3/3 passing → live

Before this existed

What the layering fixed

Machines drifted apart.one repo, symlinked to both.
A checkout can rot silently.push-triggered deploys catch it.
Cross-project questions meant opening another repo.one card to read instead.
Debugging narratives inflated the fast-lookup cards.split into a separate log.
Corrections didn't survive the session.memory carries it forward.

Commands

The ones I actually reach for

/code-review

Reviews the current diff or a PR, can apply the fixes it finds.

/commit

Stages, writes the message, commits — same discipline every time.

/loop

Runs a prompt on a recurring interval, self-paced, until told to stop.

/schedule

A cron-based agent run for work that doesn’t need a live session.

/review

Reviewer, QA, and security passes in parallel, synthesized into one report.

/security-review

A full security pass on pending changes before anything merges.

This is the same setup behind every system on this site.