/doctor
Read-only check of toolchain and kit config, with one fix-it command per failure
> /plugin marketplace add solanabr/ai-kit> /plugin install solana-ai-kit@stbr
Command definition
doctor.mddescription: "Read-only check of toolchain and kit config, with one fix-it command per failure"
model: sonnet
Run the thirteen checks below, then report. Status values: `OK` healthy, `WARN` works but fix soon, `FAIL` blocks workflows, `n/a` not applicable.
Checks
**1. Core toolchain.** `node --version`, `npm --version`. OK when both exist and node is 18+. Missing: `brew install node` / `npm install -g @anthropic-ai/claude-code`. `claude --version` gives the Claude Code version. If it is refused — firewall rule sets before 9 deny every nested `claude`, `--version` included — or fails, report the version as `unknown`; the user sees it in `/status`.
**2. Solana CLI and cluster.** `solana --version`; `solana config get | grep "RPC URL"`; `solana balance --url devnet`.
- WARN devnet balance 0: `solana airdrop 2 --url devnet`
- WARN cluster is mainnet during development: `solana config set --url devnet`
- FAIL no CLI: `sh -c "$(curl -sSfL https://release.anza.xyz/stable/install)"`
**3. Rust/Anchor toolchain** (`n/a` unless `Anchor.toml` or `programs/` exists). `rustc --version`, `cargo --version`, `anchor --version`, `avm --version`.
- FAIL no rustc/cargo: `curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh`
- FAIL no anchor: `cargo install --git https://github.com/solana-foundation/anchor avm --force && avm install latest && avm use latest`
- WARN `anchor --version` differs from `anchor_version` in `Anchor.toml`: `avm use <version>`
**4. Git submodules.** `git submodule status`; lines starting with a space are OK.
- FAIL `-` prefix (uninitialized): `git submodule update --init --recursive`
- WARN `+` prefix (checkout differs from the recorded SHA): `git submodule update --recursive`, or `/resync` if intentional
**5. Environment keys.** Expected names come from `.env.example`, which is tracked and holds no values. What is actually set comes from the names-and-presence helper, which prints one `KEY set|empty` line per key and never a value. Do not read `.env` — safe-ai-skill denies it while it is on, High denies it regardless, and a value read into the transcript has already left the machine.
grep -oE '^[A-Z_]+=' .env.example 2>/dev/null | tr -d = | sort -u # expected names
bash .claude/bin/env-keys.sh 2>/dev/null || echo "HELPER_UNAVAILABLE"
The core `colosseum` skill is the one credential that is not an env key: it signs in through a helper that keeps the token in the OS store. Check it the same way the skill does, which neither reads nor prints a credential:
npx --yes @colosseum-org/copilot-connect status 2>&1 | tail -3 || echo "HELPER_UNAVAILABLE"
- `n/a` when there is no network or npx is unavailable.
- WARN no connection: `npx @colosseum-org/copilot-connect login` (Node 20+; `--device` where no browser can open). Until then the colosseum skill has nothing to query.
- `n/a — skipped (firewall tier denies .env reads)` when the helper is missing or exits non-zero: list the expected names and stop. A gate doing its job is never a `FAIL`.
- WARN key missing or empty: `/setup-mcp` (MCP keys) or edit `.env` by hand
- FAIL the helper reports no `.env` at all: `cp .env.example .env`, then `/setup-mcp`
**6. Kit version vs upstream.**
cat .claude/VERSION
git ls-remote --tags --sort=-v:refname https://github.com/solanabr/ai-kit | head -3
- WARN behind the latest tag: `/update`, or from a shell `SOLANA_AI_KIT_BRANCH="$(bash .claude/bin/kit-ref.sh)" bash .claude/bin/update.sh` (`.agents/bin/` for `--agents` installs); preview with `--dry-run`
- FAIL no `VERSION` file (corrupted or pre-1.0 config): the same update command
**7. MCP config.**
python3 -c "import json; d=json.load(open('.mcp.json')); print('\n'.join(d.get('mcpServers', {}).keys()))" \
2>/dev/null || echo "INVALID or missing .mcp.json"
if grep -q '"surfpool"' .mcp.json 2>/dev/null; then
surfpool --version 2>/dev/null || echo "MISSING surfpool CLI"
fi
grep -q 'memsearch-mcp' .mcp.json 2>/dev/null && echo "RETIRED memsearch-mcp entry"OK when it parses and lists the default servers (helius, solana-dev, context7) plus any the user added.
- FAIL parse failure: `curl -fsSL https://raw.githubusercontent.com/solanabr/ai-kit/main/.mcp.json -o .mcp.json`
- WARN a listed server's API key failed check 5: `/setup-mcp`
- WARN `surfpool` listed but the CLI is missing: `curl -L https://surfpool.run/install | sh` (or `brew install txtx/taps/surfpool`)
- WARN `memsearch-mcp` listed: that npm package is not published, so the server never starts; delete the `memsearch` entry from `.mcp.json`. memsearch ships as a Claude Code plugin instead (`/plugin marketplace add zilliztech/memsearch`, `/plugin install memsearch`, then restart Claude Code)
**8. Dual-install guard.** The plugin (`/plugin install solana-ai-kit@stbr`) and a full install (`install.sh` into `.claude/`) in the same project double-load commands, hooks and MCP servers (`/deploy` beside `/solana-ai-kit:deploy`, the banner printed twice). Detect it from the project config alone. `$HOME/.claude/settings.json` is outside the working directory, so High's read fence refuses it.
[ -f .claude/VERSION ] && echo "FULL_INSTALL present"
grep -qE '"solana-ai-kit@[^"]*"[[:space:]]*:[[:space:]]*true' .claude/settings.json 2>/dev/null \
&& echo "PLUGIN enabled (project scope)"
[ -f .claude/VERSION ] && [ -f .agents/VERSION ] && echo "DUAL_INSTALL .claude/ and .agents/"
OK with exactly one of the two, `n/a` with neither. WARN with both; the fix is to pick one: `/plugin uninstall solana-ai-kit` (keeps the full install's permissions/sandbox policy and ext/ submodules), or remove the project `.claude/` and rely on the plugin, which carries neither. Report user-scope enablement as `unknown` whenever check 9 shows the read fence on — a plugin enabled only in `~/.claude/settings.json` is invisible then, and `/plugin` is where the user can see it. `DUAL_INSTALL` (a regular install beside an `--agents` one) is OK and works,
Read more
description: "Read-only check of toolchain and kit config, with one fix-it command per failure" model: sonnet
Run the thirteen checks below, then report. Status values: `OK` healthy, `WARN` works but fix soon, `FAIL` blocks workflows, `n/a` not applicable.
Checks
**1. Core toolchain.** `node --version`, `npm --version`. OK when both exist and node is 18+. Missing: `brew install node` / `npm install -g @anthropic-ai/claude-code`. `claude --version` gives the Claude Code version. If it is refused — firewall rule sets before 9 deny every nested `claude`, `--version` included — or fails, report the version as `unknown`; the user sees it in `/status`.
**2. Solana CLI and cluster.** `solana --version`; `solana config get | grep "RPC URL"`; `solana balance --url devnet`.
- WARN devnet balance 0: `solana airdrop 2 --url devnet`
- WARN cluster is mainnet during development: `solana config set --url devnet`
- FAIL no CLI: `sh -c "$(curl -sSfL https://release.anza.xyz/stable/install)"`
**3. Rust/Anchor toolchain** (`n/a` unless `Anchor.toml` or `programs/` exists). `rustc --version`, `cargo --version`, `anchor --version`, `avm --version`.
- FAIL no rustc/cargo: `curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh`
- FAIL no anchor: `cargo install --git https://github.com/solana-foundation/anchor avm --force && avm install latest && avm use latest`
- WARN `anchor --version` differs from `anchor_version` in `Anchor.toml`: `avm use <version>`
**4. Git submodules.** `git submodule status`; lines starting with a space are OK.
- FAIL `-` prefix (uninitialized): `git submodule update --init --recursive`
- WARN `+` prefix (checkout differs from the recorded SHA): `git submodule update --recursive`, or `/resync` if intentional
**5. Environment keys.** Expected names come from `.env.example`, which is tracked and holds no values. What is actually set comes from the names-and-presence helper, which prints one `KEY set|empty` line per key and never a value. Do not read `.env` — safe-ai-skill denies it while it is on, High denies it regardless, and a value read into the transcript has already left the machine.
grep -oE '^[A-Z_]+=' .env.example 2>/dev/null | tr -d = | sort -u # expected names bash .claude/bin/env-keys.sh 2>/dev/null || echo "HELPER_UNAVAILABLE"
The core `colosseum` skill is the one credential that is not an env key: it signs in through a helper that keeps the token in the OS store. Check it the same way the skill does, which neither reads nor prints a credential:
npx --yes @colosseum-org/copilot-connect status 2>&1 | tail -3 || echo "HELPER_UNAVAILABLE"
- `n/a` when there is no network or npx is unavailable.
- WARN no connection: `npx @colosseum-org/copilot-connect login` (Node 20+; `--device` where no browser can open). Until then the colosseum skill has nothing to query.
- `n/a — skipped (firewall tier denies .env reads)` when the helper is missing or exits non-zero: list the expected names and stop. A gate doing its job is never a `FAIL`.
- WARN key missing or empty: `/setup-mcp` (MCP keys) or edit `.env` by hand
- FAIL the helper reports no `.env` at all: `cp .env.example .env`, then `/setup-mcp`
**6. Kit version vs upstream.**
cat .claude/VERSION git ls-remote --tags --sort=-v:refname https://github.com/solanabr/ai-kit | head -3
- WARN behind the latest tag: `/update`, or from a shell `SOLANA_AI_KIT_BRANCH="$(bash .claude/bin/kit-ref.sh)" bash .claude/bin/update.sh` (`.agents/bin/` for `--agents` installs); preview with `--dry-run`
- FAIL no `VERSION` file (corrupted or pre-1.0 config): the same update command
**7. MCP config.**
python3 -c "import json; d=json.load(open('.mcp.json')); print('\n'.join(d.get('mcpServers', {}).keys()))" \
2>/dev/null || echo "INVALID or missing .mcp.json"
if grep -q '"surfpool"' .mcp.json 2>/dev/null; then
surfpool --version 2>/dev/null || echo "MISSING surfpool CLI"
fi
grep -q 'memsearch-mcp' .mcp.json 2>/dev/null && echo "RETIRED memsearch-mcp entry"OK when it parses and lists the default servers (helius, solana-dev, context7) plus any the user added.
- FAIL parse failure: `curl -fsSL https://raw.githubusercontent.com/solanabr/ai-kit/main/.mcp.json -o .mcp.json`
- WARN a listed server's API key failed check 5: `/setup-mcp`
- WARN `surfpool` listed but the CLI is missing: `curl -L https://surfpool.run/install | sh` (or `brew install txtx/taps/surfpool`)
- WARN `memsearch-mcp` listed: that npm package is not published, so the server never starts; delete the `memsearch` entry from `.mcp.json`. memsearch ships as a Claude Code plugin instead (`/plugin marketplace add zilliztech/memsearch`, `/plugin install memsearch`, then restart Claude Code)
**8. Dual-install guard.** The plugin (`/plugin install solana-ai-kit@stbr`) and a full install (`install.sh` into `.claude/`) in the same project double-load commands, hooks and MCP servers (`/deploy` beside `/solana-ai-kit:deploy`, the banner printed twice). Detect it from the project config alone. `$HOME/.claude/settings.json` is outside the working directory, so High's read fence refuses it.
[ -f .claude/VERSION ] && echo "FULL_INSTALL present" grep -qE '"solana-ai-kit@[^"]*"[[:space:]]*:[[:space:]]*true' .claude/settings.json 2>/dev/null \ && echo "PLUGIN enabled (project scope)" [ -f .claude/VERSION ] && [ -f .agents/VERSION ] && echo "DUAL_INSTALL .claude/ and .agents/"
OK with exactly one of the two, `n/a` with neither. WARN with both; the fix is to pick one: `/plugin uninstall solana-ai-kit` (keeps the full install's permissions/sandbox policy and ext/ submodules), or remove the project `.claude/` and rely on the plugin, which carries neither. Report user-scope enablement as `unknown` whenever check 9 shows the read fence on — a plugin enabled only in `~/.claude/settings.json` is invisible then, and `/plugin` is where the user can see it. `DUAL_INSTALL` (a regular install beside an `--agents` one) is OK and works,
Claude Code, set up to ship on Solana. Not programs alone — the whole lifecycle: validating the idea, building the program and the app around it, shipping it, and the launch and growth work that follows.
Other commands on ai-kit.
More commands from other plugins.
build
CommandImplement tasks incrementally — build, test, verify, commit. Add "auto" to run the whole plan in one approved pass.

