Skip to content

Instantly share code, notes, and snippets.

@bradfeld
Last active February 22, 2026 11:40
Show Gist options
  • Select an option

  • Save bradfeld/1deb0c385d12289947ff83f145b7e4d2 to your computer and use it in GitHub Desktop.

Select an option

Save bradfeld/1deb0c385d12289947ff83f145b7e4d2 to your computer and use it in GitHub Desktop.
Advanced Claude Code Configuration Guide - patterns for professional solo development

Feld Claude Code Configuration Guide

A comprehensive setup for professional solo development with Claude Code, emphasizing workflow discipline, session persistence, and automated quality gates.


Table of Contents

  1. Philosophy: Global-First Configuration
  2. File Structure
  3. Session State Architecture
  4. The Master Workflow
  5. Review Triage System
  6. Workflow Profiles
  7. Rules System
  8. Skills Inventory
  9. Superpowers Plugin
  10. Commands Inventory
  11. MCP Server Integration
  12. Repository Registry
  13. CompanyOS: Shared Configuration
  14. Blog and Learning Capture
  15. Git Workflow Rules
  16. Multi-Instance Safety (Worktrees)
  17. Coding Standards
  18. Database Migration Discipline
  19. Secrets Management
  20. Testing Patterns
  21. Critical Gotchas
  22. Quick Start for New Setup
  23. Key Insights

Philosophy: Global-First Configuration

Core Insight: As a solo developer on one machine, preferences should be consistent everywhere. Project-level configuration creates maintenance burden and inconsistency.

Configuration Type Location When to Use
Permissions, MCP servers ~/.claude/settings.json Always global
Coding rules ~/.claude/rules/ Cross-project standards
Skills/commands ~/.claude/skills/ Reusable workflows
Shared config (two-person) ~/Code/companyos/ CompanyOS skills/rules (symlinked)
Project-specific only project/.claude/ Truly unique patterns

Why this matters:

  • One place to update rules = less drift
  • Claude Code inherits global config automatically
  • Project settings can accidentally override global permissions (causing unexpected prompts)

The Discipline Philosophy: There is no "quick fix mode." Every ticket gets the full workflow. Simple fixes are when discipline matters most — process ensures consistency, documentation, and audit trails.

CRITICAL: Never create project-level .claude/settings.json. When one exists — even with just hooks — Claude Code may not properly inherit path-based permissions from global settings, causing unexpected permission prompts.


File Structure

~/.claude/
├── settings.json          # Permissions, env vars, plugin config
├── CLAUDE.md              # Global instructions for Claude
├── rules/                 # Coding standards (auto-loaded, 17 files)
│   ├── code-quality.md
│   ├── evidence-first.md
│   ├── commit-recipe.md
│   ├── review-triage.md
│   ├── co-*.md            # Symlinked from CompanyOS
│   └── ...
├── skills/                # Auto-invoked based on context (19 file-based skills)
│   ├── linear/
│   ├── testing/
│   ├── co-*/              # Symlinked from CompanyOS
│   ├── ceos-*/            # Symlinked from CEOS
│   └── ...
├── commands/              # User-level slash commands (25 commands)
│   ├── commit.md          # Universal commit workflow
│   ├── start.md           # Universal ticket start workflow
│   ├── checkpoint.md
│   ├── note.md
│   └── ...
├── comms/
│   └── drafts/            # Email drafts (draft-review-approve loop)
├── blog/
│   └── notes/             # Daily insight capture
│       └── YYYY-MM-DD.md
├── hooks/                 # File protection hooks
├── scripts/               # Utility scripts
└── PATTERNS.md            # Gotcha graduation journal

~/.claude-personal/
├── CLAUDE.md              # Personal context (separate from shared)
├── .claude.json           # MCP server configuration
├── voice/                 # Writing voice profiles
│   ├── voice-profile.md   # Brad's writing rules (hyphens, no AI slop, etc.)
│   └── samples.md         # Calibration samples
└── projects/              # Project-specific persistent memory
    └── -Users-bfeld-Code-magic0/
        └── memory/
            └── MEMORY.md  # Auto-memory (symlinked across worktrees)

~/Code/companyos/          # Shared two-person config repo
├── skills/co-*/           # 9 skills (symlinked into ~/.claude/skills/)
├── rules/co-*.md          # Shared rules (symlinked into ~/.claude/rules/)
├── .claude/commands/      # CompanyOS-specific commands
├── scripts/
│   ├── git-hooks/         # Version-controlled hooks (auto-push, auto-pull)
│   ├── auto-update.sh     # Launchd auto-sync (--autostash, failure alerting)
│   ├── co-sync            # Manual sync command
│   └── com.intensitymagic.companyos-update.plist
└── setup.sh               # Idempotent installer

project/.claude/
├── commands/              # Project-specific slash commands (18 for magic-platform)
│   ├── staging.md
│   ├── production.md
│   └── ...
└── agents/                # Custom agent definitions

Session State Architecture

The workflow system uses persistent session files that survive context compaction — solving the "amnesia" problem in long Claude sessions.

File Structure

project/.claude-session/
├── TICKET-XXX.json              # Workflow state checkpoint
├── TICKET-XXX-plan.md           # Implementation plan (survives compaction)
├── chain-state.json             # Chain mode orchestration state
└── checkpoint.md                # Full session state (via /checkpoint)

Session JSON Structure

{
  "schemaVersion": 1,
  "ticket": "PROJ-123",
  "ticketUUID": "uuid-here",
  "branch": "feature/PROJ-123-add-user-auth",
  "project": "my-project",
  "targetDir": "/absolute/path/to/project",
  "chainInvokingDir": null,
  "stashCreated": false,
  "stashOriginalBranch": null,
  "workflow": {
    "currentStep": 15,
    "status": "awaiting_user_test",
    "blockedActions": ["git commit", "git push"],
    "nextAction": "User tests manually, then runs /commit"
  },
  "sessionRules": ["integration only", "no new dependencies"],
  "ticketContext": {
    "description": "Full ticket description...",
    "comments": [],
    "isReopened": false,
    "feedbackToAddress": [],
    "previousImplementation": null
  },
  "plan": {
    "file": ".claude-session/PROJ-123-plan.md",
    "postedToLinear": true
  },
  "progress": {
    "filesModified": ["src/auth.ts", "src/middleware.ts"],
    "testsStatus": { "typeCheck": "pass", "lint": "pass" },
    "completedTasks": 12,
    "totalTasks": 15
  }
}

