| name | setup |
| description | Use when bootstrapping Claude Code on a new machine or re-running setup after installing new software. Installs MCPs, deploys skills/hooks, constructs settings.json. Re-runnable: detects current state, only installs what's missing. Triggers on: 'setup', 'bootstrap', 'install MCPs', 'configure Claude Code', 'add hopper', or 're-run setup'. |
Claude Code Environment Setup
Interactive, re-runnable setup wizard. Installs MCPs, deploys skills and hooks, constructs global configuration. Targets macOS (ARM + Intel), Linux, and Windows (WSL).
Principles
- Source vs product — source lives in git submodules under the claude repo (
~/Dropbox/Projects/claude/). Product (binaries, venvs, node_modules, configs) is built locally, never committed, never shared across platforms.
- Re-runnable — every run detects current state first. Only acts on what's missing or outdated. Safe to run again after installing new software.
- Statement-MCP first — installed before everything else so it can log the rest of the setup.
- settings.json is constructed — each entry is justified by what's actually installed. Never copy a template.
Key Concepts
Two config files, two purposes:
~/.claude.json — MCP server declarations (what servers to start, their commands and env vars). Claude Code reads this to know which MCP servers to launch.
~/.claude/settings.json — everything else: permissions (allow/deny tool lists), hooks (scripts triggered by events), env flags, model preference. Claude Code reads this to configure its own behavior.
Allow list format: Bare tool names for exact match (e.g., Write, Edit, Agent). Prefix match for MCP tools (e.g., mcp__context-lens matches all tools from that MCP). Deny list uses glob syntax with (*) suffix (e.g., Read(*), Bash(*)).
Build state tracking: ~/.claude/setup-state.json records the git commit hash each component was built from. On re-run, the skill compares current submodule HEAD to the recorded commit. If they differ, the component is marked outdated and offered for rebuild. This avoids unnecessary rebuilds while catching when source has been updated.
State file format:
{
"built_at": "2026-03-17T12:00:00Z",
"platform": "macos-arm",
"components": {
"statement-mcp": {
"source": "strongai/infrastructure",
"commit": "abc1234",
"built_at": "2026-03-17T12:01:00Z",
"product": "~/.claude/mcp-servers/statement-go/statement-mcp"
},
"context-lens": {
"source": "mcp/context",
"commit": "def5678",
"built_at": "2026-03-17T12:02:00Z",
"product": "~/.claude/mcp-servers/context/dist/index.js"
},
"serena": {
Before You Begin
Read the design doc for full rationale: docs/plans/2026-03-17-setup-skill-design.md
Phase 0: Platform Detection & State Inventory
Step 0.1: Detect Platform
Run:
PLATFORM_OS=$(uname -s)
PLATFORM_ARCH=$(uname -m)
Classify into one of:
macos-arm (Darwin + arm64)
macos-intel (Darwin + x86_64)
linux (Linux, including WSL)
windows-wsl (Linux + /mnt/c/ exists)
Store this classification — every subsequent step references it.
Step 0.2: Locate the Claude Repo
The source repo is expected at ~/Dropbox/Projects/claude/. If it doesn't exist, ask the user where it is. All source submodule paths are relative to this root.
Verify it's the right repo:
git -C <repo> remote get-url origin
Step 0.2b: Initialize Submodules
On a fresh clone, submodules are empty directories. Initialize them:
cd <repo>
git submodule update --init --recursive
Verify key submodules are populated:
ls <repo>/strongai/infrastructure/cmd/statement-mcp/
ls <repo>/mcp/context/package.json
ls <repo>/serena/pyproject.toml
ls <repo>/hopper-mcp/pyproject.toml
ls <repo>/scripts/
ls <repo>/skills/
If any are empty, check .gitmodules and ensure the remote URLs are accessible.
Step 0.3: Load Build State
Read ~/.claude/setup-state.json if it exists. This records the git commit each component was last built from.
For each component that has a source submodule, compare the recorded commit to current submodule HEAD:
git -C <repo>/<submodule-path> rev-parse HEAD
If the recorded commit differs from current HEAD, the component is outdated — source has changed since last build.
Step 0.4: Inventory Current State
Check each component and report a status table. For buildable components, include the commit comparison:
| Component | Check command | Status values |
|---|
| Node.js | node --version | installed / missing |
| Go | go version | installed / missing |
| Python 3.11 | python3.11 --version | installed / missing |
| uv | uv --version | installed / missing |
| PostgreSQL | pg_isready | running / installed-stopped / missing |
| pgvector | psql -d claude_statements -c "SELECT extversion FROM pg_extension WHERE extname='vector'" | installed / missing |
| onnxruntime | Check platform-specific path (see §0.5) | installed / missing |
| Docker | docker info | running / installed-stopped / missing |
| statement-mcp | Binary exists + build state commit matches strongai/infrastructure HEAD | current / outdated (abc→def) / built / missing |
| context-lens | dist/index.js exists + build state commit matches mcp/context HEAD | current / outdated (abc→def) / built / missing |
| git MCP | uvx --help works | ready / missing |
| github MCP | Docker + PAT configured | configured / partial / missing |
| serena | venv + binary + build state commit matches serena HEAD | current / outdated (abc→def) / working / missing |
| hopper | macOS + Hopper app + venv + build state commit matches hopper-mcp HEAD | current / outdated (abc→def) / working / skipped / missing |
| scripts | Symlinks exist + build state commit matches scripts HEAD | current / outdated (abc→def) / deployed / missing |
| settings.json | File exists at ~/.claude/settings.json | exists / missing |
| skills | Populated + build state commit matches skills HEAD |
Present this table to the user. outdated components show the recorded→current commit pair so the user can see what changed. Identify what needs action:
- missing → full setup (install deps, build, configure)
- outdated → rebuild only (deps already present, just rebuild from new source)
- current → skip entirely (no action needed)
In subsequent phases, when processing a component:
- If current: skip it, report "already up to date at [commit]"
- If outdated: rebuild it (same steps as missing, but skip dep checks)
- If missing: full setup
Step 0.5: onnxruntime Library Path
Platform-specific:
- macos-arm:
/opt/homebrew/lib/libonnxruntime.dylib
- macos-intel:
/usr/local/lib/libonnxruntime.dylib
- linux:
/usr/lib/libonnxruntime.so or /usr/local/lib/libonnxruntime.so
Check if the file exists. If not, also try:
brew --prefix onnxruntime 2>/dev/null && ls "$(brew --prefix onnxruntime)/lib/libonnxruntime.dylib"
ldconfig -p 2>/dev/null | grep onnxruntime
Step 0.6: Present Menu for Missing System Dependencies
For EACH missing system dependency, present:
[dependency] is missing. Options:
(a) Install it now [show platform-specific command]
(b) I have it elsewhere — provide path
(c) Skip for now (components requiring it will be skipped)
Platform-specific install commands:
| Dependency | macOS (brew) | Linux (apt) |
|---|
| Node.js | brew install node | Install via nodesource: https://deb.nodesource.com/setup_lts.x |
| Go | brew install go | sudo apt install -y golang-go or download from go.dev |
| Python 3.11 | brew install python@3.11 | sudo apt install -y python3.11 python3.11-venv |
| uv | brew install uv | curl -LsSf https://astral.sh/uv/install.sh piped to sh |
| PostgreSQL | brew install postgresql && brew services start postgresql | sudo apt install -y postgresql postgresql-contrib then start service |
| pgvector | brew install pgvector | Build from source: clone pgvector repo, make && sudo make install |
| onnxruntime | brew install onnxruntime | Download from onnxruntime GitHub releases, copy .so to /usr/local/lib/ |
| Docker | Install Docker Desktop from docker.com | sudo apt install -y docker.io then start service, add user to group |
After each installation, re-verify the dependency before proceeding.
Phase 1: Statement-MCP
Statement-MCP is installed first so it can log the rest of the setup.
Required dependencies: Go, PostgreSQL (running), pgvector, onnxruntime
If any are missing and were skipped in Phase 0, skip this phase entirely with message:
"Statement-MCP requires [missing deps]. Install them and re-run setup to enable."
Step 1.1: Ensure PostgreSQL Database
psql -lqt | cut -d \| -f 1 | grep -qw claude_statements
If it doesn't exist:
createdb claude_statements
Step 1.2: Ensure pgvector Extension
psql -d claude_statements -c "CREATE EXTENSION IF NOT EXISTS vector"
Step 1.3: Run Database Migrations
The migration SQL lives in the statement-mcp source. Check for and run migrations:
psql -d claude_statements -c "SELECT tablename FROM pg_tables WHERE schemaname='public'"
If no tables exist, the binary will create them on first run. Proceed to build.
Step 1.4: Download Embedding Model
Target directory: ~/.strongai/models/arctic-embed-m-v2/
Check if model files exist:
ls ~/.strongai/models/arctic-embed-m-v2/model.onnx
ls ~/.strongai/models/arctic-embed-m-v2/tokenizer.json
If missing, download:
mkdir -p ~/.strongai/models/arctic-embed-m-v2
curl -L -o ~/.strongai/models/arctic-embed-m-v2/model.onnx \
"https://huggingface.co/Snowflake/snowflake-arctic-embed-m-v2.0/resolve/main/onnx/model.onnx"
curl -L -o ~/.strongai/models/arctic-embed-m-v2/tokenizer.json \
"https://huggingface.co/Snowflake/snowflake-arctic-embed-m-v2.0/resolve/main/tokenizer.json"
Verify files are non-empty after download.
Step 1.5: Build Statement-MCP Binary
Source: <repo>/strongai/infrastructure/cmd/statement-mcp/
mkdir -p ~/.claude/mcp-servers/statement-go
cd <repo>/strongai/infrastructure
go mod download
go build -o ~/.claude/mcp-servers/statement-go/statement-mcp ./cmd/statement-mcp/
Verify the binary runs:
~/.claude/mcp-servers/statement-go/statement-mcp --help 2>&1 | head -5
Step 1.6: Write Statement-MCP Config
Determine onnxruntime path based on platform (from Step 0.4).
Add to ~/.claude.json under mcpServers:
"statement-mcp": {
"command": "<HOME>/.claude/mcp-servers/statement-go/statement-mcp",
"args": [],
"env": {
"ONNXRUNTIME_SHARED_LIBRARY_PATH": "<platform-specific onnxruntime path>",
"STRONGAI_DATABASE_URL": "postgresql://localhost:5432/claude_statements",
"STRONGAI_EMBED_MODEL_DIR": "<HOME>/.strongai/models/arctic-embed-m-v2"
},
"type": "stdio"
}
Replace <HOME> with the actual home directory path. All paths must be absolute.
Step 1.7: Record Build State
After successful build, record the commit hash:
git -C <repo>/strongai/infrastructure rev-parse HEAD
Update ~/.claude/setup-state.json → components.statement-mcp:
source: "strongai/infrastructure"
commit: the hash from above
built_at: current ISO timestamp
product: "~/.claude/mcp-servers/statement-go/statement-mcp"
If the file doesn't exist yet, create it with the top-level built_at and platform fields.
Step 1.8: Verify Statement-MCP Works
Start the binary with the environment variables and confirm it connects to PostgreSQL:
ONNXRUNTIME_SHARED_LIBRARY_PATH="<path>" \
STRONGAI_DATABASE_URL="postgresql://localhost:5432/claude_statements" \
STRONGAI_EMBED_MODEL_DIR="$HOME/.strongai/models/arctic-embed-m-v2" \
timeout 5 ~/.claude/mcp-servers/statement-go/statement-mcp 2>&1 | head -20
Look for successful startup messages (no "connection refused" or "library not found" errors).
Step 1.9: Log Setup Start
Now that statement-mcp is available, use its MCP tools to log setup progress. Call the mcp__statement-mcp__declare_topic tool with topic "claude-setup" and a description of "Claude Code environment setup log". Then call mcp__statement-mcp__ingest_collection to record the setup event:
project: "claude"
topic: "claude-setup"
content: "Claude Code setup initiated on [platform] at [timestamp]. Phase 1 (statement-mcp) complete."
From this point forward, log each phase completion by calling mcp__statement-mcp__ingest_collection with the claude-setup topic.
Phase 2: Remaining MCPs
Step 2.1: Context-Lens
Required: Node.js
Source: <repo>/mcp/context/
Deploy to: ~/.claude/mcp-servers/context/
mkdir -p ~/.claude/mcp-servers/context
rsync -a --exclude='node_modules' --exclude='dist' --exclude='.git' \
<repo>/mcp/context/ ~/.claude/mcp-servers/context/
cd ~/.claude/mcp-servers/context
npm install
npm run build
Verify: ls ~/.claude/mcp-servers/context/dist/index.js
Config entry for ~/.claude.json:
"context-lens": {
"command": "node",
"args": ["<HOME>/.claude/mcp-servers/context/dist/index.js"],
"type": "stdio"
}
Step 2.2: Git MCP
Required: uv/uvx
No build step — uvx runs it directly.
Config entry:
"git": {
"command": "uvx",
"args": ["mcp-server-git"]
}
Step 2.3: GitHub MCP Server
Required: Docker (running)
Prompt the user for their GitHub Personal Access Token. NEVER hardcode a PAT. NEVER log it. NEVER commit it.
GitHub MCP server requires a Personal Access Token.
(a) Enter your PAT now (it will be written to ~/.claude.json only)
(b) Skip for now
If PAT provided, config entry:
"github-mcp-server": {
"command": "docker",
"args": [
"run", "-i", "--rm",
"-e", "GITHUB_PERSONAL_ACCESS_TOKEN",
"ghcr.io/github/github-mcp-server"
],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "<user-provided PAT>"
}
}
Step 2.4: Serena (Swift LSP)
Required: Python 3.11, uv
Source: <repo>/serena/
cd <repo>/serena
uv venv --python 3.11
uv pip install -e .
Verify: <repo>/serena/.venv/bin/serena-mcp-server --help 2>&1 | head -5
Config entry:
"serena": {
"command": "<repo>/serena/.venv/bin/serena-mcp-server",
"type": "stdio"
}
Step 2.5: Hopper MCP (Conditional — macOS only)
Guard checks (ALL must pass):
- Platform is
macos-arm or macos-intel
- Hopper app exists:
ls /Applications/Hopper\ Disassembler*.app
- Python + uv available
If ANY guard fails:
- If not macOS: "Hopper MCP is macOS-only. Skipping."
- If macOS but no Hopper: "Hopper Disassembler not found in /Applications. Install Hopper and re-run setup to enable this MCP."
- If no Python/uv: "Hopper MCP requires Python and uv. Install them and re-run setup."
If all guards pass:
cd <repo>/hopper-mcp
uv venv
uv pip install -e .
Verify: <repo>/hopper-mcp/.venv/bin/hopper-mcp --help 2>&1 | head -5
Config entry:
"hopper": {
"command": "<repo>/hopper-mcp/.venv/bin/hopper-mcp",
"type": "stdio"
}
Step 2.6: Record Build State for Phase 2 Components
For each MCP that was built (not skipped), record its commit in ~/.claude/setup-state.json:
| Component | Submodule path | Product path |
|---|
| context-lens | mcp/context | ~/.claude/mcp-servers/context/dist/index.js |
| serena | serena | <repo>/serena/.venv/bin/serena-mcp-server |
| hopper | hopper-mcp | <repo>/hopper-mcp/.venv/bin/hopper-mcp |
For each:
git -C <repo>/<submodule-path> rev-parse HEAD
Update the corresponding entry in setup-state.json. Git MCP and GitHub MCP don't have local source submodules — they don't get build state entries.
Step 2.7: Write ~/.claude.json
Read existing ~/.claude.json. Preserve all non-mcpServers fields (numStartups, tipsHistory, etc.).
Replace mcpServers with ONLY the MCPs that were successfully set up. Do not include MCPs that were skipped.
Write the file. Verify it's valid JSON.
Step 2.8: Log Phase 2 Completion
Log to statement-mcp which MCPs were installed, which were skipped, and why.
Phase 3: Scripts, Hooks, Skills & Global Config
Step 3.1: Deploy Hook Scripts
Source: <repo>/scripts/
Target: ~/.claude/scripts/
Create the target directory structure and symlink each script:
mkdir -p ~/.claude/scripts/context-lens
for f in <repo>/scripts/*.sh <repo>/scripts/*.py; do
[ -f "$f" ] && ln -sf "$f" ~/.claude/scripts/$(basename "$f")
done
for f in <repo>/scripts/context-lens/*.sh; do
[ -f "$f" ] && ln -sf "$f" ~/.claude/scripts/context-lens/$(basename "$f")
done
Verify symlinks resolve:
ls -la ~/.claude/scripts/ | head -20
Step 3.2: Construct settings.json
This is the most complex step. The file is constructed from installed state, not copied.
3.2.1: env
Start with existing env values if ~/.claude/settings.json already exists. Add required flags:
"env": {
"ENABLE_LSP_TOOL": "1",
"CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS": "1"
}
Preserve any additional env values the user had.
3.2.2: permissions.deny
If context-lens was installed:
"deny": [
"Read(*)",
"Grep(*)",
"Glob(*)",
"Bash(*)",
"NotebookEdit(*)",
"mcp__Claude_in_Chrome(*)",
"mcp__Control_Chrome(*)"
]
Rationale: Read/Grep/Glob are denied because they're sloppy exploration — context-lens forces structured access. Bash is gated through context-lens run_command. Write and Edit are NOT denied — they represent intentional action.
If context-lens was NOT installed, only include the Chrome bans (user preference).
3.2.3: permissions.allow
Build the list from these categories:
Core tools (always):
Agent, TodoWrite, Skill, ToolSearch,
Write, Edit,
WebSearch, WebFetch, TaskOutput, TaskCreate, TaskUpdate, TaskStop, Task,
AskUserQuestion,
EnterPlanMode, ExitPlanMode,
EnterWorktree, ExitWorktree,
ListMcpResourcesTool
Per-installed MCP (only if set up in Phase 1-2):
mcp__context-lens # if context-lens installed
mcp__statement-mcp # if statement-mcp installed
mcp__git # if git MCP installed
mcp__github-mcp-server # if github MCP installed
mcp__serena # if serena installed
mcp__scheduled-tasks # always — Anthropic-hosted plugin, no local config needed, just allow
mcp__mcp-registry # always — Anthropic-hosted plugin, no local config needed, just allow
Conditional:
mcp__hopper # only if hopper was installed
Project-scope (always allowed so project-level MCPs don't prompt, but NOT globally configured):
mcp__onshape
mcp__rhino
mcp__CLIDE
mcp__Claude_Preview
IMPORTANT: Present the proposed allow list to the user for confirmation before writing.
Flag anything that looks unexpected. Specifically ask about the project-scope entries — are they still relevant? Should any be added or removed?
3.2.4: hooks
Construct hooks from deployed scripts. Each hook references a symlink in ~/.claude/scripts/.
Each hook entry in settings.json uses this JSON structure:
{
"matcher": "ToolName|OtherTool",
"hooks": [
{
"type": "command",
"command": "bash ~/.claude/scripts/script-name.sh",
"timeout": 2000
}
]
}
The matcher is a pipe-separated list of tool names (empty string "" matches all tools). async: false means the hook blocks until complete. timeout is in milliseconds.
PreToolUse hooks:
-
enforce-tool-bans.sh — ONLY if context-lens installed
- Matcher:
"Read|Edit|Grep|Glob|Bash|NotebookEdit"
- Timeout: 2000
-
enforce-ironclad.sh — always
- Matcher:
"Bash"
- Timeout: 5000
-
read-rate-limiter.sh — ONLY if context-lens installed
- Matcher:
"mcp__context-lens__Read|mcp__context-lens__Grep|mcp__context-lens__Glob"
- Timeout: 2000
-
tool-call-counter.sh — always
- Matcher:
"" (all tools)
- Timeout: 3000
SessionStart hooks:
- session-start.sh — always,
"async": false
- handoff-reload.sh — always,
"async": false
- daily-update.sh — always,
"async": false
Stop hooks:
- context-threshold-stop.sh — always
PreCompact hooks:
- pre-compact.sh — always
PostToolUse hooks:
-
swift-typecheck.sh — ONLY if macOS with Xcode (xcodebuild -version succeeds)
- Matcher:
"Edit|Write"
- Timeout: 15000
-
context-monitor.sh — always
- Matcher:
"" (all tools)
- Timeout: 3000
-
context-lens/track-session.sh — ONLY if context-lens installed
- Matcher:
"" (all tools)
- Timeout: 2000
PostCompact hooks:
- post-compact.sh — always
WorktreeCreate hooks:
- worktree-create.sh — always, timeout: 60
WorktreeRemove hooks:
- worktree-remove.sh — always, timeout: 60
SessionEnd: empty array (reserved for future use)
3.2.5: model and effortLevel
If ~/.claude/settings.json already exists, preserve existing values.
If not set, ask the user:
Model preference:
(a) opusplan (default — uses Opus for planning, Sonnet for execution)
(b) opus
(c) sonnet
Effort level:
(a) max (default)
(b) high
(c) medium
3.2.6: Write settings.json
Assemble the complete JSON object and write to ~/.claude/settings.json.
Include the schema reference:
{
"$schema": "https://json.schemastore.org/claude-code-settings.json",
...
}
Verify it's valid JSON after writing.
Step 3.3: Verify CLAUDE.md
~/.claude/CLAUDE.md is the user's private global instructions. It is NOT stored in the repo — it is hand-maintained.
Check if it exists:
ls ~/.claude/CLAUDE.md
If missing, inform the user: "~/.claude/CLAUDE.md does not exist. This file contains your global instructions for Claude Code. You'll need to create it manually or copy it from a backup."
Do NOT create or overwrite this file automatically.
Step 3.4: Deploy Skills
Run the skills sync script:
python3 ~/.claude/scripts/sync-skills.py
Verify: ls ~/.claude/skills/ should show deployed skill directories.
Step 3.5: Record Build State for Scripts and Skills
Record the current commits for scripts and skills submodules:
git -C <repo>/scripts rev-parse HEAD
git -C <repo>/skills rev-parse HEAD
Update ~/.claude/setup-state.json:
components.scripts → commit, built_at, product: "~/.claude/scripts/"
components.skills → commit, built_at, product: "~/.claude/skills/"
Step 3.6: Log Phase 3 Completion
Log to statement-mcp:
- Which scripts were deployed
- Settings.json construction choices
- Skills sync result
Phase 4: Final Verification
Step 4.1: Verify All Config Files
python3 -c "import json; json.load(open('$HOME/.claude.json'))"
python3 -c "import json; json.load(open('$HOME/.claude/settings.json'))"
for f in ~/.claude/scripts/*.sh ~/.claude/scripts/*.py; do
[ -L "$f" ] && [ ! -e "$f" ] && echo "BROKEN: $f"
done
Step 4.2: Summary Report
Present a final summary:
✓ Setup complete on [platform]
MCPs installed:
✓ statement-mcp (Go binary)
✓ context-lens (Node.js)
✓ git (uvx)
✓ github-mcp-server (Docker)
✓ serena (Python 3.11 venv)
✗ hopper (skipped — Hopper not installed)
Configuration:
✓ ~/.claude.json — 5 MCP servers configured
✓ ~/.claude/settings.json — permissions, hooks, env
✓ ~/.claude/scripts/ — 16 hook scripts symlinked
✓ ~/.claude/skills/ — skills deployed
To enable skipped components, install the missing software and run /setup again.
Step 4.3: Log Completion
Log the full summary to statement-mcp.
Troubleshooting
PostgreSQL won't start
- macOS:
brew services restart postgresql
- Linux:
sudo systemctl restart postgresql
- Check logs:
tail -50 /opt/homebrew/var/log/postgresql.log (macOS) or journalctl -u postgresql (Linux)
onnxruntime not found after install
- macOS:
brew --prefix onnxruntime to find actual path, may need export DYLD_LIBRARY_PATH=$(brew --prefix onnxruntime)/lib
- Linux: Run
sudo ldconfig after copying library
Go build fails for statement-mcp
- Ensure Go modules are available:
cd <repo>/strongai/infrastructure && go mod download
- Check Go version: statement-mcp may require Go 1.21+
Context-lens npm build fails
- Clear node_modules and rebuild:
rm -rf node_modules && npm install && npm run build
- Check Node version: may require Node 18+
Docker permission denied
- Linux:
sudo usermod -aG docker $USER then log out and back in
- macOS: Ensure Docker Desktop is running
Serena venv creation fails
- Ensure Python 3.11 specifically (not 3.12+):
python3.11 --version
- If uv can't find 3.11:
uv python install 3.11
Partial Failure Recovery
If setup fails partway through, the state is well-defined because each phase writes config only after successful installation:
- Phase 1 failed: No
statement-mcp entry in ~/.claude.json. Remaining phases were never attempted. Fix the issue and re-run — Phase 0 will detect existing deps, Phase 1 will retry.
- Phase 2 partially failed:
~/.claude.json has entries for MCPs that succeeded. The failed MCP has no entry. Re-run and the skill will detect which MCPs are working and only retry the failed ones.
- Phase 3 failed: Config files may be partially written. The skill re-reads existing
settings.json and merges, so re-running is safe. Broken symlinks are detected and recreated.
To start completely fresh: Remove generated artifacts and re-run:
rm -f ~/.claude.json
rm -f ~/.claude/settings.json
rm -f ~/.claude/setup-state.json
rm -rf ~/.claude/mcp-servers/
rm -rf ~/.claude/scripts/
rm -rf ~/.claude/skills/
Do NOT remove ~/.claude/CLAUDE.md — that is hand-maintained.