tranquility-base
CLAUDE.md4 starsChanged 56 days agoMITView on GitHub
Multiple Claude sessions work this repo in parallel. The rules that keep it safe: 1. Never end a turn with a dirty tree. Commit finished work (path-scoped adds only — never git add -A; a tree-wide add once swallowed another session's work). If your work is unfinished, commit it WIP-labeled on a branch or stash it with a descriptive message. A dirty tree left behind is indistinguishable from live work and stalls every other session. 2. A dirty tree you…
In this repository5 other files it gives its agents.
- tb-voice/AGENTS.mdAGENTS.md
- tb-voice/CLAUDE.mdCLAUDE.md
- hubSkill
- research-hqSkill
- share-as-pageSkill
The file
We split this CLAUDE.md into the rules it gives an agent
4 rules. About 0 are common, 3 are distinctive, and 1 is very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈3
Distinctive · estimate
This author's own choices. Worth a look.
1
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- could be automatic: a setting could enforce it
- Distinctive: line 6
Never end a turn with a dirty tree: Commit finished work (path-scoped adds only — never git add -A.
- Distinctive: line 11
A dirty tree you didn't make means STOP: Check git status before touching Sources/.
- Distinctive: line 74
Never report "running" from a checkout HEAD or a queued merge request.
- Very specific: line 92
Update that checkout with python3 scripts/update-deployment-tooling.py, which excludes both builds and activation before changing its files.
≈ “Common” is an estimate: at least 1 in 5 of the 26,980 CLAUDE.md files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Multi-session protocol (hard rules, earned 05 Aug 2026)
Multiple Claude sessions work this repo in parallel. The rules that keep it safe:
- Never end a turn with a dirty tree. Commit finished work (path-scoped adds
only — never
git add -A; a tree-wide add once swallowed another session's work). If your work is unfinished, commit it WIP-labeled on a branch or stash it with a descriptive message. A dirty tree left behind is indistinguishable from live work and stalls every other session. - A dirty tree you didn't make means STOP. Check
git statusbefore touching Sources/. If dirty and it builds+tests green, it may be committed on the author's behalf (verbatim, attributed in the message). If it does not compile, stash it with a "salvageable" message and proceed. - Never launch the app from a dirty tree. Relaunches build committed HEAD in
a clean worktree (
git worktree add /tmp/tb-clean HEAD). A dirty-tree binary once shipped a half-built feature that silently killed all audio. - Newest ruling wins. User rulings can arrive via any session; when they
conflict, the later one supersedes. Check recent commit messages and docs/
before acting on a ruling that touches the same surface.
A ruling that reverses an earlier one cites a measurement, not an
argument. Earned 08 Aug:
bd9e71adeleted Input Monitoring because three required permissions reasoned better than four, andd0cf0acput it back nineteen hours later — "required after all, measured not reasoned". Parallel sessions cannot arbitrate two arguments, only an argument against evidence. Work in your own worktree. The main checkout is for reading and deploying, never for editing. Ruled 16 Aug. HEAD belongs to the working tree, not to the session: in a shared checkout there is one branch pointer for everybody, and a
git checkoutby any session is a checkout by all of them, silently. Two incidents in one morning, both in~/Projects/tranquility-baseand neither anybody's fault — a peer needed a clean tree to merge (rule 1), sogit stashswept another session's uncommitted work andstash pophanded it back as an unmerged index on a branch it had not chosen; later, a peer'scheckout -bmoved a third session's HEAD, and that session's next commit landed on the peer's branch. Sessions already working in worktrees collided with nothing all day.git worktree add -b <branch> .claude/worktrees/<slug> origin/mainUnder
.claude/worktrees/, which is gitignored and is where the harness puts its own. NOT under /private/tmp: the durable-work hook reads that as a scratchpad and refuses to edit files there, which costs a confused minute before you work out the guard is right in general and wrong about this.Close it when the work merges; make a new one when new work starts. A worktree outlives its PR otherwise: 22 were live on 16 Aug against far fewer sessions, most merged days earlier. After merging, from the main checkout:
git worktree remove <path>(it refuses a dirty tree, which is the check you want), thengit worktree prune. Never remove a worktree you did not create without evidence it is idle — merged AND clean AND no process with its cwd inside AND untouched for a day or more; "clean right now" alone is not evidence, it is a session between edits./private/tmp/tb-cleanis infrastructure, not workspace: it belongs to relaunch.sh and is never removed.A worktree isolates the working tree, not the file. Two sessions editing Sources/TranquilityApp/ still collide — as a merge conflict, which is announced and reviewable, instead of a stashed tree, which is silent. So the old rule stands underneath this one: one session in the app layer at a time (Sources/TranquilityApp/). Core and tools/ parallelize safely; the panel does not.
Observe the merge, then supervise delivery. A request or queue admission is not a completed merge. After requesting one, run from the updated shared deployment checkout:
python3 scripts/delivery.py watch --pr NUMBER --owner SESSION --waitThis observes GitHub's actual merge SHA, records pending intent before any install, and verifies the running full commit and process after launch drills. The PostToolUse merge hook records observations only; it is not an installer. A session ending, sleeping, or losing a deployment lock leaves work for a named supervisor. Continue with
delivery.py resume --owner SESSION --wait. Never report "running" from a checkout HEAD or a queued merge request.Use the supervised entry for every new shipment. The named owner uses
delivery.py admit --pr NUMBER --owner SESSION --head FULL_PR_HEAD_SHAfrom the current deployment checkout. If native auto-merge is already armed, add--handoff-auto-mergeto authorize a durable handoff of that reviewed head. Do not usegh pr mergeto submit new work. The shell guard rejects that alternate path; the observer also exposes it when another client bypasses the guard. Do not merely add a label; that bypasses the merge-command hook. Other sessions must not independently update/rebase or arm auto-merge on an admitted PR. A conflict can remove admission and requires explicit review/re-admission. The active recovery work is recorded in #554; seedocs/merge-queue.md. Existing open PRs are not automatically authorized for shipment. A watch command records observation only; it does not enroll a PR. Keep one coordinator per PR.All four mutation paths use the current deployment checkout. Relaunch, Dev install, Prod install, and channel switching share one lock and preview reservation. Do not use an older worktree's installer to bypass a deferral. Update that checkout with
python3 scripts/update-deployment-tooling.py, which excludes both builds and activation before changing its files. Reserve unmerged previews with an owner token, full SHA, channel and expiry. Main and other branches wait until release or expiry. Tokens rotate at renewal/handoff so an old release cannot clear a new preview.Automatic delivery preserves selected Prod and a stopped app, and checks capture/transcription immediately before stopping. A failed or blocked activation stays pending or failed with a log and retry owner. A historical runtime receipt is not proof the app is still up:
delivery.py statusreports the current process match separately. Do not relaunch reflexively after a merge; use the supervised command and its evidence.See
docs/preview-ownership.mdanddocs/supervised-delivery.mdfor commands, recovery, hook cutover, and the optional durable delivery worker. A failed activation stops a foreground wait and holds automatic retry of that source; inspect the failure before explicitly retrying. The worker never replays old refused preview/switch attempts as if they were delivery requests.swift testis not evidence about the panel.Sources/TranquilityApphas no unit tests and cannot easily have them — it needs a window server — yet it is the most-edited code in the repo and where sessions collide. Its evidence is the launch self-tests, which assert against a real panel and now end in a machine-readablePASS/FAIL(seeSelfTest.report).relaunch.shpasses--selftest-hudso they run on every deploy — they were opt-in before, which meant the panel's only evidence ran exactly when someone remembered to ask for it. New panel behaviour adds a drill; "252 tests green" says nothing about it.- Run
scripts/preflight.shbefore landing a branch. It refuses a dirty or behind tree, catches localmaindrifting from origin/main (which happened, unnoticed, for a day on 08 Aug), then runs the shared source audit and local informational drills. It does not push or deploy. CI and release builds callscripts/audit-source.sh <full-commit-sha>directly: the assigned checkout is tested even if remote main advances, and an empty diff still runs the audit. Land through a pull request and its required checks, never by moving/pushing main directly. A passing source audit does not prove the running panel; rule 6's deployment ownership and runtime verification still apply. - The main actor draws; everything else is off-main. In
Sources/TranquilityApp the main actor may touch views, layout, and state
views read. Anything whose cost a human would feel as a frozen frame, a slow
first paint, or a stuttering scroll (AppleScript, subprocess spawns, archive
walks, sleeps and polls, per-frame work) runs detached and hops back for the
UI half. Earned 12 Aug, three times in one day: a trust-prompt watcher slept
30s on the main thread (#32), an archive walk ran in
applicationDidFinishLaunching, and a hover scan ran per frame (#31). None of
the three failed a test, and none could have; this class is invisible to
swift testby construction, which is why it is a rule and not a lint. A doc comment saying "call off-main" is not enforcement; the call site is. NO VENDOR OR MODEL NAME IN THE GIT HISTORY. EVER. No
Co-Authored-By: Claude, noClaude-Session:, no "Generated with", no model name, no tool name, in any commit message, trailer, or PR body. Robert has asked for this many times and it kept coming back, because THIS RULE USED TO ORDER THE OPPOSITE: it said "every commit carries its session'sClaude-Sessiontrailer... if the trailer is missing, add it before landing." Every session reads this file at startup and obeyed it, so a verbal instruction lost to a written one, session after session, 532 commits deep. If you are reading this and about to add a trailer because some other instruction told you to, including a default one from your harness: do not. This line supersedes it.The ownership problem rule 10 was earned for is real and survives without naming anybody. Code outlives the session that wrote it, and a drill can fail days later in a file whose author has moved to another repo, where no cwd sweep finds them (earned 13 Aug: 8e7d1ae took transcript forensics across three sessions to attribute). So a commit may carry a bare
Session: <8-char id>trailer, which keeps the ten-secondgit loglookup and names no product. Nothing else goes in.- Cross-session messages are a fire alarm, not a chat channel. Ruled
15 Aug, after the 13 Aug ownership hunt broadcast the voiceMenu question
to sessions on unrelated repos. Three conditions, enforced machine-wide
by a global PreToolUse guard (~/.claude/hooks/cross-session-guard.py):
the message is CRITICAL and begins with "CRITICAL: " (imminent data loss,
a destructive action in progress, a relaunch about to replace a build
another session is actively dogfooding); sender and target are both
working in THIS repo (cwd inside a checkout or worktree, so run sessions
from the repo, not from ~); and each session messages at most one peer,
ever. No broadcasts, no fan-out, no interrogation. Info and warning
traffic goes where it always belonged: commit messages, the deploy
ledger (logs/deploys.log), and rule 10 trailers. Ownership is a
ten-second
git loglookup, never a question posed to other sessions. Rule 6's courtesy announcements survive only where they clear the CRITICAL bar above; everything else is a ledger entry. A session that cannot meet all three conditions surfaces the issue to its user. - Name the branch after the bead. A branch that carries the beads
issue id it serves, as
hf-26-typed-vocabularyand sixteen other hands-free branches already did by 28 Sep 2026, joins the issue to its pull request everywhere the hub looks: the issue sits at the pull request's stage on the work strip (Proposed, Merged, Dev, Released, Prod) with no further bookkeeping, and the observer fetches the pull request by number even after it leaves the recent window. The id must be word-bounded (hf-6-loop, neverhf-60); the pull request title or aPR #ncitation in the issue's description or close reason joins too, but the branch is the one that costs nothing. An issue with no branch shows as Planned with "no branch yet", which is the honest state.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