Why Session State Matters

  1. Survives context compaction — Plan and state persist when Claude's context fills
  2. Prevents accidental commitsblockedActions enforces workflow discipline
  3. Enables multi-session work — Resume in different terminal, same state
  4. Session rules enforcement — Constraints from /start apply throughout
  5. Reopened ticket handling — Tracks previous implementation and feedback to address
  6. Chain mode coordination — Tracks multi-ticket progress across context windows

Circuit Breaker Protection

Before ANY git commit, the system checks for session files with status: "awaiting_user_test". If found, commit is BLOCKED:

Cannot commit - session state shows awaiting user test.
Run /commit when ready to review and push.

This prevents bypassing the review workflow.

The /checkpoint Command

Use before context is about to compact:

/checkpoint

Saves: Current ticket and branch, implementation plan, progress, session rules, review status.

Output: .claude-session/checkpoint.md with full state snapshot.


The Master Workflow

Every ticket follows this exact loop — no exceptions:

/start TICKET-XXX
    | Fetch ticket, analyze, create branch, post plan to Linear
    | Sets status: "awaiting_user_test" (blocks git commit)
    v
Implement locally + manual testing
    v
/commit
    | Auto-triage review level -> run reviews -> push -> update Linear
    v
/staging (when ready to deploy batch — magic-platform only)
    | Batch merge feature branches -> deploy -> reset worktrees
    v
/production (after staging verification — magic-platform only)
    | Health audit -> create PR -> manual merge -> verify -> update Linear
    v
LIVE

Note: For direct-to-main repos (CompanyOS, CEOS, Adventures in Claude), /commit IS the deploy — no staging/production steps needed.


/start TICKET-XXX

The entry point for all ticket work. Creates session state and posts plan to Linear.

Modes

Mode Usage Behavior
Single ticket /start AUTM-123 Full 15-step workflow with plan approval
Explicit chain /start chain AUTM-123 AUTM-124 AUTM-125 Sequential autonomous processing of listed tickets
Epic chain /start epic PLA-50 Fetch epic children, process eligible tickets sequentially

Chain Mode

Chain mode processes multiple tickets autonomously:

  • Plans are auto-approved (no user gate per ticket)
  • User testing is skipped (no manual test wait)
  • /commit runs automatically after each implementation
  • Chain state persists in chain-state.json for resume across context windows
  • Cross-project chains supported (e.g., mix of AUTM and PLA tickets)
  • Failure on one ticket doesn't halt the chain — moves to next

Steps (15 total)

Step Phase What Happens
0 Resume check If session exists, resume from last checkpoint
1 Project detection Identify project type from working directory
2 Pre-flight Validate git clean, check pattern journal health
3 Ticket validation Verify ticket ID format matches expected pattern
4 Fetch ticket Get from Linear: title, description, status, priority
5 Fetch context Get all comments (oldest first)
6 Reopened detection Check for previous work, extract feedback to address
7 Team-repo validation Auto-switch repos if ticket belongs elsewhere
7.1 Load profile Read Workflow Profile from project CLAUDE.md
7.5 Session rules Parse constraints from message ("no new files", "integration only")
8 Create plan Plan subagent explores codebase, creates implementation plan
9 User approval Present plan, wait for confirmation (skipped in chain mode)
10 Create branch feature/TICKET-XXX-description (or stay on main for direct-to-main repos)
11 Update Linear Status -> "In Progress", post plan as comment (threaded)
12 Confirm ready Show branch, plan location, next steps
13 Implement Execute plan tasks with TaskCreate/TaskUpdate tracking
14 Run quality gates Profile-driven: type-check, lint, tests
15 Handoff Set status: "awaiting_user_test", show test instructions

Cross-Repository Auto-Switch

/start detects the ticket's team prefix and auto-switches to the correct repository:

Prefix Target Repository
AUTM, MED, MYH, NEW, PLA, INT Magic Platform (current worktree)
TARS MagicEA (~/Code/magicea)
FRE Freshell (~/Code/freshell)
COS CompanyOS (~/Code/companyos)
CEO CEOS (~/Code/ceos)
AIC Adventures in Claude (~/Code/adventuresinclaude)

/commit

Reviews code, commits, pushes, and updates Linear. Adapts to each project's Workflow Profile.

Steps

