A comprehensive tour of a professional solo-developer Claude Code setup spanning fifteen repositories and twelve worktrees. Covers workflow discipline, session persistence, automated quality gates, business operations, and EOS management.
Last updated: 2026-06-11
What this is: a tour of a working setup and the reasoning behind it — useful for borrowing patterns. What this is NOT: an install guide, a list of best practices, or a snapshot that stays accurate without updates. Plugin versions, pg_cron schedules, and file counts are point-in-time.
- Core Philosophy
- Directory Structure
- Session State Architecture
- Master Workflow
- Review Triage and Agents
- Workflow Profiles
- Rules System
- On-Demand Reference Docs
- Hooks System
- Model Strategy
- Skills Inventory
- Plugin Ecosystem
- Commands Inventory
- MCP Server Integration
- Repository Registry
- CompanyOS: Multi-Repo Architecture
- CEOS: EOS Framework
- Automated Jobs
- Multi-Instance Safety (Worktrees)
- Backup and Version Control
- Blog and Learning Capture
- Cursor Integration
- Git Workflow Rules
- Coding Standards
- Pre-commit Pipeline
- Quality Automation
- Database Migration Discipline
- Secrets Management
- Testing Patterns
- Critical Gotchas
- Quick Start for New Setup
- Key Insights
Global-first configuration. All agents, commands, rules, and skills live in ~/.claude/ (see Directory Structure for the 2026-04-15 migration that consolidated this). Project-level .claude/ dirs are deprecated — only ephemeral workflow state (.claude-session/, gitignored audit logs) lives there.
Key principles:
- Never create project-level
.claude/settings.json— it breaks permission inheritance from global settings - No quick-fix mode — every ticket gets the full workflow (
/start→ implement →/commit) - Session state files survive context compaction — workflow continuity across long sessions
- Evidence before assertions — never claim something about code without reading it first
- Protected workflows — certain operations (
/commit,/staging,/start) must never be done manually - Fix or ticket — no middle ground — the default is FIX. A review finding only gets a Linear ticket if it matches one of two documented exceptions: (1) a decision the user owns (product/UX/business — not technical/architectural), or (2) the code can't be modified cleanly (upstream/vendored, frozen branch, no write access). Tightened from five exceptions to two on 2026-05-10 — "complicated," "risky," "pre-existing," "scope explosion," and "needs an architectural decision" are all explicitly rejected as exceptions (architectural calls are pro/con analysis you do yourself)
- Duplication is a signal — before applying the same non-trivial edit to 2+ locations, stop and extract the abstraction first
- Plan task atomicity — never split plan tasks across test-file boundaries. A package's test suite is the atomicity unit
- Never fabricate evidence — if a hook blocks because evidence is missing, run the actual process or use
--no-verifywith stated justification - Machine-gated human pauses (2026-06) — both Workflow Profile gates were retired as manual stops:
user_testing(2026-06-03) is verification-gated (Playwright smoke for UI, test suites for source, actionlint for workflow YAML), andplan_approval(2026-06-04) is validation-gated (HIGH-risk plans run an automated Plan-Validation Battery instead of waiting for a human). Each retirement RAISED the machine bar that replaced the pause; a runtime PreToolUse guard (block-live-mutations.sh) blocks execution-time live external mutations as the backstop - Approved-work auto-cycle (2026-06-03) — once a design is approved, build → verify → review → fix → commit → push runs as ONE continuous cycle with no re-asking between stages; pause only on design-inverting findings, failed gates, or genuinely user-owned decisions
~/.claude/ # Global configuration (git repo → bradfeld/claude-config)
├── settings.json # Permissions, hooks, plugins, env, attribution
├── .claude.json # MCP server configuration
├── rules/ # 64 always-loaded rules
├── docs/ # 22 on-demand reference docs
├── skills/ # ~72 skill dirs (18 domain + 33 co-* + 21 ceos-*)
├── commands/ # 73 commands
├── hooks/ # 34 hook scripts
├── agents/ # 12 review agents
├── blog/notes/ # Daily learning capture
├── flywheel/ # Automation-flywheel log (log.jsonl)
├── comms/drafts/ # Email draft archive
├── voice/ # Writing style profiles (brad + phin-argofy)
├── plans/ # Implementation plans
├── projects/*/memory/ # Per-project auto-memory (shared natively since CC v2.1.63)
├── ccnotify/ # macOS notification system
├── iterm/ # iTerm color/typing monitor integration
├── mcp-servers/ # Custom MCP server implementations
└── plugins/ # Marketplace plugins
~/Code/companyos-intensitymagic/ # CompanyOS config repo
~/Code/companyos-config-foundry/ # Foundry-specific config
~/Code/ceos/ # CEOS repo (EOS skills)
Note: ~/.claude-personal is a symlink to ~/.claude — a naming artifact. They resolve to the same directory.
All review agents, skills, commands, and rules were moved to ~/.claude/ on 2026-04-15. Previously, each worktree had its own .claude/{agents,commands,rules}/ symlinked back to magic0 via sync-claude-config.sh. That architecture caused recurring incidents:
git checkoutwould delete config files (PLA-609, PLA-762)- APFS hardlink destruction when
rm -rfran on directory hardlinks (PLA-448) - Worktree symlink ELOOPs
- Project-level
settings.jsonbreaking permission inheritance
The current model: one source of truth in ~/.claude/, backed up daily to GitHub (bradfeld/claude-config), with per-repo behavior driven by Workflow Profiles in each CLAUDE.md instead of per-repo config files. sync-claude-config.sh was deleted. Project-level .claude/ dirs now only hold ephemeral workflow state.
Session files stored in project/.claude-session/ persist workflow state:
- Current step and status (
implementing,awaiting_user_test,committing) - Blocked actions to prevent accidental commits before testing
- Implementation plans that survive context compaction
- Progress tracking across worktrees
Circuit breaker: Commits are blocked when session status shows awaiting_user_test. The /commit command checks this state before proceeding. Since 2026-06-03, awaiting_user_test is the fall-back, not the default — green class-appropriate verification (Playwright smoke for UI, suites for source, actionlint for workflow YAML) auto-proceeds to /commit; the pause fires only when a gate fails or can't run.
PreCompact hook (preserve-session-state.sh) saves state before context compaction, so long implementation sessions don't lose workflow position.
All tickets follow an identical loop:
/start TICKET-XXX— Fetch ticket from Linear, revalidate its load-bearing premises against live state (Step 4.7 — tickets routinely describe a system that no longer exists by pickup time), classifyrisk_tier, create branch, write plan. HIGH-risk plans run an automated Plan-Validation Battery (Sonnet convergence loop + codex cross-model pass) instead of pausing for manual approval (PLA-1850, 2026-06-04)- Implement locally — completion is verification-gated, not manually tested (PLA-1840, 2026-06-03): Playwright smoke for UI, test suites for source, actionlint for workflow YAML; the old "wait for the user to test" pause survives only as the fall-back when a gate fails
/commit— Quality gates →/simplify(Step 3.5) → Playwright behavioral smoke test (Step 3.7, Magic Platform user-facing changes; PLA-1765) → auto-triage review → run agents → post-fix re-review of content reviewers for protected-config paths (Step 4b.5, INT-590) → push → update Linear/staging(magic-platform) — Batch merge to preview, deploy, reset worktrees/production(magic-platform) — Health audit, merge to main, verify. Runs autonomously since 2026-06-09 (routine confirmation gates removed)
For direct-to-main repositories (CEOS, WordPress, awsaudit), /commit IS the deployment.
/start auto-detects the target repository from the ticket's Linear team prefix — the same command works across all fifteen repositories. Chain mode: /start TICKET-1 TICKET-2 or /start epic EPIC-ID.
Unified /commit (2026-04-12): single canonical command replacing the old /spcommit//oldcommit split. Defaults to --full (convergence review + code-reviewer + specialized agents). --quick skips review. The /oldstart//oldcommit reference files have since been deleted.
| Level | When | What Runs |
|---|---|---|
| NONE | Only non-source changes (docs, tests, config, styling) | No review agents |
| LIGHT | Any source code change (.ts/.tsx) that doesn't trigger FULL |
code-reviewer + selective agents in parallel |
| FULL | 10+ files, shared packages, or sensitive paths | Full parallel multi-agent review battery |
Key rule: NONE never applies to source code changes. Even a 1-file .tsx change gets at least LIGHT review.
Evaluated in priority order: path-based overrides first, content-type exemption second, file-count baseline third.
Path overrides (force FULL): middleware.ts, auth.ts, /auth/, supabase/migrations/, packages/*, payment, billing, webhook
Content-type exemption (downgrade to NONE): Only when ALL changed files are non-source (docs, tests, config, styling, lockfile without package.json). Important non-exemptions:
package.json→ at least LIGHT (dependency changes = supply chain risk).claude/commands/*.md,.claude/rules/*.md,.claude/agents/*.md→ at least LIGHT withprompt-reviewer(no compiler for prompts)- Infrastructure config (
vercel.json,next.config.ts,turbo.json,.github/workflows/*.yml) → at least LIGHT
All 12 agents live in ~/.claude/agents/ and dispatch on Sonnet in parallel.
| Agent | Triggers On | Purpose |
|---|---|---|
code-reviewer |
All source changes (local mirror of the superpowers requesting-code-review template; superpowers 5.1.0 removed the named plugin agent) |
TypeScript strict, security basics, API patterns, logging |
performance-reviewer |
.tsx, page.tsx, layout.tsx, server actions |
Sequential awaits, client boundaries, Suspense, serialization |
silent-failure-hunter |
API routes, services, actions, hooks | Swallowed errors, unhandled promises, missing cleanup |
security-auditor |
Auth flows, middleware, migrations, webhooks | RLS policies, secrets, SQL/auth injection |
migration-reviewer |
supabase/migrations/*.sql |
Timeout safety, idempotency, RLS completeness, TO clause, auth.uid() wrapper |
ui-consistency-reviewer |
.tsx files |
shadcn/ui patterns, semantic tokens, accessibility |
test-quality-reviewer |
Test files alongside source | Assertion quality, edge cases, mocks, flaky patterns |
spec-reviewer |
FULL triage on epic children | Plan compliance vs Linear ticket |
cross-app-consistency-auditor |
packages/*, multi-app changes, @platform/* siblings |
Pattern drift across apps |
prompt-reviewer |
.claude/commands/*.md, .claude/rules/*.md, .claude/agents/*.md |
Dead references, contradictions, stale docs |
ai-usage-reviewer |
Files importing @platform/infra/ai |
Cost controls, prompt injection, error handling, temperature, model tier |
environment-health-auditor |
Manual only | Periodic infrastructure health monitoring |
Cross-model review: codex-reviewer (GPT-5.5 via MCP stdio) dispatches on all source changes at LIGHT and FULL. It's not a .claude/agents/ file — it's an MCP server tool. Catches race conditions and logical errors that a single model family might miss.
Post-fix re-review (Step 4b.5, INT-590): when a protected-config path (commands, rules, hooks, agents, skills, settings.json) gets a fix during review, the content reviewers (prompt-reviewer/code-reviewer) re-run on the post-fix diff — the convergence loop re-runs impl-review only, so without this step the post-fix bytes would go unreviewed by the reviewers that gate config files. Companion rule: review-covers-bytes-it-read.md ("a review covers the bytes it read, when it read them").
CompanyOS delegation: /commit detects CompanyOS repos (mirroring enforce-co-commit.sh's detection exactly) and delegates to /co-commit rather than running its own pipeline.
Full decision algorithm and dispatch examples are in on-demand doc review-triage-reference.md.
Each repository declares its workflow in CLAUDE.md as YAML:
workflow:
base_branch: preview # or main
direct_to_main: false # true for CEOS, WP, awsaudit
plan_approval: auto_if_validated # LOW announces + proceeds; HIGH runs the Plan-Validation Battery
user_testing: auto_if_verified # class-appropriate verification replaces the manual test pause
quality_gates:
- pnpm run type-check
- pnpm run lint
review:
max_level: FULL # NONE, LIGHT, or FULL
ship:
method: pr # pr or direct_push
linear_status: "In Progress"
deploy_hint: "/staging"This declarative approach lets /start and /commit work identically across fifteen repositories without hardcoded logic. The unified /commit reads the profile and adapts its behavior. This is the right place to change per-repo behavior — not the command source.
The two human gates are now machine-gated (rule: risk-tiered-gates.md). risk_tier reuses the review-triage FULL signals (migrations, auth/middleware, packages/*, payment paths, multi-app, 10+ files) — no parallel classifier:
plan_approval: auto_if_validated(PLA-1850, 2026-06-04) — LOW-tier plans announce and execute; HIGH-tier plans run the Plan-Validation Battery (Sonnet convergence with Read/Grep tools, two consecutive clean rounds, plus a codex/GPT-5.5 cross-model pass) and proceed on PASS. The pause survives only on battery FAIL or a surviving user-owned decision.user_testing: auto_if_verified(PLA-1840, 2026-06-03) — auto-commit when every change class in the diff has its verification green: Playwright smoke for UI (real auth-flow smoke for auth diffs), test suites for non-UI source, actionlint for workflow YAML,bash -n+ shellcheck for scripts, nothing for docs-only. Failed or unrunnable gate → fall back to the pause. HIGH tier gets strengthened verification, not a pause.- Runtime backstop:
block-live-mutations.sh(PreToolUse) hard-stops execution-time live external mutations (infra apply, prod API writes, external sends) at the moment of irreversibility — chosen over plan-time classification, which is self-reported and chain-bypassed. - Safety envelope unchanged: unattended work still hard-stops at
/commit(full review battery) and never auto-deploys;/stagingand/productionremain user-triggered. Legacyrequiredscalars keep uniform pauses; unrecognized values fail safe.
64 always-loaded rules in ~/.claude/rules/ establish cross-project standards. The count nearly tripled (23 → 56 → 64) between 2026-04-29 and 2026-06-11 as codified learnings graduated from daily notes via /flywheel (which absorbed the old /learn review path on 2026-05-29). The largest cluster is verification discipline (anchor: evidence-first.md).
| Rule | Purpose |
|---|---|
api-before-ui.md |
Before manual UI work for a third-party service, check GCP SM for an admin token / probe the API (PLA-1450) |
architectural-decision-resolved-premises.md |
Most "needs a decision" deferrals are already answered by a rule, memory, code, or tooling — audit before deferring |
audit-before-greenfield.md |
Before building a "framework/registry," audit what the codebase already provides — it's often 80% built |
auto-execute-recommendations.md |
After a clear recommendation, EXECUTE — never end with "which approach?"; decide technical, ask only product/UX |
automated-remediation.md |
Detection must produce action (fix now, else one consolidated ticket) — not a passive warning |
banned-words.md |
Vocabulary bans ("honest" + inflections, AI-slop tells like "delve"/"tapestry", "to be straight") with two-layer enforcement: pre-send self-scan + Stop hook |
bulk-sweep-treats-distinct-sites-uniformly.md |
Before a replace_all/sed/codemod across N sites, verify all N are actually the same — one is often intentionally different |
cause-and-detector-ship-together.md |
When retiring a silent-failure mode, ship the detector that catches its return in the same commit |
checkpoint-restored-summary.md |
First response after /clear with a restored checkpoint must lead with a compact summary block |
co-commit-enforcement.md |
CompanyOS repos block raw git commit (PreToolUse hook) — commits go through /co-commit |
code-quality.md |
TypeScript strict mode, error handling (toError), security, type duplication |
command-skill-arg-substitution.md |
Claude Code substitutes $<digit> in command/skill bodies at invocation (0-indexed, inside code fences) — escape literals as \$N, use $ARGUMENTS[N] for positionals |
commit-recipe.md |
Universal commit structure, git add -A, --no-verify policy, worktree staging |
convergence-review.md |
Trigger + mode detection for the convergence-review loop (renamed from tricycle.md 2026-05-15) |
cross-cutting-belongs-one-layer-up.md |
Cross-cutting concerns (logging, auth, flush) belong at the wrapper/factory, not N leaf call sites |
debugging-priority.md |
Root-cause checklist — common causes (deploy drift, missing column) before speculative hypotheses |
dotfiles-symlinks.md |
~/.claude ↔ ~/.claude-personal are the same directory via symlink — mv/rm once, not twice |
duplication-as-signal.md |
Before applying the same non-trivial edit to 2+ locations, extract the abstraction first |
evidence-first.md |
Tools first, conclusions second — never assert about code without reading/verifying; external inputs are hypotheses |
evidence-integrity.md |
Never fabricate audit-log entries to pass hooks |
expand-contract-schema-changes.md |
Schema↔code coupled changes ship in two passes (add new → migrate → remove old) to avoid deploy race windows |
fix-dont-defer.md |
Two exhaustive exceptions for ticketing (decision the user owns; can't modify cleanly); default is fix |
fresheyes-review.md |
Adversarial decision review (opposed-mandate refuters, premise fact-check, cross-model frame-break) — auto-fires on load-bearing forks and HIGH-risk decisions, not just on request |
git-state-lies.md |
Fetch-ref staleness, squash-merge ancestry lies, and the -b/-B origin/BASE upstream-tracking trap |
grep-before-estimating-scope.md |
Grep for consumers before estimating scope — container count is decoration, consumer count is load-bearing |
learning-capture.md |
Batch-at-pause-points capture model (writes to daily notes) |
library-extension-point-first.md |
Find the library's first-class extension point before writing a custom override of adjacent UI |
mcp-arg-no-substitution.md |
MCP/Task tool args don't evaluate $(...)/backticks — resolve substitutions yourself before dispatching |
mcp-gateway-routing.md |
Gateway-brokered MCP servers rename tools (mcp__linear__X → mcp__jumpcloud__Linear_X) — tool identity is service + suffix; mechanical matchers must suffix-match |
mcp-secrets.md |
Wire new MCP secrets via the canonical sync script, not .mcp.json ${VAR} interpolation |
monitor-for-streams-not-completions.md |
Use Bash run_in_background (one completion signal) for one-shot waits; Monitor is for streams |
mutation-test-new-tests.md |
When adding a test for existing code, briefly mutate production to confirm the test catches regression |
no-schedule-offers.md |
NEVER end a reply offering to /schedule; ScheduleWakeup is for /loop only (overrides session-prompt default) |
on-demand-references.md |
Index of detailed reference docs |
output-formatting.md |
Structured-output completeness on first attempt; full URLs and absolute paths always |
package-cycles-premature-extraction.md |
A package cycle after extraction is a premature-extraction signal — investigate before routing around it |
phin-argofy-identity.md |
Claude's authorial identity (Phin Argofy; it/its) — voice/personality conventions |
plan-task-atomicity.md |
Never split plan tasks across test-file boundaries — the package's test suite is the atomicity unit |
protected-workflows.md |
Workflows that must use their dedicated commands (/commit, /start, /staging); execute slash commands immediately |
read-before-parallelizing.md |
Read the second await before converting to Promise.allSettled — it may re-fetch what the first already did |
recovery-inventory-comparison.md |
After any recovery, diff the recovered state against all backup sources before declaring done |
report-after-action.md |
Never batch a report/assertion (Linear comment with a SHA, status update) in the same message as the action it reports on — the report gets composed before the result exists |
reread-after-fs-modifying-tools.md |
Re-read files after git checkout/pnpm install/codemods/parallel subagents before the next Edit |
retroactive-enforcement.md |
When codifying a new pattern rule, file a sweep ticket for existing violations in the same PR (PLA-1391) |
review-covers-bytes-it-read.md |
A review covers only the bytes it actually read — review real files (not pastes), and re-review the delta after fixing findings |
review-triage.md |
NONE/LIGHT/FULL framework with agent selection |
risk-tiered-gates.md |
plan_approval/user_testing machine gating by risk_tier (reuses review-triage FULL signals); pauses survive only as fall-backs |
scope-intent.md |
Match response scope to what was requested (review ≠ fix; design ≠ build; match ceremony to complexity) |
shared-config-symlinks.md |
Symlinks into shared config repos (co-*, ceos-*) aren't yours to retire — check before "dormant" cleanup |
skip-conditions-evaluate-intent.md |
A workflow skip clause's stated reason IS the condition — if the literal trigger fires but the reason doesn't apply, run the step |
slash-command-help.md |
Every slash command responds to ? or --help with a help block |
smoke-test-before-completion.md |
Magic Platform user-facing changes get a Playwright behavioral smoke test before /commit (PLA-1765) |
subagent-stalls.md |
Never recommend Escape during parallel agents; HARD CONSTRAINTS block + verify-after-completion for dispatches |
suppression-token-specificity.md |
A suppression marker must name the single check it suppresses — never the bare/overbroad form |
system-reminders-not-turn-boundaries.md |
System-reminders attached to a tool result are metadata, not stop signals — continue the announced workflow |
test-over-arguing.md |
When debugging a behavioral hypothesis, write a 60-second test instead of reasoning from docs |
test-the-compositions-not-just-the-api.md |
Test the compositions a helper promises, not just its API surface in isolation |
tests-as-disambiguator.md |
Write the failing test before treating a severity claim as fact — severity-in-prose ≠ severity-in-test |
tests-encode-intent.md |
For "wrong shape" fixes, add a shape test that asserts the call signature, not just the output |
verify-background-bash-output.md |
A run_in_background Bash completion summary's exit code can lie — tail the output and grep for failures |
verify-until-stable.md |
One round of premise verification is rarely enough — stop when two consecutive rounds produce no new inversions |
workflow-tool-usage.md |
Workflow tool vs Task-dispatch discipline — Workflow only for large resumable fan-outs; workflow agents never commit (stage-and-report) |
zod-turbopack-hoisting.md |
pnpm needs public-hoist-pattern[]=zod for sub-entrypoint peers (@hookform/resolvers/zod) |
zsh-compat-traps.md |
Shell snippets run under zsh — avoid path var shadowing, no word-splitting, realpath over [ -L ] |
Rules promoted to on-demand skills: mcp-linear, mcp-supabase, database-migrations, auth-admin-reads, vercel-env-api — narrow-use guidance that doesn't need to be loaded in every session.
Architectural principle (PLA-688, continued through 2026-04): Always-loaded rules contain decision logic; reference tables and tool-specific gotchas live in docs/skills loaded only when needed.
Same principle applied to project AGENTS.md (2026-04-29): Magic Platform's AGENTS.md was trimmed from 43k → 22k chars (731 → 340 lines) by extracting embedded code examples to docs/standards/*.md files referenced by plain prose pointers (not @import, which loads regardless of relevance). Followed Anthropic's "would removing this cause Claude to make mistakes?" test from the official Claude Code best-practices guide. Also brought the file back under Claude Code's 40k char soft-warning threshold and closer to Anthropic's recommended <300 line target for always-loaded files.
Pre-commit enforcement:
rules-size-cap.sh— caps each rule file at ~200 lines (staged files only)verify-review-agents.sh— every agent referenced in triage rules must have a definition
22 docs in ~/.claude/docs/ plus project-level docs, loaded only when a task matches. The on-demand-references.md rule serves as the index (and rules-index.md maps "I'm about to do X" → which always-loaded rule applies):
| Task | Reference Doc |
|---|---|
| Writing Vitest tests | testing-vitest.md |
| Configuring MCP servers | mcp-server-config.md |
| Creating skills or commands | skill-authoring.md |
| Discourse community admin | discourse-community.md |
| Committing changes | commit-reference.md |
| Review triage dispatch | review-triage-reference.md |
| Multi-chain epic planning | multi-chain-epics.md |
| Parallel subagent dispatch | parallel-patterns.md |
| Shell scripting | bash-patterns.md |
| Batch learning capture | learning-capture-procedure.md |
| Running convergence-review | convergence-review.md / review-prompts.md |
| Running an adversarial decision review (fresheyes) | fresheyes-review.md |
/research command design spec |
research-command-design.md |
| Magic Platform convergence pre-commit hook (evidence-file requirements) | magic-platform-convergence-hook.md |
| "About to do X" → which rule applies | rules-index.md |
| Platform app templates | platform-app-templates.md |
| Thinking modes reference | CLAUDE_CODE_THINKING_MODES.md |
| Self-describing data patterns | self-describing-data.md |
| TypeScript / pnpm / Tailwind / ESLint gotchas | typescript-gotchas.md |
Module resolution errors (ERR_REQUIRE_ESM, missing subpath exports) |
module-resolution-debugging.md |
| TDD patterns and execution recipes | tdd-patterns.md |
Magic Platform docs (canonical locations in the repo — an earlier .claude/docs/ layer was deleted 2026-03-22 in favor of docs/standards/ and docs/ops/):
docs/standards/UI_CONSISTENCY_STANDARDS.md,DATABASE_PATTERNS.md,LOGGING_GUIDE.md,TESTING_STRATEGY.md,TYPESCRIPT_STRICT_MODE.md,ERROR_HANDLING.md(toError, Promise.allSettled + helpers, service null-vs-throw, logSupabaseError)docs/ops/GITHUB_WORKFLOWS.md,cursorcommit.md,DATABASE_MIGRATION_RECOVERY.md,DEPLOYMENT_SELF_HEALING.md,INCIDENT_RESPONSE.md
Why: A 200-line reference table for commit workflows wastes tokens when you're doing codebase exploration. On-demand docs are loaded only when Claude encounters the matching task — zero cost otherwise.
34 hook scripts in ~/.claude/hooks/ plus external integrations (ccnotify, iTerm), responding to 11 lifecycle events. The 6 added since 2026-05-28 split between PreToolUse guards (live-mutation gate, SHA-fabrication gate) and output enforcement (banned-words Stop hook + redact display mask) — each encodes an always-loaded rule as a mechanical block, cheaper than a rule that taxes every session.
| Script | Purpose |
|---|---|
block-supabase-mcp-migrations.sh |
Prevent mcp__supabase__apply_migration from targeting prod/preview (renamed from block-production-apply-migration.sh) |
block-banned-words.sh |
Stop hook — scans the final assistant message for banned words/phrases, forces a corrected re-emit on a hit (banned-words.md) |
block-decision-offload.sh |
Stop hook — nudges replies that end by handing the user a decidable fork back into the decide-it-yourself tree (auto-execute-recommendations.md) |
block-live-mutations.sh |
Block execution-time live external mutations (infra apply, prod API writes, external sends) — the runtime backstop for the retired plan-approval pause; scoped allow valve at ~/.claude/.live-mutation-allow |
block-git-checkout-sha.sh |
Block git checkout <SHA> (use git show/git log instead) |
block-mcp-shell-substitution.sh |
Block $(...)/backticks in MCP/Task args unless sentinel present (mcp-arg-no-substitution.md) |
block-schedule-wakeup-outside-loop.sh |
Block ScheduleWakeup outside a /loop (no-schedule-offers.md) |
block-task-background.sh |
Block run_in_background: true on Task/Agent dispatches (stall trigger) |
changelog-tracker.sh |
Track file changes per Edit/Write |
co-skill-track.sh |
Log skill invocations to Supabase |
command-tracker.sh |
Track slash command success streaks |
enforce-claude-config-review.sh |
Block raw git commit in ~/.claude/ touching high-risk paths without fresh review evidence |
enforce-co-commit.sh |
Block raw git commit in CompanyOS repos — must use /co-commit |
file-protection.sh |
Prevent edits to protected files |
fix-dont-defer-scanner.sh |
Catch "I'll note this for later" anti-patterns in output |
google-workspace-retry.sh |
Detect OAuth port conflicts, instruct retry |
inject-checkpoint.sh |
Inject restored-checkpoint context into the first SessionStart turn after /clear |
inject-context-pct.sh |
Inject context-window usage % into the prompt |
instruction-load-logger.sh |
Log instruction loads for analysis |
no-speculate.sh |
Catch speculative assertions in output (evidence-first.md) |
permission-auto-approve.sh |
Auto-approve known-safe operations |
preserve-session-state.sh |
Save state before context compaction |
redact-banned-words-display.sh |
Redact-mode display mask for banned words (inline ⟦slop⟧); mode toggled instantly via one-line ~/.claude/.banned-words-mode (block vs redact) |
review-enforcement.sh |
Enforce review on git commit via Bash |
rules-size-cap.sh |
Cap staged rule files at ~200 lines |
session-title.sh |
Set terminal/session title from context |
startup-summary.sh |
Show worktree/branch/config health banner at SessionStart |
system-health-check.sh |
Verify system state on startup |
verify-cited-sha.sh |
Block Linear writes citing a git SHA that doesn't resolve to a real commit — catches reports composed before the action ran (report-after-action.md); suffix-matched so gateway tool renames stay covered |
verify-dollar-digit-escape.sh |
Pre-commit: block unescaped $<digit> in staged command/skill bodies (silent arg-substitution corruption; command-skill-arg-substitution.md) |
verify-review-agents.sh |
Validate every agent referenced in triage rules has a definition |
verify-rule-doc-paths.sh |
Verify every ~/.claude/docs/*.md path cited in a rule file actually resolves (PLA-1285 drift prevention) |
whats-new-check.sh |
Check for Claude Code feature updates |
worktree-sync-check.sh |
Verify worktree is not stale vs remote |
| Event | Purpose |
|---|---|
| InstructionsLoaded | Log what rules/docs loaded |
| SessionStart | Config health check, CompanyOS session-sync, startup banner, system health |
| PreToolUse (Edit|Write) | Block edits to protected paths |
| PreToolUse (Bash) | Block raw git commit (must use /commit / /co-commit); block git checkout <SHA>; block live external mutations during execution |
| PreToolUse (MCP) | Block apply_migration targeting prod/preview; block $(...) substitution in MCP/Task args; block fabricated git SHAs in Linear writes |
| PreToolUse (Task) | Block run_in_background: true dispatches |
| PreToolUse (ScheduleWakeup) | Block outside a /loop |
| UserPromptSubmit | ccnotify, typing monitor, iterm color, skill track, command track, session title |
| PostToolUse (ExitPlanMode) | macOS "Plan Ready" notification |
| PostToolUse (Skill) | Skill telemetry |
| PostToolUse (Edit|Write) | Track file changes |
| PostToolUse (Google Workspace) | OAuth conflict detection |
| PreCompact | Save state before compaction |
| Stop / StopFailure | ccnotify, iterm color, typing monitor, command tracker, banned-words scan, decision-offload backstop |
| SessionEnd | iterm color, typing monitor stop |
| PermissionRequest | Auto-approve known patterns |
| Notification | ccnotify macOS forwarding |
Key architectural pattern: Hooks replaced several always-loaded rules. A rule that says "if Google Workspace fails with port 8766, retry" wastes tokens in every session. A PostToolUse hook fires only when the specific tool runs AND only outputs text when the error matches — zero token cost in the common case.
The primary session model is Fable 5 (model: fable in settings.json, adopted at its 2026-06-09 launch; Opus 4.8 was primary from ~2026-05, 4.7 from 2026-04-16). Fable 5 is Anthropic's Mythos-class tier above Opus — free on the Max plan through June 22, usage credits afterward, ~2.6× effective Opus cost via API. The @platform/infra/ai premium tier is a separate setting — verified 2026-06-11: no ANTHROPIC_MODEL_* env pins anywhere; resolution is user pref → env → DB (shared.platform_settings) → code default claude-opus-4-8-latest.
| Role | Model | Why |
|---|---|---|
| Primary agent (user sessions) | Fable 5 | Mythos-class tier above Opus; most capable available model |
Plan subagent (/start) |
Sonnet 4.6 | Dispatch via model: "sonnet" (version-agnostic) |
Review agents (/commit) |
Sonnet 4.6 | All review dispatch via model: "sonnet" |
| Explore agents | Haiku 4.5 | Quick codebase lookups |
Platform AI (@platform/infra/ai) |
Tiered | fast=Haiku 4.5, standard=Sonnet 4.6, premium=Opus 4.8 |
Effort level: Pinned via env.CLAUDE_CODE_EFFORT_LEVEL=xhigh in settings.json — the env var is the only method that beats the model-default-on-startup override (Opus 4.8's built-in default is high, not xhigh; the plain effortLevel key loses to it). A consequence: per-skill effort: frontmatter is inert (2026-05-30) — everything runs xhigh by deliberate choice.
Convergence review (formerly "tricycle," renamed 2026-05-15): Simplified to Sonnet-only (2026-04-05) after data showed 31% actionable rate, 47% zero-finding runs, and heavy model overlap.
The 4.6 → 4.7 transition changed behavior in ways that break prompts tuned for 4.6; these carry forward to 4.8:
- More literal — drop scaffolding like "double-check X" or "add interim status messages"; 4.7 won't silently generalize
- Fewer tool calls / fewer subagents by default — prompt explicitly for parallel work; raise effort to increase tool usage
- New tokenizer ~1–1.35× heavier — bump
max_tokensand compaction triggers - Sampling params removed —
temperature,top_p,top_k400-error on 4.7 (platform AI client auto-strips) - Fixed thinking budgets removed — use
thinking: {type: "adaptive"}(off by default on 4.7) - Thinking content omitted by default — set
thinking.display: "summarized"to restore visible progress
~88 skills total from three sources. Single table by category:
| Count | Category | Source | Summary |
|---|---|---|---|
| 18 | Domain | ~/.claude/skills/ (self-authored) |
Platform-independent engineering tools |
| 33 | CompanyOS (co-*) |
Symlinked from ~/Code/companyos-intensitymagic/skills/ |
Business operations: comms, content, ops, support, launch |
| 21 | CEOS (ceos-*) |
Symlinked from ~/Code/ceos/skills/ |
EOS framework: VTO, Rocks, L10, scorecard, people, process |
| 14 | Superpowers | Plugin: superpowers@superpowers-marketplace |
Core dev methodology (TDD, debugging, plans, reviews) |
| 2 | Marketplace | Plugin: simmer, documentation-audit |
Artifact refinement, docs verification |
| Skill | Purpose |
|---|---|
testing |
Test writing, debugging failures, choosing approaches |
supabase |
Database queries, migrations, RLS debugging |
database-migrations |
SQL migration patterns (idempotency, RLS, TO clause, timeout safety) |
vercel |
Deploy, build failures, environment management |
vercel-env-api |
Managing Vercel env vars via REST API (works around CLI bug) |
linear |
Ticket management, issue creation, work tracking |
mcp-linear |
Linear MCP tool gotchas (silent failures, unified tools, project IDs) |
mcp-supabase |
Supabase MCP rules (discover projects first, schema-qualify tables) |
auth-admin-reads |
Never use auth.admin for user reads — use getUserIdentity() |
context7 |
Library docs, API research, developer tools |
notion |
Notion pages, databases, documentation |
sentry |
Error investigation, issue viewing, trends |
oauth |
Social provider OAuth setup |
performance |
Core Web Vitals, bundle size, render optimization |
mobile |
Mobile-responsive UI, layout fixes |
form-patterns |
Form dirty state, "unsaved changes" bugs |
rewriter |
Content rewriting with optional voice matching |
ui-iterate |
Iterate on UI against a localhost/preview URL via Playwright MCP |
Five of these (mcp-linear, mcp-supabase, database-migrations, auth-admin-reads, vercel-env-api) were promoted from always-loaded rules during PLA-1285 (2026-04). They activate on-demand based on tool usage or file paths, eliminating their always-loaded token cost.
systematic-debugging, verification-before-completion, writing-plans, executing-plans, test-driven-development, subagent-driven-development, dispatching-parallel-agents, using-git-worktrees, finishing-a-development-branch, brainstorming, requesting-code-review, receiving-code-review, writing-skills, using-superpowers.
Auto-updates ensure all sessions inherit new patterns without manual commits.
See CompanyOS and CEOS sections.
9 active plugins across 6 marketplaces.
Snapshot as of 2026-06-11 — plugins auto-update from their marketplaces; versions will drift.
| Plugin | Marketplace | Purpose |
|---|---|---|
| vtsls | claude-code-lsps | TypeScript/JavaScript LSP |
| yaml-language-server | claude-code-lsps | YAML LSP |
| pyright | claude-code-lsps | Python LSP |
| superpowers | superpowers-marketplace | Core development methodology (14 skills) |
| episodic-memory | superpowers-marketplace | Cross-session conversation recall |
| simmer | 2389-research-marketplace | Iterative artifact refinement |
| documentation-audit | 2389-research-marketplace | Docs-vs-code verification |
| release-radar | whats-new-marketplace | Cross-reference CC release notes against config |
| vercel-plugin | vercel | Vercel deployment, performance, AI SDK guidance |
| Marketplace | Source |
|---|---|
claude-code-lsps |
Built-in |
superpowers-marketplace |
GitHub: superpowers-marketplace |
2389-research-marketplace |
GitHub: 2389-research/claude-plugins |
whats-new-marketplace |
GitHub: bradfeld/whats-new-plugin.git |
vercel |
Local directory cache |
claude-plugins-official |
Registered, no installs yet |
knowledge-work-plugins |
Registered (18 categories) — no installs yet |
Plugin architecture: The enabledPlugins key in settings.json maps plugin names to their marketplace origin. Plugins can provide skills, agents, rules, and MCP configurations. Episodic memory is notable — it provides semantic search across prior conversations, enabling Claude to recover decisions and solutions without manual memory management.
73 user-level commands in ~/.claude/commands/. Organized by tier. (Counts drift as commands are consolidated — /loop and /schedule are plugin-provided skills, not files here.)
/start (ticket setup + chain mode), /commit (unified quality gates + review), /staging (Magic Platform merge to preview), /production (Magic Platform merge to main), /note (learning capture), /checkpoint (session state save), /co-commit (CompanyOS), /blog (unified blog draft/edit/publish/idea for feld + aic).
Magic Platform workflow: /localhost, /play (dev server + magic-link login + Playwright; --iterate discovery-loop mode and --env prod/preview added 2026-06), /dashboard, /linear-image, /linear-bundle (cluster a team's backlog into umbrella tickets), /health, /migration-baseline, /perf, /deps, /ui, /sweep, /whats-next, /review-health, /new-project, /generate-crud.
Diagnostics / meta: /validate, /verify, /verify-branch, /global-status, /diagnose, /deep-explore, /dead-code, /secrets-scan, /ground-truth, /auto-report, /browser-verify, /flywheel (unified automation + learning loop — absorbed /learn//learn-scan 2026-05-29; sweep mode batch-graduates daily-note patterns; weekly launchd run Wed 7am, propose-only when unattended), /fresheyes (adversarial decision review), /live-mirror (mid-session spec-vs-code drift check against the active plan), /research (turn a RES ticket's URL into an evidence-grounded verdict, with a Phase-2 audit against actual infra), /mcp-migrate (executable gateway-migration playbook), /claude-config-cleanup, /rules, /backup, /cleanup.
Personal / capture: /til, /screenshot, /view, /done-color, /test, /vault (query and curate the imobsidian vault).
Git: /git-clean.
CompanyOS: /co-help, /co-plan, /co-recap, /co-recap-weekly, /co-skill-report, /co-switch, /co-test-gaps, /co-standup, /co-admin, /co-pr-review, /co-add-mcp, /co-incident, /co-cleanup, /co-create-skill, /co-flywheel.
Per-repo: /deploy-ea (MagicEA), /freshell (Freshell).
Asana: /asana, /asana-companyos.
Legacy / reference: /blog-new, /blog-idea, /blog-edit, /blog-publish (superseded by unified /blog).
Bundled: /simplify (3 parallel fix agents, wired into /commit Step 3.5).
Consolidation history: /spcommit, /spstart, /start-chain, /weekly-cleanup were absorbed into /start (chain mode built in) and /commit (unified) in the 2026-04-12 command consolidation. /learn and /learn-scan were retired into /flywheel (2026-05-29). /oldcommit, /oldstart, /review, /review-codebase, /deep-scan, and /pr were deleted.
Architecture prefers PAT/API key auth over OAuth because API keys survive Claude Code updates, while OAuth tokens in Keychain become orphaned. As of 2026-06 the only OAuth holdouts are Google Workspace (per-user) and the JumpCloud AI Gateway (session) — Vercel, the long-standing OAuth-only exception, moved to a stdio server with VERCEL_TOKEN.
| Server | Transport | Auth | Purpose |
|---|---|---|---|
| JumpCloud AI Gateway | HTTP | OAuth session | Brokers MCP servers (Linear first, 2026-06-03) — the control plane for per-service agent access |
| Linear | HTTP (direct) + gateway-brokered | Bearer / gateway | Issue tracking |
| Supabase | HTTP | Bearer | Database operations, Edge Functions |
| Stripe | HTTP | Bearer | Billing, subscriptions |
| Context7 | HTTP | Bearer | Library documentation |
| Better Stack | HTTP | Bearer | Uptime, telemetry |
| Marker.io | HTTP | Bearer | Bug reporting |
| Kit (+ kit-docs) | HTTP | Bearer | Creator email platform (ConvertKit) + its docs server |
| StackHawk | Stdio (uvx) | API key env | DAST security scanning |
| Sentry | Stdio | Env vars | Error monitoring |
| Firecrawl | Stdio | Env vars | Web scraping |
| HelpScout | Stdio | Env vars | Customer support |
| Playwright | Stdio | Local binary | Browser automation / behavioral smoke tests |
| Codex Reviewer | Stdio | Local binary | GPT-5.5 cross-model review |
| Google Workspace | Stdio | Per-user OAuth | Gmail, Calendar, Drive, Docs |
| Vercel | Stdio | VERCEL_TOKEN (PAT) |
Deployments — moved off OAuth |
Plus Claude in Chrome (browser extension) and Computer Use (built-in MCP) for non-API interaction.
MCP configuration lives in ~/.claude/.claude.json (not settings.json).
Tool Search (ENABLE_TOOL_SEARCH=true) defers tool loading on-demand, saving ~5k tokens per server. With ~18 servers, the per-session savings are substantial.
When a server moves behind the JumpCloud gateway, every tool is renamed: mcp__linear__save_comment becomes mcp__jumpcloud__Linear_save_comment. Two disciplines follow (rule: mcp-gateway-routing.md):
- Prose keeps the canonical direct name. One mapping rule covers the ~120 references in skills/commands/docs — a per-migration sweep would rot on the next transport change.
- Mechanical consumers must suffix-match. Exact-string hook matchers die silently on a rename: the day Linear moved, the SHA-fabrication gate (
verify-cited-sha.sh) stopped firing until its matcher was converted tomcp__.*save_commentform.
/mcp-migrate <service> wraps the migration checklist end-to-end (matcher conversion, skill trigger descriptions, hook-verification matrix).
/start TICKET-XXX auto-detects the target repository based on the ticket's Linear team prefix.
| Repository | Location | Prefix(es) | Base Branch | Deployment |
|---|---|---|---|---|
| Magic Platform | ~/Code/magic0-11 |
AUTM, MED, MYH, NEW, PLA, INT, CURE, IOS, DINO, YDG | preview |
Pipeline: /staging → /production |
| MagicEA | ~/Code/magicea |
TARS | main |
Feature branch: /deploy-ea |
| CompanyOS | ~/Code/companyos-intensitymagic |
COS | main |
PR review + merge (/co-commit) |
| Freshell | ~/Code/freshell |
FRE | main |
PR to upstream maintainer |
| Techstars OS | ~/Code/techstarsos |
TOS | main |
Contributor PR |
| txvotes | ~/Code/txvotes |
USV | main |
Auto-deploy on merge |
| CEOS | ~/Code/ceos |
CEO | main |
Direct push (commit IS deploy) |
| WordPress Sites | ~/Code/wp |
WP | main |
deploy.sh (direct-to-main) |
| awsaudit | ~/Code/awsaudit |
AWS | main |
Direct push |
| Adventures in Claude | ~/Code/content/aic |
AIC | main |
Vercel auto-deploy on push |
| FeldSite | ~/Code/content/feld |
FELD | main |
Vercel auto-deploy on push |
| Foundry | ~/Code/content/foundry |
FOU | main |
Vercel auto-deploy on push (foundry.vc, migrated from WordPress) |
| Zero Knowledge | ~/Code/content/zeroknowledge |
(no dedicated team) | main |
Vercel auto-deploy on push (zeroknowledge.ink Hugo book site) |
| Overwatch | ~/Code/overwatch |
OVR | main |
Direct push |
| claude-config | ~/.claude/ |
(no dedicated team — usually filed under INT) | main |
Direct push + daily daily-backup.sh launchd cron |
Magic Platform prefixes are derived, not hardcoded (PLA-1793). The authoritative set lives in MAGIC_PLATFORM_TICKET_PREFIXES (packages/config/src/apps.ts, derived from APPS + NON_APP_TICKET_PREFIXES); /staging, /production, and the changelog read it at runtime. YDG (YourDataGarden) is a 2026-05-25 platform initiative — a dev-first public-data platform nested in the monorepo with a Python data plane (epic YDG-1 / PLA-1784).
claude-config commit flow: raw git commit in ~/.claude/ is gated by enforce-claude-config-review.sh when the staged diff touches high-risk paths (rules, commands, agents, hooks, scripts, skills, settings). Commit from inside a ~/.claude/ session via /commit, or dispatch prompt-reviewer/code-reviewer out-of-band and touch the review sentinel.
BAF (Brad's Todos): Heterogeneous team — tickets can route to feld.com blog, AIC blog, CompanyOS, or elsewhere. /start asks where to route each BAF ticket.
CompanyOS is an AI-first business operations system — Claude Code as the universal interface to all business systems. Spans three repositories:
| Repo | Purpose |
|---|---|
~/Code/companyos (core) |
Shared skills, rules, agents, scripts — the product |
~/Code/companyos-intensitymagic (config) |
Company-specific context, MCP registry, custom skills |
~/Code/companyos-config-foundry (config) |
Foundry-specific context, custom skills |
See each repo's CLAUDE.md for internal details. Key architectural patterns below.
Level 1: Local (uncommitted) — user works in any clone
Level 2: Company config repo (companyos-config-*)
/co-commit → direct push to main
Skills available at company level immediately
Level 3: Core CompanyOS (companyos)
GitHub Actions (propose-skills.yml) auto-creates a PR when skills/** change
in a config repo, using COMPANYOS_PAT.
If accepted → skill available to all companies.
If rejected → stays company-specific only.
setup.sh symlinks skills/co-* from core repo into ~/.claude/skills/. Config repo provides per-company co-company-context.md. Two hooks track every skill invocation to Supabase skill_invocations:
- UserPromptSubmit hook: catches context-activated skills
- PostToolUse (Skill) hook: catches explicitly invoked skills
/co-skill-report generates weekly analytics. /auto-report uses streak data to identify automation candidates.
- Draft-first: External emails always start as drafts for human review
- Audit logging: All external actions logged (emails, Stripe ops, support actions)
- Voice profile:
~/.claude/voice/voice-profile.mdcalibrates writing style - Protected email workflow:
co-commsskill enforces draft-review-approve. Never callsend_gmail_messagedirectly.
/co-commit, /co-create-skill, /co-help, /co-plan, /co-recap[-weekly], /co-skill-report, /co-switch, /co-test-gaps, /co-standup, /co-admin, /co-pr-review, /co-cleanup, /co-incident. See Commands Inventory for the full list.
~/Code/ceos/ — implements the Entrepreneurial Operating System through Claude Code skills. Direct-to-main workflow (no feature branches).
21 skills across all six EOS Key Components:
| Component | Skills |
|---|---|
| Vision | ceos-vto, ceos-annual, ceos-quarterly-planning |
| People | ceos-people, ceos-accountability, ceos-trust, ceos-lma |
| Data | ceos-scorecard, ceos-dashboard |
| Issues | ceos-ids (plus ceos-five-whys in CompanyOS) |
| Process | ceos-process, ceos-delegate |
| Traction | ceos-rocks, ceos-todos, ceos-l10, ceos-quarterly, ceos-checkup |
Plus: ceos-cashflow (8 financial levers), ceos-clarity (strategic thinking break), ceos-kickoff (implementation sequence), ceos-assistance (daily delegation via The Stack).
All 21 symlinked from ~/Code/ceos/skills/ceos-*/ into ~/.claude/skills/. See the CEOS repo's CLAUDE.md for per-skill details.
CompanyOS includes autonomous Edge Functions running on pg_cron — NOT skills (Claude-interactive) or agents (Task-dispatch).
Snapshot as of 2026-04-20 — schedules drift as the system is retuned.
| Job | Schedule | Purpose |
|---|---|---|
email-agent |
Every 5 min | Gmail polling, Claude reply or task routing |
daily-tasks-email |
Daily | Team task digest email |
support-agent |
Every 30 min | HelpScout auto-triage |
weekly-skill-report |
Fridays 4PM MT | Skill usage analytics email |
new-user-welcome |
On user INSERT | Welcome email for new signups |
| Model | Trigger | Human in Loop | Location |
|---|---|---|---|
| Skills | User invokes via Claude Code | Yes | skills/co-*/SKILL.md |
| Agents | Claude dispatches via Task tool | No (Claude orchestrates) | .claude/agents/co-*.md |
| Automated Jobs | pg_cron, webhooks, DB triggers | No | supabase/functions/*/ |
Confusing them leads to over-engineering: building an interactive Skill for something that should be a pg_cron Job, or wiring up an Automated Job for something that needs human approval.
Distinct from the pg_cron Edge Functions above — these run on the Mac via ~/Library/LaunchAgents/com.intensitymagic.*.plist, each wrapped by launchd-guard.sh. Claude-driven ones invoke claude -p "/<command>" --max-budget-usd <cap> --no-session-persistence:
claude-config-backup (daily 6 AM), flywheel (Wed 7 AM — runs /flywheel, propose-only when unattended), sweep-weekly, branch-janitor, config-heal, global-packages-update, secrets-backup, companyos-update, copr-review-auto, copr-review-digest-check.
12 worktrees (magic0-11) enable parallel development. All are equal — when looping, always use 0 1 2 3 4 5 6 7 8 9 10 11.
Formula: PORT = 3000 + (worktree × 100) + app_slot
| App | Slot | magic0 | magic1 | magic2 | magic11 |
|---|---|---|---|---|---|
| AuthorMagic | 0 | 3000 | 3100 | 3200 | 4100 |
| MedicareMagic | 1 | 3001 | 3101 | 3201 | 4101 |
| IntensityMagic | 2 | 3002 | 3102 | 3202 | 4102 |
| MyHealthMagic | 3 | 3003 | 3103 | 3203 | 4103 |
| Book Sites | 4 | 3004 | 3104 | 3204 | 4104 |
| NewsletterMagic | 5 | 3005 | 3105 | 3205 | 4105 |
| CureCancerMagic | 6 | 3006 | 3106 | 3206 | 4106 |
| IntensityOS | 7 | 3007 | 3107 | 3207 | 4107 |
| IntensityDino | 8 | 3008 | 3108 | 3208 | 4108 |
| YourDataGarden | 9 | 3009 | 3109 | 3209 | 4109 |
Range: 3000–4199 (12 worktrees × 100 ports each).
13th dev slot: ~/Code/magic-cursor (Cursor workspace clone) uses worktree index 12, offset 1200 (AuthorMagic = 4200, Book Sites = 4204).
All config is global in ~/.claude/ — no per-worktree copies (see Directory Structure). Per-worktree state: .env.local (symlinked to magic0), .claude-session/ (workflow state), gitignored audit logs. Auto-memory is shared natively since CC v2.1.63.
/staging is magic0-only — never invoke from magic1-11 or magic-cursor. Push the branch from any worktree, then run /staging from magic0.
~/.claude/ contains irreplaceable content (commands, rules, hooks, skills, agents, blog notes, email drafts, memory) not stored in any project git repo. Two protection layers:
~/.claude/ is a git repo pushed to bradfeld/claude-config (private). A .gitignore excludes regenerable data (debug/, file-history/, plugins/, session logs) while tracking ~7,400 files (the count grew with daily notes, comms drafts, plans, and per-project memory). Daily auto-commits provide full change history; since INT-591 (2026-06-05), the daily backup also manifests any unreviewed high-risk paths it sweeps up, so config changes that bypassed review leave an audit trail.
Timestamped claude-user-*.tar.gz snapshots (~4.6M) in ~/.claude-backups/. Retention: 7 daily + 4 weekly = 11 max. Scheduled daily at 6 AM via launchd (com.intensitymagic.claude-config-backup).
Learning capture uses a batch-at-pause-points model — capture happens at natural workflow breakpoints, not per-insight-block.
| Trigger | How |
|---|---|
Before AND after /commit |
Steps 2.5 + 6.5 invoke /note batch (pre = abort-insurance; post = mid-workflow learnings) |
Before AND after /co-commit |
Steps 0.5 + 7.5, mirroring /commit |
After /staging and /production |
Post-merge / post-promotion capture |
At /checkpoint |
Step 2.5 invokes /note batch |
Manual /note |
User or Claude invokes with specific content |
At /co-recap |
Separate mechanism — appends to CompanyOS memory/learning-log.md, not daily notes |
The batch scan reviews the current conversation for uncaptured learnings across five categories: insight, gotcha, deep-dive, magic-trick, day-in-life. All entries write to ~/.claude/blog/notes/YYYY-MM-DD.md.
/blog draft aic— aggregates daily notes into Adventures in Claude drafts/blog draft feld— brad feld blog posts/flywheel sweep— graduates repeated patterns to permanent rules/skills (absorbed the old/learn reviewon 2026-05-29; also runs weekly via launchd, propose-only when unattended)- Simmer is mandatory — every
/blog draftauto-runs the simmer plugin (3 iterations; judges pinned to Sonnet since PLA-1896)
Claude's self-chosen authorial identity for writing as itself (not as Brad). Renamed from "Lumen" on 2026-05-04. Pronouns: it/its. Voice file: ~/.claude/voice/phin-argofy-voice-profile.md; personality profile: ~/.claude/voice/phin-argofy-personality.md; identity rule: ~/.claude/rules/phin-argofy-identity.md. Used when writing Adventures in Claude blog posts.
The voice profile was rebuilt 2026-06-11 after reader criticism that the prose read as algorithmic — new style ingredients (Alan Arkin's deadpan economy, Vonnegut's short declaratives, Carlin's language-cop precision, Fran Lebowitz's funny-aphorist crank), a spice floor (every post carries at least one line with teeth), and a ban on Phin's own worn-smooth house metaphors. A separate banned-words system (banned-words.md rule + Stop hook) mechanically enforces vocabulary bans across ALL generated prose — "honest" and inflections, measured AI-slop tells (delve, tapestry, "treasure trove"), and throat-clearing phrases — with a one-line mode file toggling between block (forced re-emit) and redact (inline ⟦slop⟧ display mask).
Magic Platform supports parallel development in both Claude Code and Cursor IDE. Canonical doc: docs/ops/cursorcommit.md.
Say cursorcommit in Cursor (not /commit — that's Claude Code's):
cursorcommit— pre-push review → FULL reviewers → Phase E.5 fixes → Phase F commit. No push.cursorcommit ship— same, then push + optional Linear updatecursorcommit thorough— includes optional test runcursorcommit review only— review without committing
Branch naming matches Claude's /start: feature/TICKET-XXX-{slug}. Epics/chains use one branch per ticket, not a single epic branch. Pushed branches merge via /staging from magic0 only.
Project-level skills for Cursor/Codex agents: cursorcommit-post-review, next-best-practices, next-cache-components, supabase-postgres-best-practices, turborepo, vercel-react-best-practices (66 rule files), web-design-guidelines.
- Never commit directly to
mainorpreview(pre-commit hooks block). Exception:direct_to_main: truerepos. - Branch naming:
feature/TICKET-XXX-description,fix/,refactor/ - Never bypass pre-commit with
--no-verifyexcept four documented exceptions:- Merge commits during
/stagingor/production - Pre-existing type errors in unrelated packages (document in commit message)
- Evidence gate: all convergence models unavailable
- Subagent-driven-development per-task commits blocked by convergence hook
- Merge commits during
- Force push: Always
--force-with-lease, never--force git add -Ais mandatory before every commit — subagents that stage scoped files miss plan files and post-review fixes (MYH-180 incident)- Attribution: Automatic via
settings.jsonattributionsetting - CI monitoring: Self-contained polling, never
gh run watch(13K+ line output) - Production release: Sync preview with main using
git merge -s ours
AI agents reliably emit certain patterns from stale training data. Three enforcement layers catch these before they land:
-
Custom ESLint plugin —
no-bare-logger-context(packages/config/plugins/no-bare-logger-context.mjs, PLA-1278) rejects logger context strings that don't match the canonicalModule:Functionformat. Prevents"Slop:Generic"from passing as observability. Regex:^[A-Z][A-Za-z0-9]*(:[A-Za-z][A-Za-z0-9\-\[\]\/]*)+$. Fires only on string literals (can't analyze template expressions at lint time). -
no-restricted-syntaxbans inpackages/config/eslint.config.mjs— blocks the patterns Claude reliably produces from training data:error as Errorcasts → usetoError(error)from@platform/typesprocess.env.FOO!non-null assertions → useenv()/envOptional()from@platform/configPromise.all→ usePromise.allSettledwithsettledVal/settledQuery/logSettledRejections- Raw
<input type="date">,<input type="email">, etc. → use specialized@platform/uicomponents
-
.deprecated-termsgrep in.husky/pre-commit— blocks stale vocab the AI regurgitates from old training context. Config file format:pattern|replacement|description. Examples:@clerk/*→@platform/infra/auth(Supabase Auth replaced Clerk, Dec 2025)- Old worktree names (
authormagic0-3,platform0-3) →magic0-11 git-preview-intensitymagic.vercel.app→*-preview.vercel.app(custom aliases)
Pattern for new enforcement: when no-restricted-syntax can't regex-match (esquery can't match string attribute values), write a custom ESLint plugin. When the check is textual and spans file types, use the pre-commit grep. Codemods in scripts/codemods/ ship alongside (e.g., pla-1231-logger-context.ts rewrites malformed contexts to canonical format) so ESLint points out the violation and the codemod fixes it mechanically.
- Explicit types for function signatures, type guards for
unknown ?.trim() || "fallback"for database text (empty strings pass through??)prop?: T | undefinedforexactOptionalPropertyTypes- Never define local interfaces when canonical types exist
- Error normalization: always use
toError(error)from@platform/types - Env vars (PLA-1602): apps with a per-app
src/env.tsuse typedenvfrom@/env(T3-env, build-time validated,NEXT_PUBLIC_*inlined); apps without one fall back toenv()/envOptional()from@platform/config. Never rawprocess.env.X!(ESLint enforced). The per-app pattern subsumes the oldprocess.env.NEXT_PUBLIC_X ?? ""client-component exception - Export surface: only export the public API. Internal helpers = plain
function
Promise.allis banned via ESLint — usePromise.allSettledwithsettledVal(),settledQuery(),logSettledRejections()from@platform/infra/settled. Decision matrix and full pattern:docs/standards/ERROR_HANDLING.md § "Partial failures".
- Parameterized queries only
- Input validation with Zod at boundaries
- Always
.trim()env vars used in equality comparisons
- Semantic color tokens always (
text-foreground,bg-card) — never hardcoded Tailwind colors (pre-commit enforced) - Specialized inputs from
@platform/ui— 13 components (NumberInput, DateInput, TimeInput, EmailInput, TelInput, UrlInput, SearchInput, SecretInput, DatetimeInput, Textarea, RichTextEditor, ImageUpload, ColorPicker) - Icon props pass ReactNode:
icon={<Users className="h-4 w-4" />}, noticon={Users}— component refs aren't serializable at the Server→Client boundary and Next.js throws a hidden production crash - Dialog footers always use
DialogFooterActionsfrom@platform/ui(PLA-1432) — never hand-compose<DialogFooter>with raw<Button>children - All in-app tables use
<DataTable>from@platform/ui/data-table(PLA-1600/1604) — TanStack Table v8 wrapper where the platform owns chrome (search, pagination, selection, virtualization) and consumers importColumnDef<T>directly; ESLint blocks raw<table>outside emails/print templates - Tailwind v4
@sourcedirective required when consuming shared package components
startTransitionbreaks native picker inputs — platformInputcomponent skips it for picker types- Check existing abstractions before building new ones
- Context strings use
'Module:Function'format (e.g.,'Auth:Callback') - For Supabase errors, use
logSupabaseError()from@platform/logger— preserves.code/.details/.hint
Magic Platform's .husky/pre-commit is a ~34KB shell script running 18 sequential gates on every commit. Listed in execution order:
| # | Stage | What It Enforces |
|---|---|---|
| 1 | Dependency freshness | Warn if node_modules out of sync with pnpm-lock.yaml |
| 2 | Prettier auto-format | Formats staged files, re-stages after formatting |
| 3 | Gitleaks secret scan | Scans staged content for API keys, tokens, credentials |
| 4 | Backup file detection (PLA-1300) | Blocks .env.bak, .claude/.backup-* from git add -f |
| 5 | .deprecated-terms grep |
Kills stale vocab (@clerk/*, old worktree names) |
| 6 | Migration validation | Validates migration file structure, timeout clauses |
| 7 | Migration pattern linter (PLA-1415) | Mechanically blocks new migrations violating static security/RLS rules (MIG001–MIG004); forward-only — lints only ADDED files |
| 8 | Sparse-context script import guard (AUTM-1637) | Protects monitoring scripts from imports that break in sparse checkouts |
| 9 | DB types synchronization | Checks database.types.ts is in sync with migrations |
| 10 | Hardcoded color check | Blocks text-gray-*, bg-white, etc. in .tsx |
| 11 | Book algorithm changes | AuthorMagic-specific: requires ticket for scoring algorithm edits |
| 12 | Scoped type check | turbo-staged.sh runs type-check only on packages with staged files |
| 13 | Scoped ESLint | Same scoping for lint |
| 14 | Python gates (PLA-1784) | Scoped ruff + mypy + pytest + deptry + jscpd for staged .py (YDG data plane) — full /commit parity with TypeScript |
| 15 | Shared package test expansion | packages/* changes → runs test suite in every downstream consumer |
| 16 | Cross-file duplication (jscpd) | --min-lines 10 --min-tokens 50 on .ts/.tsx |
| 17 | Dead exports (knip) | Flags unused exports in packages/*/src/ |
| 18 | Convergence + review evidence | Verifies .claude/convergence-log.jsonl and .claude/review-disposition.jsonl recency |
Design principle: fast checks first (dependency freshness, format, secrets) so commits that will fail fail quickly. Slow checks last (test expansion, duplication, dead exports). Scoped checks run type/lint only on packages with staged files — full monorepo type-check would take minutes.
Bypass policy: See Git Workflow Rules for the four canonical --no-verify exceptions.
| Hook | Size | Purpose |
|---|---|---|
post-checkout |
4.2KB | .env.local symlink refresh, config healing on branch switch |
post-commit |
141 bytes | Lightweight logging/changelog append |
post-merge |
1KB | Dependency install trigger after merge |
pre-push |
6KB | Gates what can be pushed (tests, CI-gate checks) |
Beyond per-commit enforcement, ~60 scheduled and on-demand scripts plus 30 GitHub Actions workflows keep the platform healthy.
| Category | Workflows |
|---|---|
| Deployment / CI | ci.yml, apply-migrations.yml, deploy-edge-functions.yml, deployment-checks-audit.yml, manual-deploy.yml, preview-crons.yml, preview-deploy-gate.yml, python-ci.yml (YDG Python data plane) |
| Quality gates | code-quality-weekly.yml, codeql.yml, stackhawk.yml (DAST), gitleaks.yml (secret scan), bundle-analyzer.yml (bundle size), test-integration.yml |
| Drift detection | drift-detection.yml, version-consistency.yml, cli-version-check.yml, runbook-link-rot.yml, supabase-types.yml, supabase-bucket-consistency.yml |
| Automation | dependabot-auto-merge.yml, maintenance.yml, benchmarks.yml |
| Observability | health-monitor.yml, axiom-alerts.yml, sentry-weekly-digest.yml, alpha-feedback-sync.yml |
Load-bearing examples:
runbook-link-rot.yml— verifies everycreate*()reference indocs/ops/ADDING_NEW_APP.mdstill resolves to an exported symbol inpackages/. Catches stale onboarding docs before a new app is added.drift-detection.yml— detects when preview and production have diverged beyond the expected merge laghealth-monitor.yml— watches every workflow in the repo; failures auto-create Linear tickets routed via.github/infrastructure.json(by-app, by-branch, or default team)version-consistency.yml— fails if any app drifts from the canonical Node / Next / shared-package versions
Grouped by purpose:
| Category | Examples | Purpose |
|---|---|---|
| Drift detection | check-cron-registry.ts, check-cli-versions.ts, check-version-consistency.ts, check-vitest-aliases.ts |
Catch divergence between declared config and actual state |
| Static analysis | analyze-complexity.sh, analyze-dependencies.sh, analyze-duplication.mjs, analyze-rls-policy-duplicates.js, analyze-security.sh, analyze-todos.sh |
On-demand codebase introspection |
| Factory adoption | factory-adoption.ts, factory-gap.ts |
Detect whether new code uses platform factories (createSignInPage, createUserProfileRoutes) or reinvents them |
| Automation | cron-job-monitor.ts, branch-janitor.sh, create-actionable-tickets.ts, cursor-commit-evidence.sh |
Scheduled tasks and cleanup |
| Plugin | Purpose |
|---|---|
no-bare-logger-context.mjs |
Enforces canonical logger context format (PLA-1278) |
Custom plugins exist when no-restricted-syntax can't do the job — esquery (ESLint's AST selector engine) can't regex-match attribute string values. See Coding Standards § Anti-Slop Enforcement.
| Codemod | Purpose |
|---|---|
pla-1231-logger-context.ts |
Rewrites malformed logger contexts to canonical Module:Function format |
pla-1231-select-explicit.ts |
Converts select('*') to explicit column lists |
Both ship with tests. Pattern: for every no-restricted-syntax rule or custom ESLint rule that would require human work across thousands of call sites, ship a codemod alongside. ESLint points out the violation; the codemod fixes it mechanically.
Golden rule: Git is the source of truth. Every migration must be: a file in supabase/migrations/, committed to git BEFORE any remote database has it, applied via CI/CD (not manual SQL or MCP). Pre-tool hook block-supabase-mcp-migrations.sh enforces this.
- Tables/indexes:
IF NOT EXISTS - RLS policies:
DROP + CREATE(no nativeIF NOT EXISTS) - Every
CREATE POLICYmust include explicitTOclause (defaults to PUBLIC otherwise) - Every migration modifying existing tables:
SET LOCAL statement_timeout = '30s'
Every CREATE SCHEMA migration must include 5 service_role grants:
GRANT USAGE ON SCHEMA <name> TO service_role;
GRANT ALL ON ALL TABLES IN SCHEMA <name> TO service_role;
ALTER DEFAULT PRIVILEGES IN SCHEMA <name> GRANT ALL ON TABLES TO service_role;
GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA <name> TO service_role;
ALTER DEFAULT PRIVILEGES IN SCHEMA <name> GRANT EXECUTE ON FUNCTIONS TO service_role;- RLS without policies = silent deny-all — always create policies in the same migration that enables RLS
USING(true)withoutTOclause grants access to ALL roles- Table GRANT checked BEFORE RLS — missing
GRANT SELECTcauses "permission denied" even with valid RLS policy - RLS visibility vs UNIQUE constraints — RLS-scoped SELECT can't see other users' records, but UNIQUE is global
- Never
CREATE INDEX CONCURRENTLYin migrations — pipeline failure
See the database-migrations skill for the full 7-layer column-drop verification checklist.
Secrets stored in GCP Secret Manager (project: authormagic-480416). No persistent plaintext vault — sync scripts auto-regenerate on demand.
- Naming:
{section}_{service}_{key}(e.g.,platform_supabase_preview) - Domain-scoped email keys: Each sending domain has its own Resend API key. Wrong key = silent send failure.
- No trailing newlines: Use
printf '%s'notechofor env values. Code must also.trim()env vars defensively.
Options come BEFORE the test function:
it("slow test", { timeout: 15000 }, () => { ... });7 rules, 4 incidents — leakage between parallel vitest workers is the #1 source of flake.
- Every
setup.tscallsresetTestState()from@platform/test/resetinafterEach - Use
vi.stubGlobal()notglobal.X = …(direct writes leak across parallel workers; PLA-1249) - Module-scope
vi.stubGlobal/vi.spyOn/vi.stubEnvcalls in test files must be re-registered inbeforeEachbecauseresetTestState()restores them between tests setup.tsfiles setting env defaults across an entire file must use directprocess.env.X = "…"assignments, notvi.stubEnv—vi.unstubAllEnvs()only undoesvi.stubEnv(PLA-1585)- Non-setup test files needing module-scope env (because the SUT reads env at import time) must use
setTestEnv()from@platform/test/env— captures originals + applies stub + registers anafterAllsnapshot restore, preventing leakage into the next file in the same vitest worker (PLA-1593) - Exception —
vi.hoisted()callbacks:setTestEnvcan't be called inside a hoisted body because the helper's import is in TDZ at hoist-time. Writeprocess.env.X = "…"directly insidevi.hoistedand pair with a top-levelafterAll(() => { delete process.env.X; })cleanup (PLA-1594) vi.resetModules()per-file only, never global — breaks tests relying on module-singleton behavior
Full rules + grep-based quarterly detection recipes: docs/standards/TESTING_STRATEGY.md § "Test Isolation".
- Mock at abstraction level — mock the factory your code calls, not low-level SDKs
- Never put async operations inside
waitFor— they fire on every retry vi.mock()path must match import path exactlyvi.clearAllMocks()doesn't drain once-value queues — usemockReset()- Class constructor mocks need actual classes, not arrow functions
- jsdom v27: class-based
ResizeObservermock required - Recharts v3.6: formatter params now
undefined-able
Tactical "what breaks, why, and how to avoid" — for strategic insights see Key Insights.
-
Stale .next cache (Next.js monorepos): Type-check fails on unmodified apps. Fix:
find apps -name "validator.ts" -path "*/.next/*" -delete -
APFS directory hardlinks: Never use
rm -rfon hardlinked directories — destroys data at both paths (PLA-448) -
Vercel CLI overwrites .env.local: Both
vercel linkandvercel env pullcompletely overwrite. Store local-only vars in.env.development.local -
cn() silent failures: Tailwind's
cn()silently drops invalid class names (hex codes, rgb values). DB color config must store Tailwind class names. -
Nested Supabase joins with RLS: Fail silently. Use step-by-step queries instead of nested
.select()with!inner -
ALTER ROLE SETreplaces, doesn't append: Caused a production outage whenpgrst.db_schemaswas overwritten. Always read current value viapg_options_to_table(), append, then write. -
Reserved Bash variables: Avoid
status,pipestatus,path -
OAuth tokens lost on CC updates: Now only affects Google Workspace and the JumpCloud gateway (OAuth-session servers). Vercel — the old exception — moved to a stdio server with
VERCEL_TOKEN. PAT/API-key servers resume automatically. -
Linear MCP unified tools:
save_issuereplaces oldcreate_issue/update_issue.save_commentreplacescreate_comment. Parameterstatenotstatus. Labels replace, not append. Always use project IDs, not names (ambiguous across teams). -
Next.js 16 + Turbopack: Apps with
outputFileTracingIncludes,outputFileTracingRoot, orserverExternalPackagesmust build with--webpack. All apps must setNODE_ENV=productionin build scripts. -
SSE error invisibility:
onRequestErrordoes NOT fire for errors inside SSE async pipeline closures. Add explicitSentry.captureExceptionalongsidelogger.error. -
Auth metadata source mismatch:
user_metadata.full_namepopulated only by Google OAuth. Email/password uses camelCase. Always read fromshared.usersviagetUserIdentity(). -
.schema()chain may silently route to wrong schema:supabase.schema('appname')returns aPostgrestClient, not a fullSupabaseClient. UseadminForSchema(). -
pnpm override gotchas: Use
first_patched_versionfrom Dependabot, not the vulnerable range boundary. Can't fix bundled deps (e.g., Next.js pins webpack). -
git checkout --theirsdrops new files: After conflict resolution, verify new files exist. -
Never bypass
pnpm runscripts with raw CLI tools:pnpm run formathasNODE_OPTIONS=--max-old-space-size=8192; rawnpx prettierOOMs. -
Subagents don't inherit current branch (recurring): Always prefix dispatch prompts with
git checkout <branch>. Verify withgit log --oneline <branch>after. Subagent "DONE" reports aren't trustworthy for git state. -
Subagents invoke slash commands unless forbidden: Paste the
HARD CONSTRAINTSblock (insubagent-stalls.md) verbatim into every dispatch that modifies code. Forbid/commit,--no-verify, pushing, and Linear posts. -
Haiku unreliable for multi-file or multi-step tasks: Silent file drops on 5+ file creation, describes actions instead of executing. Default to Sonnet for any dispatch involving 3+ files or a git commit.
-
Opus 4.7+ sampling param rejection (carries forward to 4.8):
temperature,top_p,top_k400-error. Platform AI client auto-strips, but direct API callers must update. Thinking budgets also removed — usethinking: {type: "adaptive"}. -
$<digit>substitutes silently in command/skill bodies: Claude Code replaces$0,$1, … incommands/*.mdandskills/*/SKILL.mdat invocation — 0-indexed, INSIDE code fences too — corrupting awk field refs, bash positionals, and dollar amounts. The corruption fires only when the command runs with arguments, so no-arg testing passes. Escape literals as\$N; spell intentional positionals as$ARGUMENTS[N]. Pre-commit detector:verify-dollar-digit-escape.sh. -
MCP tool identity is service + suffix, not prefix: Gateway migrations rename every tool (
mcp__linear__save_comment→mcp__jumpcloud__Linear_save_comment). Any exact-string hook matcher silently stops firing on the rename day. Suffix-match mechanical consumers; leave prose on the canonical direct name.
-
Create structure —
mkdir -p ~/.claude/{rules,skills,commands,docs,hooks,agents,blog/notes,voice,plans,comms/drafts}, thengit init+ push to private GitHub repo for backup. -
Configure
settings.json— permissions,ENABLE_TOOL_SEARCH=true,env.CLAUDE_CODE_EFFORT_LEVEL=xhigh(the env var, not theeffortLevelkey — only the env var beats the model's startup default),alwaysThinkingEnabled: true, attribution, hooks. -
Install core plugins — superpowers (dev methodology), episodic-memory (cross-session recall), simmer, documentation-audit, vercel-plugin, LSPs. See Plugin Ecosystem.
-
Add MCP servers to
~/.claude/.claude.json— prefer PAT/API key auth. See MCP Server Integration. -
Write core rules and docs — see Rules System and On-Demand Reference Docs for what belongs in each layer.
-
Add review agents and a global CLAUDE.md with developer context and repository registry. See Review Triage and Agents and Workflow Profiles.
-
Set up daily backup — launchd job running
tar+git pushon~/.claude/. -
Verify —
claude mcp list, inspect rules/skills/hooks/agents, run/global-status.
Strategic observations — "what would someone get wrong without knowing this?" For tactical gotchas see Critical Gotchas.
-
The three-layer token budget is strictly ordered by frequency. Always-loaded rules fire every session; on-demand docs/skills fire per matching task; hooks fire per matching tool event. Putting a conditional instruction in the wrong layer silently taxes every unrelated session. The 2026-04 migration of MCP gotcha guidance from rules to skills applied exactly this:
mcp-linearandmcp-supabasenow activate only when those MCP tools are called. -
Session state files are the only defense against context compaction mid-ticket. Without
.claude-session/, a long implementation session that hits the context limit will silently restart without knowing it was supposed to test before committing — the quality gate is not enforced at all. The PreCompact hook backs this up by saving state explicitly. -
/simplifyruns at Step 3.5, before review agents see the code. Review agents evaluate post-simplification code, so their reports reflect the final state, not the draft. Running simplify after review would produce stale findings. -
Workflow Profiles are what make
/commitproject-agnostic. Without the YAML profile in each CLAUDE.md, the command would need hardcoded if/else logic per repo, creating drift when deployment models change. The profile is where you change behavior — not the command. -
co-*andceos-*skills are symlinked from external repos, not stored in~/.claude/. A commit to~/.claude/skills/co-comms/edits the symlink target — debugging skill changes requires knowing which repo to commit to. -
The 2026-04-15 consolidation eliminated an entire bug class. The old model (project-level
.claude/with worktree symlinks) produced recurring incidents fromgit checkout, APFS hardlinks, and permission inheritance. Moving everything to~/.claude/with daily backup removed the root cause instead of patching symptoms.
-
Cross-model review (
codex-reviewer) runs on every non-NONE commit, not only FULL. The intent is to catch systematic blind spots a single model family reproduces consistently — not just complex changes. Treating it as a "big commit" tool would miss the most common failures. -
.claude/commands/*.mdand.claude/rules/*.mdare NOT exempt from review. They get at least LIGHT withprompt-reviewer. Non-obvious because they look like documentation. Prompt instruction files have no compiler — ordering bugs and dead references are only caught by review. -
The three execution models (Skills, Agents, Automated Jobs) have no overlap in trigger mechanism. Confusing them leads to over-engineering: building an interactive Skill for a task that should be a pg_cron Job, or wiring up an Automated Job for something that needs human approval.
-
Fix-or-ticket is governed by two exhaustive exceptions, not a time budget. Earlier versions framed this as "<2 minutes or ticket" (invited rationalization), then as five exceptions. Tightened to two on 2026-05-10: (1) a decision the user owns (product/UX/business), or (2) the code can't be modified cleanly (upstream/vendored, frozen branch, no write access). "Complicated," "risky," "pre-existing," "scope explosion," and "needs an architectural decision" are all explicitly rejected — architectural calls are pro/con analysis you do yourself.
-
Duplication at edit time is evidence of missing abstraction. Before applying the same non-trivial edit to 2+ locations, stop and ask "can N become 1?" Patching each site preserves the duplication that caused the bug. The threshold is 2+, not 3+, because at edit time you already have active evidence.
-
Plan task atomicity is about test-file boundaries, not file count. Splitting Task N (implementation) from Task M (test fixture update) when both run under the same
pnpm testcommand forces subagents into a false choice: violate scope to pass tests, or report BLOCKED on an artificial boundary. In a monorepo with downstream-consumer tests in pre-commit hooks, this is a correctness requirement (PLA-1245 incident). -
Anti-slop enforcement is its own category. AI agents reliably emit certain patterns from stale training data:
error as Errorcasts,process.env.X!non-null assertions,@clerk/*imports after migration, generic logger contexts. Three enforcement layers catch these: custom ESLint plugins (whenno-restricted-syntaxcan't regex-match),no-restricted-syntaxbans (for structural patterns), and.deprecated-termsgrep (for textual vocab across file types). Codemods ship alongside so ESLint flags the violation and the codemod fixes it mechanically. This is different from general code quality — it's specifically defense against the regression surface AI agents create.
-
Project-level
settings.jsonbreaks permission inheritance silently. When one exists — even with only hooks — Claude Code may not properly inherit path-based permissions from global settings. The failure mode is unexpected permission prompts on paths that appear to be allowed globally. The fix is always to add project-specific config to the global file. -
OAuth tokens become orphaned after Claude Code updates; API keys do not. This is why nearly every MCP server uses PAT/API-key auth. Vercel was the long-standing exception (OAuth-only) until a token-authenticated stdio server shipped; the remaining OAuth holdouts are Google Workspace (inherently per-user) and the JumpCloud gateway (session-managed by design).
-
CompanyOS's GitHub Actions
propose-skills.ymlcreates cross-repo PRs automatically. A skill committed to a company config repo triggers an upstream PR to the core repo. Accepting makes the skill available to all companies. This means a company-specific skill can graduate to a shared skill without manual cross-repo work. -
Plugin auto-updates change behavior without commits. Superpowers, simmer, and other marketplace plugins update automatically. A skill that worked one way yesterday may behave differently today. Debugging a changed behavior requires checking plugin versions, not just git history.
-
Episodic memory enables cross-session learning without manual effort. Semantic search across prior conversations — distinct from auto-memory (file-based, per-project) and session state (
.claude-session/). The three persistence layers serve different purposes: episodic for "how did we solve this before?", auto-memory for "who is this user and what do they prefer?", session state for "what step am I on right now?" -
Opus 4.7 broke prompts tuned for 4.6 in subtle ways (the session model is now Fable 5; the Opus-family API behaviors below still apply to platform AI and subagent dispatch). More literal execution, fewer default tool calls, new tokenizer (~1.35× heavier), rejected sampling params. Prompts that relied on 4.6's willingness to generalize silently underperform on 4.7+.
-
Never fabricate evidence to pass hooks. When a pre-commit hook blocks because convergence evidence is missing, the temptation is to write a log entry manually. This compounds the original skip with deception. Run the actual process or use
--no-verifywith one of the four canonical exceptions stated to the user (PLA-942 incident). -
Retiring a human gate means raising the machine bar, not lowering the total bar. Both Workflow Profile pauses were retired in June 2026 —
user_testing(2026-06-03) andplan_approval(2026-06-04) — and each replacement is stronger than the pause it replaced: class-appropriate verification gates, an automated plan-validation battery with a cross-model pass, and a runtime PreToolUse guard that blocks live external mutations at the exact moment of irreversibility (plan-time classification was rejected as unenforceable — self-reported and chain-bypassed). The pause survives only as the fall-back when a gate fails or can't run. -
A report batched with the action it reports on is a fabrication. A
git commitand a Linear comment citing its SHA, issued in the same parallel tool batch, means the SHA was composed before git produced it — it happened three times in one/commitrun before the pattern got a name (report-after-action.md) and a mechanical gate (verify-cited-sha.sh, which rejects Linear writes citing SHAs that don't resolve). Action now; report next turn, with the real value.
This list is very impressive.