Skip to content
Development
Command

/doctor

Health-check the scaffolding install and report install problems plus exact fixes (diagnose-only, never mutates).

From plugin
scaffolding
1621 skills13 agents21 commands25 hooks
> /plugin marketplace add komluk/scaffolding
> /plugin install scaffolding@komluk-scaffolding

Command definition

doctor.md
name: doctor
description: Health-check the scaffolding install and report install problems plus exact fixes (diagnose-only, never mutates).

/doctor Command

Run a health check of the scaffolding plugin install and report problems with the exact command to fix each one. Diagnoses the documented first-run gotchas (the #1 being `Agent type 'scaffolding:...' not found` after a fresh install) and groups findings by severity.

Usage

/doctor

Run from any project. No arguments. Safe to run repeatedly.

Guardrail — DIAGNOSE ONLY (never mutate)

This command **only diagnoses and prints fixes**. It MUST NEVER:

  • run `/reload-plugins`, `/plugin install/update`, or restart anything itself
  • edit `settings.json`, `CLAUDE.md`, `.gitignore`, or any user/project file
  • `chmod`, `mkdir`, `cp`, register an MCP server, or set an env var

It only reads files, runs read-only shell, and spawns **one trivial probe agent** (check #2). Print the exact command for the *user* to run — matches the propose-don't-mutate posture of `/memory`.

Steps

Follow these steps exactly, in order.

Step A — Run the inline health-check bash block

Run the block below verbatim. It performs the file/shell checks (#1, #3–#10) and prints a grouped report. It writes nothing.

# ---- scaffolding /doctor — read-only health check ----
BLOCKING=0; RECOMMENDED=0; OPTIONAL=0
pass() { printf '  [PASS] %s\n' "$1"; }
fail() { printf '  [FAIL] %s\n        fix: %s\n' "$1" "$2"; }

# Locate the installed plugin root (same multi-base discovery as /init-scaffolding)
PLUGIN_ROOT=""
find_plugin_root() {
  local base="$1"; [ -d "$base" ] || return
  local latest
  latest=$(find "$base" -name "CLAUDE.md" -path "*/scaffolding/*/CLAUDE.md" 2>/dev/null | sort -V | tail -1 | xargs dirname 2>/dev/null || true)
  if [ -n "$latest" ] && [ -f "$latest/CLAUDE.md" ]; then echo "$latest"; return; fi
  latest=$(find "$base" -name "CLAUDE.md" 2>/dev/null | sort -V | tail -1 | xargs dirname 2>/dev/null || true)
  if [ -n "$latest" ] && [ -f "$latest/CLAUDE.md" ]; then echo "$latest"; return; fi
}
# Prefer the env var Claude Code injects when the plugin is loaded
if [ -n "${CLAUDE_PLUGIN_ROOT:-}" ] && [ -f "${CLAUDE_PLUGIN_ROOT}/CLAUDE.md" ]; then
  PLUGIN_ROOT="${CLAUDE_PLUGIN_ROOT}"
fi
if [ -z "$PLUGIN_ROOT" ]; then
  for base in \
    "$HOME/.claude/plugins/cache/komluk-scaffolding" \
    "$HOME/.claude/plugins/marketplaces/komluk-scaffolding" \
    "${USERPROFILE:-}/.claude/plugins/cache/komluk-scaffolding" \
    "${LOCALAPPDATA:-}/claude/plugins/cache/komluk-scaffolding"; do
    [ -n "$base" ] || continue
    found=$(find_plugin_root "$base")
    if [ -n "$found" ]; then PLUGIN_ROOT="$found"; break; fi
  done
fi

echo "=== BLOCKING (install will not work until these pass) ==="

# Check 1 — plugin installed / loaded
if [ -n "$PLUGIN_ROOT" ] && [ -f "$PLUGIN_ROOT/CLAUDE.md" ]; then
  if [ -n "${CLAUDE_PLUGIN_ROOT:-}" ]; then
    pass "Plugin installed & loaded (CLAUDE_PLUGIN_ROOT set; root: $PLUGIN_ROOT)"
  else
    pass "Plugin installed (cache root: $PLUGIN_ROOT)"
    echo "        note: CLAUDE_PLUGIN_ROOT not set in this shell — fine for /doctor, but if hooks misbehave, restart Claude Code."
  fi
else
  BLOCKING=$((BLOCKING+1))
  fail "Plugin not installed / not found" "/plugin marketplace add komluk/scaffolding   then   /plugin install scaffolding@komluk-scaffolding"
fi

# Check 1b — agent files present (13) — needed for resolution
if [ -n "$PLUGIN_ROOT" ]; then
  AGENT_COUNT=$(find "$PLUGIN_ROOT/agents" -maxdepth 1 -name '*.md' 2>/dev/null | wc -l | tr -d ' ')
  if [ "$AGENT_COUNT" = "13" ]; then
    pass "All 13 agent definitions present in plugin root"
  else
    BLOCKING=$((BLOCKING+1))
    fail "Incomplete install — found ${AGENT_COUNT:-0}/13 agent files" "/plugin update scaffolding@komluk-scaffolding   then   /reload-plugins"
  fi
fi

# Check 1c — node >= 22 (every hook runs on it; without node the hooks do nothing and say so on stderr)
NODE_MAJOR=$(node -p 'process.versions.node.split(".")[0]' 2>/dev/null || true)
if [ -n "$NODE_MAJOR" ] && [ "$NODE_MAJOR" -ge 22 ] 2>/dev/null; then
  pass "node $(node --version) (>= 22) found for the hooks"
else
  BLOCKING=$((BLOCKING+1))
  fail "node >= 22 not found ($([ -n "$NODE_MAJOR" ] && echo "found major $NODE_MAJOR" || echo "not on PATH")) — hooks (block-*, refactor-guard, action-log, memory-recall, staleness) are not enforced" "install Node.js 22 or newer (https://nodejs.org) and make sure it is on PATH for Claude Code"
fi

# Check 4 — plugin.json valid + hooks registered
if [ -n "$PLUGIN_ROOT" ]; then
  PJ="$PLUGIN_ROOT/.claude-plugin/plugin.json"
  [ -f "$PJ" ] || PJ="$PLUGIN_ROOT/plugin.json"
  if [ -f "$PJ" ] && node -e 'const d = JSON.parse(require("fs").readFileSync(process.argv[1], "utf8")); if (!d.hooks || !Object.keys(d.hooks).length) process.exit(1)' "$PJ" 2>/dev/null; then
    pass "plugin.json valid and hooks registered"
  else
    BLOCKING=$((BLOCKING+1))
    fail "plugin.json missing/invalid or no hooks registered" "/plugin update scaffolding@komluk-scaffolding   then   /reload-plugins"
  fi
fi

echo ""
echo "=== RECOMMENDED (protocol / hooks / memory tiers) ==="

# Check 3a — settings.json present in plugin root
if [ -n "$PLUGIN_ROOT" ] && [ -f "$PLUGIN_ROOT/settings.json" ] \
   && node -e 'JSON.parse(require("fs").readFileSync(process.argv[1], "utf8"))' "$PLUGIN_ROOT/settings.json" 2>/dev/null; then
  pass "settings.json present and valid in plugin root"
else
  RECOMMENDED=$((RECOMMENDED+1))
  fail "settings.json missing or unparseable in plugin root" "/plugin update scaffolding@komluk-scaffolding (reinstall)"
fi

# Check 3b — hook .sh files present + executable (9 plugin-registered hooks; refresh-mcp-token.sh is opt-in)
if [ -n "$PLUGIN_ROOT" ] && [ -d "$PLUGIN_ROOT/hooks" ]; then
  NONEXEC=$(find "$PLUGIN_ROOT/hooks" -maxdepth 1 -name '*.sh' ! -perm -u+x 2>/dev/null | wc -l | tr -d ' ')
  SH_COUNT=$(find "$PLUGIN_ROOT/hooks" -maxdepth 1 -name '*.sh'
Read more
@komluk
Ships withscaffolding

Spec-driven multi-agent orchestration for Claude Code — pure markdown, zero backend, runs on the stock runtime. 13 agents, 39 skills, 21 commands, 20 hooks, per-phase model tiers, opt-in lifecycle hooks, optional cross-device semantic memory.

1639 skills13 agents
Get the whole plugin

Stars on GitHub

Momentum

stars in total
16
Star history of komluk/scaffolding on GitHub, a chart by star-history.com

Other commands on scaffolding.

context

context

Command

Analyze and optimize Claude Code's context configuration (analyze, optimize, or reset).

@komluk@komlukInstall Command
create-skill

create-skill

Command

Scaffold a new scaffolding-compatible skill: an interactive flow that creates `skills/<name>/SKILL.md` from the canonical…

@komluk@komlukInstall Command
init-rules

init-rules

Command

Scaffold opt-in path-scoped nested CLAUDE.md rule files into the project to lazy-load per-area conventions while keeping routing…

@komluk@komlukInstall Command
init-scaffolding

init-scaffolding

Command

Bootstrap a new project with the scaffolding CLAUDE.md, settings.json, and `.scaffolding/` directory structure.

@komluk@komlukInstall Command
learn

learn

Command

Distill a finished conversation into classified knowledge candidates and propose (never auto-apply) memory writes or a new-skill…

@komluk@komlukInstall Command

More commands from other plugins.

build
Auto-invoked

build

Command

Implement tasks incrementally — build, test, verify, commit. Add "auto" to run the whole plan in one approved pass.

@addyosmani@addyosmaniInstall Command