Phase What Happens
0. Load profile Detect project, read Workflow Profile from CLAUDE.md
0.5. Session check Read .claude-session/*.json, verify branch matches
1. Pre-flight Must be on correct branch, must have changes
2. Quality gates Run profile.quality_gates commands sequentially
3. Review triage Auto-detect review level based on changes
4. Review dispatch NONE: skip / LIGHT: code-reviewer / FULL: parallel agents
4.5. Auto-label Detect labels from file paths and branch name
5. Commit Stage, generate message, include ticket reference
6. Push Push with upstream tracking (or direct to main)
7. Update Linear Set status per profile, apply labels, post comment (threaded)
8. Summary Profile-driven output with next steps

/staging

Batch merge feature branches to preview, deploy, and update Linear. Magic Platform only.

Step What Happens
1. Validate Show branches to merge, worktree status
2. Merge Loop through feature branches, merge to preview
3. Format pnpm run format, commit formatting changes
4. Push Push to origin/preview
5. Monitor CI Poll gh run list every 15s (token-efficient)
5b. Auto-fix Common failures: format, lint, type errors
6. Update Linear Extract tickets, parallel update -> "Staging"
7. Cleanup Delete remote branches, reset worktrees

/production

Deploy staging to production after approval gates. Magic Platform only.

Step What Happens
1. Pre-flight Must be on preview branch in main worktree
1.5. Marker check Block if any tickets not "Approved"
2. Health audit Run environment-health-auditor agent
3-4. Verify + confirm pnpm run verify:preview, interactive checklist
5. Create PR preview -> main with ticket list
6-7. CI + merge Monitor CI, provide URL for manual merge (safety gate)
8. Verify production pnpm run verify:production (waits 90s for Vercel)
9-11. Finalize Update Linear -> "Done", changelog reminder

Review Triage System

The system automatically selects review depth based on changes, saving tokens on small changes while maintaining rigor on complex ones.

Triage Matrix

Signal Review Level What Runs
< 3 files, app-only, no sensitive paths, no behavior changes NONE Skip reviews entirely
3-9 files, or behavior changes (server actions, hooks, deps) LIGHT Quick code-reviewer (single agent)
10+ files, or 200+ lines FULL Parallel multi-agent review
Touches packages/* or sensitive paths FULL Always (shared code / security)
Epic child ticket FULL+ spec-reviewer + code-reviewer
Docs/tests/config/styling only NONE Exempt regardless of file count

Behavior Change Overrides (At Least LIGHT)

Even a 1-file change triggers at least LIGHT review when it modifies:

  • Server actions (actions.ts)
  • API routes (route.ts, api/)
  • React hooks (hooks/, use*.ts)
  • Production dependencies (package.json)
  • Database queries/services (services/, queries/)

Sensitive Paths (Force FULL)

**/auth/**    **/middleware/**    **/rls/**
**/payment/** **/billing/**      **/stripe/**
**/webhook/** **/cron/**         **/admin/**
supabase/migrations/*

Multi-Agent Review (FULL/FULL+ only)

Up to 5 agents run in parallel based on file types:

Agent Triggers On Focus
code-reviewer Always at FULL Code quality, patterns, bugs
ui-consistency-reviewer .tsx files Design system, accessibility
silent-failure-hunter API routes, services Error handling, unhandled promises
security-auditor Auth, migrations RLS, SQL injection, CSRF
test-quality-reviewer Test files Assertions, edge cases, reliability

Workflow Profiles

Each repository defines a Workflow Profile in its CLAUDE.md that drives /start and /commit behavior. This replaces hardcoded per-project logic with declarative configuration.

Profile Fields

Field Description Example Values
workflow.base_branch Base for feature branches preview, main
workflow.direct_to_main Skip feature branches true / false
workflow.investigation Explore agent depth full / light
workflow.plan_approval Require user approval of plans required / auto
workflow.user_testing Manual testing gate required / optional / skip
workflow.quality_gates Commands to run before commit ["pnpm run type-check"]
workflow.review.triage Enable review triage true / false
workflow.review.max_level Cap review depth NONE / LIGHT / FULL
workflow.ship.method How to ship code direct_push / pr
workflow.ship.linear_status Status to set on commit "In Progress" / "Done"
workflow.ship.deploy_hint What to do after commit "/staging", "git push"

Profile Comparison

Profile Field Magic Platform MagicEA Freshell CompanyOS CEOS WP
base_branch preview main main main main main
direct_to_main false false false true true true
quality_gates type-check, lint type-check npm test (none) (none) (none)
review.max_level FULL LIGHT LIGHT NONE NONE NONE
ship.method pr (deferred) pr pr direct_push direct_push direct_push
ship.linear_status In Progress In Progress In Progress Done Done Done
ship.deploy_hint /staging /deploy-ea Maintainer merge Auto-push git push deploy.sh

Rules System

Rules in ~/.claude/rules/*.md are automatically loaded into every Claude session. Each rule file is focused and actionable.

Rule Inventory (17 rules)

Core Discipline

Rule File Key Points
evidence-first.md Never assert about code without reading it first. Tools first, conclusions second
scope-intent.md Match response scope to request. Review mode = report only. Don't over-engineer process
output-formatting.md Include required formatting on first attempt. Always output full URLs and file paths
protected-workflows.md Never bypass skill commands (/commit, /staging, etc.) with manual git
parallel-patterns.md When to parallelize with Task agents. Subagents need full inline context
skill-authoring.md Description = WHEN to invoke, not WHAT it does. Command delegation rule

Code Quality

Rule File Key Points
code-quality.md TypeScript strict, avoid any, ?.trim() || "fallback" for DB text, pre-existing monorepo errors
testing-vitest.md Mock at factory level, Vitest 4 signatures, waitFor assertions only, vi.mock() path matching
bash-patterns.md Reserved variables (status, path), multi-line in loops, grep exit codes with set -e

Infrastructure

Rule File Key Points
commit-recipe.md Shared commit structure for all projects, quality gates, pre-commit hook discipline
review-triage.md NONE/LIGHT/FULL triage logic, behavior change overrides, agent selection
mcp-server-config.md Prefer PAT/API key auth over OAuth, user-scope config in ~/.claude-personal/.claude.json
mcp-linear.md Labels replace (not append), id vs issueId, state not status
learning-capture.md Auto-capture insight blocks, suggested discovery capture, gotcha graduation

CompanyOS (symlinked from shared repo)

Rule File Key Points
co-company-context.md Company info, people, products, communication conventions
co-skill-patterns.md Quality checklist and template for CompanyOS skills
co-protected-workflows.md Never send emails without draft-review-approve loop

Project-Level Rules (Magic Platform)

These live in project/.claude/rules/ and are loaded only in that project:

Rule File Key Points
ui-patterns.md Semantic color tokens (never hardcoded), @platform/ui first, app visual identity
ci-pipeline.md CI polling (never gh run watch), production merge sync pattern
database-migrations.md Git is source of truth, CLI-first, idempotent SQL, RLS DROP+CREATE
production-safety.md ALTER ROLE SET replaces (not appends). Read pg_roles.rolconfig before modifying
env-local-protection.md Vercel CLI overwrites .env.local. Use .env.development.local for local Supabase
nextjs-monorepo.md Stale .next cache causes false type-check failures. Clean validator.ts files
vercel-operations.md Shell escaping in Ignored Build Step. Use heredoc to avoid \!=
jsonb-naming.md Database JSONB = snake_case, TypeScript = camelCase, conversion layer
mcp-resend.md Domain-scoped API keys. Wrong key = silent send failure

Skills Inventory

Skills in ~/.claude/skills/ are auto-invoked based on context. They encode domain expertise and enforce discipline.

Domain Skills (10 file-based)

Skill Trigger Context Purpose
testing Writing/debugging tests Vitest, Playwright, mocking patterns
supabase Database operations Queries, migrations, RLS debugging
vercel Deployment issues Build failures, environment management
linear Ticket management Issue operations, workflow updates
context7 Library docs Up-to-date API documentation lookup
notion Documentation Notion pages, databases
sentry Error monitoring Investigate errors, view trends
oauth Auth integrations Social provider setup
performance Slow pages Bundle optimization, Core Web Vitals, React render optimization
mobile Mobile UI work Responsive patterns, touch targets

Utility Skills (2 file-based)

Skill Trigger Context Purpose
form-patterns Form development Dirty state, validation, unsaved changes
ceos-lma EOS assessment Leadership and management accountability framework

CompanyOS Skills (9, symlinked from shared repo)

Skill Trigger Context Purpose
co-ops Company operations Decisions, contacts, conventions
co-comms Business communications Draft-review-approve loop, tone guidelines, voice profile
co-content Marketing content Blog posts, announcements, social copy
co-feedback User feedback Triage, analyze patterns, respond
co-calendar Scheduling Meeting prep, time awareness
co-secrets API keys, credentials GCP Secret Manager operations
co-search Cross-tool search Find info across Linear, Gmail, Notion, Help Scout, Sentry, Drive
co-launch Product launches Launch planning and coordination
co-support Customer support Help Scout integration, support workflow

Voice Profile (co-comms)

The co-comms skill uses a voice profile at ~/.claude-personal/voice/voice-profile.md to match Brad's writing style:

  • Hyphens with spaces for asides ( - ), never em dashes
  • Short sentences, 1-3 sentence paragraphs
  • No hedging, no corporate language, no AI slop words
  • No greeting line, no sign-off
  • Per-recipient calibration via Gmail history (when MCP available)

Superpowers Plugin

The superpowers plugin (superpowers@superpowers-marketplace) provides a core development methodology that auto-updates via the plugin marketplace. It adds skills for debugging, verification, brainstorming, plan writing/execution, code review, TDD, and subagent-driven development.

Plugin Skills

Skill When Invoked Purpose
systematic-debugging Bug reports, errors, test failures 4-phase root cause analysis before any fix
verification-before-completion Before claiming work is done Require fresh evidence (tests, builds)
writing-plans Complex multi-step implementation Create plans with 2-5 minute atomic tasks
executing-plans Have a plan to execute Task-by-task with review checkpoints
brainstorming Before any creative/feature work Explore intent, requirements, design before code
test-driven-development Before writing implementation Write failing tests first, then implement
requesting-code-review After completing features Structured code review request
receiving-code-review After getting review feedback Technical rigor, not performative agreement
dispatching-parallel-agents 2+ independent tasks Parallel subagent orchestration
subagent-driven-development Plans with independent tasks Execute plan tasks via parallel agents
using-git-worktrees Need isolation for feature work Smart worktree creation and management
finishing-a-development-branch Implementation complete Merge, PR, or cleanup decision guide
writing-skills Creating/editing skills Skill authoring with verification
using-superpowers Start of conversation Establishes skill discovery patterns

Why a Plugin?

Plugin skills auto-update independently of the repository. When superpowers publishes a new debugging technique or verification pattern, all sessions get it automatically without commits or manual updates.


Commands Inventory

Commands are explicit slash commands invoked by the user. /start and /commit are user-level (work across all 7 repositories).

User-Level Commands (~/.claude/commands/, 25 commands)

Available in all projects:

Core Workflow (work across all repos)

Command Purpose
/start Begin work on a Linear ticket (with chain and epic modes)
/commit Review, commit, push, update Linear (profile-driven)
/deploy-ea Deploy MagicEA to DigitalOcean
/freshell Freshell-specific operations

Session Management

Command Purpose
/checkpoint Save full session state before context compaction
/rules Add session rules that persist across compaction
/verify-branch Verify correct git branch for current work
/git-clean Clean up git state

Knowledge Capture

Command Purpose
/note Capture a learning or interesting technique
/learn Graduate a pattern to permanent rules/skills
/til Extract an atomic learning for GitHub TIL repo
/blogaic-draft Generate blog post draft from captured daily notes
/blogaic-post Publish a blog post to Adventures in Claude
/blog-feld Blog operations for feld.com

Diagnostics

Command Purpose
/screenshot View and analyze most recent Desktop screenshot
/view Visually inspect a file (image, PDF, HTML)
/diagnose Investigate system resource issues (memory, CPU)
/global-status Universal project health check
/validate Type-check + lint + build verification
/secrets-scan Security scan for secrets in code
/linear-image View images attached to Linear tickets

Utility

Command Purpose
/test Generate tests or run test coverage campaign
/localhost Open local dev server
/done-color Change terminal background when Claude finishes
/pr Create a pull request
/start-epic Legacy epic starter (now integrated into /start epic)

Project-Level Commands (magic-platform, 18 commands)

Specific to the Magic Platform monorepo (project/.claude/commands/):

Command Purpose
/staging Batch merge to preview, deploy
/production Deploy to production with safety gates
/validate Type-check + lint + build (project-scoped)
/verify Verify deployment health
/review Code review current changes
/review-codebase Broader codebase review
/health Infrastructure health check
/sweep Cross-codebase cleanup operations
/cleanup Clean up after staging/production
/whats-next Suggest next ticket to work on
/ui UI component operations
/backup Backup secrets to Google Drive
/blog-new Create new blog post
/blog-edit Edit existing blog post
/blog-publish Prepare blog post for publication
/blog-idea Brainstorm blog post ideas
/migration-baseline Database migration baseline
/start-epic Epic workflow (project-level version)

CompanyOS Commands (~/Code/companyos/.claude/commands/)

Command Purpose
/co-create-skill Generate a new CompanyOS skill from description

MCP Server Integration

Architecture

Each MCP server is configured individually with direct connections. Tool Search (ENABLE_TOOL_SEARCH=true) enables lazy loading — tools are discovered on-demand rather than loaded upfront, saving ~5k tokens per server in context.

Auth Strategy: Prefer PAT/API Key Over OAuth

OAuth tokens stored in macOS Keychain use version-specific keys. When Claude Code updates, previous tokens are orphaned. PAT/API key auth survives updates — only Vercel still requires OAuth.

Configured Servers (12)

Server Transport Auth Method Survives Updates? Purpose
linear HTTP Bearer PAT (lin_api_) Yes Issue tracking, ticket management
supabase HTTP Bearer PAT (sbp_) Yes Database queries, project management
stripe HTTP Bearer restricted key (rk_) Yes Billing, subscriptions
context7 HTTP API key header Yes Up-to-date library documentation
betterstack HTTP Bearer API key Yes Uptime monitoring, incidents
vercel HTTP OAuth (Keychain) No Deployment management
sentry Stdio Env var (SENTRY_ACCESS_TOKEN) Yes Error monitoring
notion Stdio Env var (NOTION_TOKEN) Yes Documentation, databases
firecrawl Stdio Env var (FIRECRAWL_API_KEY) Yes JS-rendered web scraping
helpscout Stdio Env vars (app ID + secret) Yes Customer support inbox
google-workspace Stdio Google OAuth client creds Yes Gmail, Calendar, Drive, Docs, Sheets
claude-in-chrome Built-in Extension Yes Browser automation (read pages, fill forms, navigate)

How Tool Search Works

Instead of loading all tool schemas from all servers upfront (thousands of tokens), tools are deferred:

// 1. Search for tools by keyword
ToolSearch({ query: "linear issues" })
// Returns: mcp__linear__list_issues, mcp__linear__get_issue, ...

// 2. Call the tool directly (now loaded)
mcp__linear__get_issue({ id: "PROJ-123" })

Server Configuration

CRITICAL: User-scope MCP config lives in ~/.claude-personal/.claude.json, NOT ~/.claude.json. Never manually edit JSON. Always use CLI:

# HTTP servers with Bearer token (preferred — survives updates)
claude mcp add --transport http --scope user linear https://mcp.linear.app/mcp \
  --header "Authorization: Bearer lin_api_XXXX"
claude mcp add --transport http --scope user supabase https://mcp.supabase.com/mcp \
  --header "Authorization: Bearer sbp_XXXX"

# HTTP servers with API key header
claude mcp add --transport http --scope user context7 https://mcp.context7.com/mcp \
  --header "CONTEXT7_API_KEY: $KEY"

# Stdio servers with environment variables
claude mcp add --transport stdio --scope user -e SENTRY_ACCESS_TOKEN=sntryu_XXXX sentry \
  -- npx -y @sentry/mcp-server@latest

# Verify
claude mcp list

Services NOT Using MCP

Service Approach Why
GitHub CLI (gh ...) Full feature access, auth configured
Supabase mutations CLI + migrations Git-based audit trail
Vercel CLI Direct (npx vercel ...) More reliable for env operations

Repository Registry

Seven repositories, all accessible via /start TICKET-XXX with auto-switching:

Repository Location Linear Prefix Base Branch Ship Method Deploy
Magic Platform ~/Code/magic0-7 AUTM, MED, MYH, NEW, PLA, INT preview PR (via /staging) /staging + /production
MagicEA ~/Code/magicea TARS main PR /deploy-ea
Freshell ~/Code/freshell FRE main PR (upstream) Maintainer merge
CompanyOS ~/Code/companyos COS main Direct push Auto-push hook
CEOS ~/Code/ceos CEO main Direct push git push
Adventures in Claude ~/Code/adventuresinclaude AIC main Direct push Vercel auto-deploy
WordPress Sites ~/Code/wp WP main Direct push deploy.sh

Two Deployment Models

Model Repos Commit Status Why
Pipeline (3-tier) Magic Platform In Progress /staging -> /production advance status
Feature branch + PR MagicEA, Freshell In Progress PR/deploy advances status
Direct-to-main CompanyOS, CEOS, AIC, WP Done Commit IS the deploy

CompanyOS: Shared Configuration

CompanyOS is a shared git repository for two-person company configuration — skills, rules, decisions, and operational knowledge.

Architecture

~/Code/companyos/
├── skills/co-*/           # 9 shared skills (symlinked into ~/.claude/skills/)
├── rules/co-*.md          # Shared rules (symlinked into ~/.claude/rules/)
├── .claude/commands/      # CompanyOS-specific commands
├── co-skill-rules.json    # Trigger definitions for co-* skills
├── mcp-registry.json      # MCP servers to auto-configure
├── scripts/
│   ├── git-hooks/         # Version-controlled hooks
│   │   ├── pre-commit     # Auto-pull --autostash before commit
│   │   ├── post-commit    # Auto-push after commit
│   │   └── post-merge     # Auto-run setup.sh after pull
│   ├── auto-update.sh     # Launchd-driven sync (--autostash, failure alerting)
│   ├── co-sync            # Manual sync command
│   └── com.intensitymagic.companyos-update.plist
└── setup.sh               # Idempotent installer

Auto-Sync Pipeline

Changes propagate automatically between users:

User A commits in CompanyOS
    | pre-commit hook: git pull --ff-only --autostash (handles dirty working tree)
    v
Commit happens
    | post-commit hook: git push origin main
    v
User B's launchd (every 30 min)
    | auto-update.sh: git pull --ff-only --autostash
    | On failure: increment counter, alert every 3rd consecutive failure (macOS notification)
    v
    | post-merge hook: setup.sh runs
    v
User B has new skills/rules symlinked

Failure Alerting (COS-38)

The auto-sync script tracks consecutive failures and alerts when stale:

  • File-based counter at ~/.companyos-update-failures
  • Resets to 0 on successful pull
  • macOS notification every 3rd consecutive failure
  • Prevents silent staleness (previously went 6 days unnoticed)

setup.sh (Idempotent Installer)

Run once to configure everything, safe to re-run anytime:

  1. Symlinks skills/co-*/ into ~/.claude/skills/
  2. Symlinks rules/co-*.md into ~/.claude/rules/
  3. Merges co-skill-rules.json into ~/.claude/skills/skill-rules.json
  4. Configures MCP servers from mcp-registry.json (check-before-add)
  5. Sets up Google Workspace MCP (if not configured)
  6. Configures git core.hooksPath to use version-controlled hooks

Blog and Learning Capture

A subsystem for capturing insights during development and turning them into blog content.

Automatic Capture (Insight Blocks)

Every Insight block generated during work is automatically appended to daily notes:

File: ~/.claude/blog/notes/YYYY-MM-DD.md

## [HH:MM] category - Worktree: magicN

**Context:** Branch name or what you were working on
**Note:** The insight content as a cohesive paragraph
**Related:** Files, tickets, or concepts

Categories: gotcha, deep-dive, magic-trick, day-in-life, insight

Gotcha Graduation

Entries categorized as gotcha are automatically added to ~/.claude/PATTERNS.md — a permanent journal of surprising behaviors and edge cases.

Proactive Noting

During development, Claude suggests capturing discoveries for blog content when it encounters high-value triggers (surprising behavior, clever solutions, long debugging sessions, architectural decisions). Max 3 suggestions per hour, respects user flow.

Manual Capture Commands

Command Purpose
/note Manually capture a learning
/learn Graduate a pattern to permanent rules/skills
/til Extract atomic learning for GitHub TIL repo
/blogaic-draft Aggregate daily notes into blog post draft
/blogaic-post Publish post to Adventures in Claude blog

Flow

Daily work -> Insight blocks (auto-captured) -> /blogaic-draft (aggregation) -> Blog post
                                              -> Gotchas graduate to PATTERNS.md
                                              -> /learn graduates to rules/skills

Git Workflow Rules

Branch Protection

Never commit directly to main (production) or preview (staging). Pre-commit hooks block this automatically.

Exception: Direct-to-main repos (CompanyOS, CEOS, Adventures in Claude, WP) commit directly to main per their Workflow Profile.

Branch Naming

  • feature/TICKET-XXX-description — New features
  • fix/description — Bug fixes
  • refactor/description — Code restructuring

Commit Message Format

<type>: <description>

[Optional body explaining WHY]

Refs TICKET-XXX

Types: feat:, fix:, refactor:, docs:, chore:, test:

Note: Co-author attribution is added automatically by settings.json attribution.commit. Do not add it manually.

Pre-commit Hook Discipline

NEVER bypass with --no-verify except for two documented exceptions:

  1. Merge commits in /staging or merge fix commits on preview during /production
  2. Pre-existing type errors in unrelated packages — errors in apps you didn't modify and don't depend on. Document skipped errors in the commit message.

CI Monitoring (Token-Efficient)

Never use gh run watch — outputs 13K+ lines and overflows context.

Self-contained polling:

SHA=$(git rev-parse HEAD)
for i in {1..60}; do
  result=$(gh run list --workflow "CI/CD Pipeline" -L5 \
    --json databaseId,headSha,status,conclusion \
    -q ".[] | select(.headSha==\"$SHA\") | \"\(.databaseId),\(.status),\(.conclusion)\"" | head -1)

  [[ -z "$result" ]] && { sleep 10; continue; }

  IFS=',' read -r run_id run_status conclusion <<< "$result"
  echo "Run $run_id: $run_status ${conclusion:+($conclusion)}"

  [[ "$run_status" == "completed" ]] && break
  sleep 15
done

Production Release: Merge Sync Pattern

After every production squash merge (preview -> main), sync preview with main's ancestry:

git checkout preview
git fetch origin main
git merge -s ours origin/main -m "chore: sync preview with main after production release"
git push origin preview

Key distinction:

Command What it does When to use
git merge -s ours Keeps our tree exactly, records ancestry Post-production sync
git merge -X ours Resolves conflicts favoring ours NEVER for post-production sync

Multi-Instance Safety (Worktrees)

For running multiple Claude Code sessions simultaneously:

Rules

  1. Each session = different worktree
  2. Each worktree = different branch (never same branch in two places)
  3. Commit before switching between sessions
  4. Never modify main/preview in any worktree

Port Allocation (8 Worktrees)

Formula: PORT = 3000 + (worktree * 10) + app_slot

App Slot magic0 magic1 magic2 ... magic7
AuthorMagic 0 3000 3010 3020 ... 3070
MedicareMagic 1 3001 3011 3021 ... 3071
IntensityMagic 2 3002 3012 3022 ... 3072
MyHealthMagic 3 3003 3013 3023 ... 3073
Book Sites 4 3004 3014 3024 ... 3074
NewsletterMagic 5 3005 3015 3025 ... 3075

Environment File Symlinks

All worktrees (magic1-7) symlink env files to magic0:

magic1/apps/*/web/.env.local -> magic0/apps/*/web/.env.local
magic1/apps/*/web/.env.development.local -> magic0/apps/*/web/.env.development.local

Worktree Config Protection

A sync script (scripts/sync-claude-config.sh) manages Claude config symlinks across worktrees with safety guards:

  • Blocks magic0 as sync target (it's the source)
  • Automated daily backups via launchd -> ~/.claude-backups/
  • Manifest validation (--check) catches partial recovery

Coding Standards

TypeScript Strict Mode

// Explicit types for function signatures
function processUser(user: User): ProcessedUser { ... }

// Type guards for unknown
function isUser(value: unknown): value is User {
  return typeof value === 'object' && value !== null && 'id' in value;
}

// Handle null/undefined explicitly
const name = user?.profile?.name ?? 'Unknown';

Database Text Handling

?? only handles null/undefined, not empty strings:

const title = dbRecord.title ?? "Untitled";    // "" stays ""
const title = dbRecord.title?.trim() || "Untitled";  // handles all three

Security Requirements

// Parameterized queries ONLY
await db.query('SELECT * FROM users WHERE id = $1', [userId]);

// Input validation at boundaries with Zod
const userInput = z.object({
  email: z.string().email(),
  name: z.string().min(1).max(100),
}).parse(req.body);

Error Handling

try {
  await riskyOperation();
} catch (error) {
  logger.error('Operation failed', {
    operation: 'riskyOperation',
    userId: user.id,
    error: error instanceof Error ? error.message : String(error),
  });
  throw new UserFacingError('Unable to complete operation');
}

Semantic Color Tokens

Never hardcode Tailwind colors. Always use semantic tokens:

// BAD: Hardcoded
<div className="bg-white text-gray-900 border-gray-200">

// GOOD: Semantic
<div className="bg-card text-foreground border-border">

Visual differences between apps come from CSS variable values in each app's globals.css, not different class names.


Database Migration Discipline

The Golden Rule

Git is the source of truth for migrations. Every migration must:

  1. Be a file in supabase/migrations/
  2. Be committed to git BEFORE any remote database has it
  3. Be applied to environments via CI/CD (not MCP or manual SQL)

CLI-First Workflow (MANDATORY)

supabase migration new add_user_preferences  # Create file
# Edit the SQL
supabase db reset                            # Test locally
git add supabase/migrations/ && git commit   # Commit

Idempotent SQL Patterns

-- Tables and indexes: IF NOT EXISTS
CREATE TABLE IF NOT EXISTS my_table (...);

-- RLS Policies: DROP + CREATE (no IF NOT EXISTS support)
DROP POLICY IF EXISTS "policy_name" ON my_table;
CREATE POLICY "policy_name" ON my_table FOR SELECT USING (...);

Production Safety: ALTER ROLE SET (CRITICAL)

ALTER ROLE SET REPLACES the entire parameter value, it does NOT append. This caused a production outage when pgrst.db_schemas was overwritten.

-- SAFE: Read first, then modify
DO $$
DECLARE current_schemas TEXT;
BEGIN
  SELECT option_value INTO current_schemas
  FROM pg_options_to_table(
    (SELECT rolconfig FROM pg_roles WHERE rolname = 'authenticator')
  ) WHERE option_name = 'pgrst.db_schemas';

  IF current_schemas NOT LIKE '%newschema%' THEN
    EXECUTE format('ALTER ROLE authenticator SET pgrst.db_schemas TO %L',
      current_schemas || ', newschema');
  END IF;
END $$;
NOTIFY pgrst, 'reload config';

Secrets Management

Architecture

Secrets are stored in GCP Secret Manager (project: authormagic-480416). No persistent plaintext vault on disk — sync scripts auto-regenerate from GCP SM on demand.

Sync Scripts

Script Purpose
scripts/secrets-regenerate-vault.sh Download all secrets from GCP SM
scripts/secrets-sync-env.sh [app] [env] Generate .env.local for an app
scripts/secrets-sync-vercel.sh [app] [env] Push env vars to Vercel
scripts/secrets-validate.sh Validate vault completeness

Domain-Scoped Email Keys

Each sending domain has its own Resend API key. Using the wrong key causes silent send failure:

From Domain Vault Path
authormagic.com authormagic.resend.api_key
intensitymagic.com intensitymagic.resend.api_key
mynewslettermagic.com newslettermagic.resend.api_key

Adding New Secrets

# 1. Add to GCP Secret Manager
printf '%s' 'value' | gcloud secrets create name --project=authormagic-480416 --data-file=-

# 2. Regenerate local .env.local
./scripts/secrets-sync-env.sh app/web local

# 3. Push to Vercel (no vercel link needed!)
vercel env add VAR_NAME preview --force
vercel env add VAR_NAME production --force

CRITICAL: Never run vercel link just to add env vars. Projects are already linked via .vercel/. vercel link overwrites .env.local.


Testing Patterns

Vitest 4 Test Signature (CRITICAL)

Options come BEFORE the test function:

// Vitest 4
it("slow test", { timeout: 15000 }, () => { ... });

Mock at the Right Abstraction Level

// BAD: Low-level SDK mock — factory initialization still runs
vi.mock("@supabase/supabase-js", () => ({ createClient: vi.fn() }));

// GOOD: Mock the factory your code actually calls
vi.mock("@/lib/supabase/factory", () => ({
  SupabaseClients: { admin: () => mockClient },
}));

waitFor Anti-Pattern (CRITICAL)

Never put async operations inside waitFor callbacks. They fire on EVERY retry:

// GOOD: actions outside, assertions inside
await user.click(button);
await waitFor(() => {
  expect(button).toBeDisabled();
});

Additional Vitest Gotchas

  • vi.mock() path must match import path — mismatched paths are silently ignored
  • vi.clearAllMocks() doesn't drain once-value queues — use mockReset() to prevent cross-test leaks
  • NODE_ENV is "test" in Vitest — not "development"
  • Vitest doesn't resolve package.json exports — add vitest.config aliases for @platform/ui/*
  • Class constructor mocks — arrow functions lack [[Construct]], use class MockClass { ... } pattern

Critical Gotchas

Stale .next Cache (Next.js Monorepos)

Symptom: Type-check fails on apps you didn't modify:

.next/types/validator.ts: Cannot find module '../../src/app/page.js'

Fix:

find apps -name "validator.ts" -path "*/.next/*" -delete

APFS Directory Hardlinks and rm -rf

NEVER use rm -rf on an APFS hardlinked directory. Both directory entries share child inodes — rm -rf destroys data at BOTH paths.

Vercel CLI Overwrites .env.local

Both vercel link and vercel env pull completely overwrite .env.local. Protection: Store local-only vars in .env.development.local.

cn() Silent Failures

Tailwind's cn() silently drops invalid class names (hex codes, rgb values).

Nested Supabase Joins Fail Silently with RLS

Use step-by-step queries instead of nested .select() with !inner.

ALTER ROLE SET Replaces (Not Appends)

See Database Migration Discipline — caused a production outage.

Reserved Bash Variables

Avoid Use Instead Why
status run_status zsh read-only
pipestatus pipe_result zsh reserved
path file_path PATH conflict on macOS

OAuth Tokens Lost on Claude Code Updates

Only affects Vercel (the last OAuth server). All other MCP servers now use PAT/API key auth that survives updates.


Quick Start for New Setup

1. Create Structure

mkdir -p ~/.claude/{rules,skills,commands,blog/notes}
mkdir -p ~/.claude-personal/voice
touch ~/.claude/CLAUDE.md
mkdir -p project/.claude/{commands,session}

2. Add MCP Servers (PAT/API key preferred)

# HTTP servers with Bearer token
claude mcp add --transport http --scope user linear https://mcp.linear.app/mcp \
  --header "Authorization: Bearer lin_api_XXXX"
claude mcp add --transport http --scope user supabase https://mcp.supabase.com/mcp \
  --header "Authorization: Bearer sbp_XXXX"
claude mcp add --transport http --scope user stripe https://mcp.stripe.com/ \
  --header "Authorization: Bearer rk_test_XXXX"

# HTTP servers with API key header
claude mcp add --transport http --scope user context7 https://mcp.context7.com/mcp \
  --header "CONTEXT7_API_KEY: $KEY"
claude mcp add --transport http --scope user betterstack https://mcp.betterstack.com \
  --header "Authorization: Bearer $KEY"

# Stdio servers with environment variables
claude mcp add --transport stdio --scope user -e SENTRY_ACCESS_TOKEN=sntryu_XXXX sentry \
  -- npx -y @sentry/mcp-server@latest
claude mcp add --transport stdio --scope user -e NOTION_TOKEN=ntn_XXXX notion \
  -- npx -y @notionhq/notion-mcp-server

# OAuth (only if no PAT option exists)
claude mcp add --transport http --scope user vercel https://mcp.vercel.com

# Verify
claude mcp list

3. Enable Tool Search

Add to ~/.claude/settings.json env section:

{ "env": { "ENABLE_TOOL_SEARCH": "true" } }

4. Install Superpowers Plugin

// In ~/.claude/settings.json
{ "plugins": ["superpowers@superpowers-marketplace"] }

5. Create Core Rules

Essential files for ~/.claude/rules/:

  • evidence-first.md — Read before asserting
  • code-quality.md — TypeScript strict, error handling
  • commit-recipe.md — Shared commit structure
  • review-triage.md — Auto-detect review depth
  • scope-intent.md — Match response to request
  • protected-workflows.md — Don't bypass skill commands

6. Write Global CLAUDE.md

# Global Claude Code Configuration

## Developer Context
Solo developer, one machine, multiple concurrent workspaces via worktrees.

## Workflow Discipline
Every ticket gets the full workflow:
1. /start TICKET-XXX
2. Implement
3. /commit

No exceptions. No "quick fixes."

## Session State
Check .claude-session/ for current ticket state.
Respect blockedActions when status is "awaiting_user_test".

## Key Rules
See ~/.claude/rules/ for standards.
Evidence-first: read before asserting.
Root cause: trace before fixing.

7. Verify

claude mcp list           # All servers connected
ls ~/.claude/rules/       # Rules loaded
ls ~/.claude/skills/      # Skills available

Key Insights

  1. Session state solves context amnesia — The .claude-session/ directory creates "process memory" that survives context compaction.

  2. Review triage saves tokens without sacrificing quality — Automatic NONE/LIGHT/FULL selection handles most commits without agent overhead while maintaining rigor on complex changes.

  3. Tool Search transforms MCP economics — Lazy loading tools on-demand saves ~5k tokens per server, making 12 MCP servers practical without overwhelming context.

  4. PAT/API key auth over OAuth — Migrating from OAuth to PAT/API key for MCP servers eliminates the reauth-on-update problem. Only Vercel still requires OAuth.

  5. Evidence-first prevents confident wrong answers — Requiring source reading before assertions catches the "sounds right but isn't" failure mode.

  6. Workflow Profiles make commands project-agnostic/start and /commit work across 7 repositories by reading declarative config instead of hardcoded logic.

  7. Chain mode enables batch ticket processing/start chain and /start epic process multiple tickets autonomously with auto-approval and auto-commit.

  8. Global-first reduces cognitive load — One place for standards means less drift and easier maintenance across 7 repositories.

  9. Worktrees enable true parallelism — Multiple Claude sessions can work simultaneously without conflicts.

  10. The description trap wastes skill potential — If a skill description summarizes workflow, Claude may skip the detailed body.

  11. CompanyOS makes config collaborative — Git hooks + launchd auto-sync means shared skills/rules propagate without manual steps. Failure alerting prevents silent staleness.

  12. Superpowers plugin auto-updates methodology — Core development patterns (debugging, verification, TDD) improve automatically without manual updates.

  13. Voice profile calibration — Per-recipient tone matching via Gmail history produces natural-sounding communications, not generic AI output.

  14. ALTER ROLE SET is a replace operation — This production outage taught the universal rule: always read current state before modifying shared configuration.

  15. Self-describing data prevents drift — When the data itself describes how it should be processed, adding new items never requires script changes.


Configuration patterns from a two-person company setup optimized for workflow discipline, session persistence, knowledge capture, and automated quality gates with Claude Code. Last updated: 2026-02-16.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment