Preflight
Preflight

Doctor

Findings about your AI setup: what it costs in context, what is broken, and the smallest fix

preflight doctor reads your Claude Code, Cursor and Codex files and reports findings. Each finding has a stable code, a severity (error, warning or note), a short explanation, an estimated token cost per session when one is known, and the smallest fix. There is no overall score: findings are listed by severity, each with an icon and a word.

preflight doctor                 # grouped, readable output in a terminal
preflight doctor --json          # JSON array of findings (also the default when piped)
preflight doctor --days 60       # usage window for unused-context checks
preflight doctor --processes     # count running MCP server processes (macOS, Linux)
preflight doctor --measure       # run SessionStart hooks once to measure their output
preflight doctor --connect       # start or call each MCP server (opt-in)

The static doctor only reads files. --measure and --connect run programs and are opt-in; in the desktop app they are previewed and confirmed first. --measure runs each distinct SessionStart hook once in a new, empty temporary folder (CLAUDE_PROJECT_DIR points there) with a time limit, and deletes the folder afterwards. --processes runs ps and is skipped cleanly on other systems.

Token figures are character estimates (characters / 4), the same as the context map. MCP tool definitions are not measured locally, so their cost is shown as unknown, never as zero.

Findings

CodeSeverityWhat it means
skill-manual-candidatenoteA model-invocable Claude Code skill was used at most manualMaxUses times (default 1) in the last N days. Shows the listing tokens a manual skill saves. Fix: preflight skill manual <name>, which sets disable-model-invocation: true; the skill stays callable as /name. A skill with this finding does not get unused-context as well.
unused-contextwarningA skill, subagent, MCP server or plugin is listed every session but was not used in the last N days. Shows the listing tokens it would recover. Fix: disable-model-invocation: true, claude plugin disable, claude mcp remove.
effort-default-highwarningeffortLevel is xhigh or max in a settings file.
agent-no-modelwarningA custom subagent has no model: in its frontmatter. Suggests haiku for search agents, sonnet otherwise.
subagent-model-advicenoteBuilt-in subagents and how to pin a model.
mcp-global-single-projectwarningA user-scope MCP server was called from one project only; move it to that project's .mcp.json.
mcp-processesnote or warningNumber and resident memory of MCP server processes under Claude Code (--processes).
claude-md-longwarningAn instructions file is longer than the line limit.
claude-md-broken-importwarningAn @import points to a missing file.
claude-md-duplicates-skillnoteInstruction lines that a skill already contains.
claude-md-secreterrorAn instructions file contains what looks like a credential.
skill-clusterwarningSkills whose descriptions overlap (Jaccard similarity of normalized words, grouped into connected components). Keep one; set disable-model-invocation: true on the others.
skill-countnote or warningModel-invocable global skills against the target range (60-80 by default).
startup-injectionnoteA SessionStart, UserPromptSubmit, SubagentStart or PreCompact hook (from settings or a plugin) adds its output to the context.
startup-injection-large, startup-injection-totalwarningMeasured SessionStart output is over the per-hook or total budget (--measure).
hook-failed, hook-duplicatewarningA measured hook failed or timed out; a hook is listed more than once.
plugins-many, mcp-manywarningMore enabled plugins or user-level MCP servers (Claude Code or Codex) than the budget.
cache-model-switchnote or warningSessions that switched model mid-session, which drops the prompt cache.
cache-ttl-gapnote or warningPrompts sent after the cache lifetime expired.
cache-variable-prompt-hooknoteA UserPromptSubmit hook added different text to each prompt.

Existing codes such as secret, broad-permissions, mcp-unverified, drift and settings-secret are unchanged.

Usage-based checks (unused-context, mcp-global-single-project, cache hygiene) read the session transcripts in ~/.claude/projects from the window. When there are none, they are listed under Skipped with the reason instead of reporting anything. Cache heuristics ignore subagent lines, which share the parent session. With --no-transcripts, or when transcript reading is turned off in the desktop app, these checks are skipped with that reason. Only Claude Code transcripts are read, so resources that only Codex uses are never reported as unused.

Thresholds

Every threshold can be set under doctor in preflight.config.json. The global configuration (~/.preflight/global/preflight.config.json) applies first, then the project's. Missing keys keep their default.

{
  "version": 1,
  "activeProfile": "default",
  "profiles": { "default": { "resources": [] } },
  "doctor": {
    "unusedDays": 30,
    "manualMaxUses": 1,
    "instructionsMaxLines": 200,
    "skillSimilarity": 0.5,
    "skillTarget": { "min": 60, "max": 80 },
    "maxPlugins": 15,
    "maxMcpServers": 10,
    "hookOutputChars": 1000,
    "hookTotalChars": 2000,
    "hookTimeoutMs": 10000,
    "mcpProcessMemoryMb": 1024,
    "cacheGapMinutes": 5,
    "duplicateMinChars": 40
  }
}
KeyDefaultUsed by
manualMaxUses1skill-manual-candidate: uses in the window at or below which a skill is a candidate
unusedDays30unused-context, mcp-global-single-project, cache checks (--days overrides it)
instructionsMaxLines200claude-md-long
skillSimilarity0.5skill-cluster (0.05 to 1)
skillTarget60-80skill-count, Overview gauge
maxPlugins / maxMcpServers15 / 10plugins-many / mcp-many
hookOutputChars / hookTotalChars1000 / 2000startup-injection-large / startup-injection-total
hookTimeoutMs10000time limit for one measured hook
mcpProcessMemoryMb1024mcp-processes becomes a warning above it
cacheGapMinutes5cache-ttl-gap
duplicateMinChars40shortest line compared for claude-md-duplicates-skill

Instructions

preflight instructions lint [file]
preflight instructions draft [--scope global|project] [--agent claude-code|codex] [--write]

lint reports lines, estimated tokens (with and without @imports, resolved up to five levels deep), broken imports, lines repeated from skills, and credentials, for ~/.claude/CLAUDE.md, the project's CLAUDE.md, .claude/CLAUDE.md and CLAUDE.local.md, plus Codex's $CODEX_HOME/AGENTS.md (default ~/.codex/AGENTS.md) and AGENTS.md. draft --agent codex keeps the blocks that Preflight manages for instructions resources (<!-- preflight:begin … -->) unchanged.

draft proposes a concise file and prints it as a diff. It keeps your rules, removes repeated lines, lines a skill already carries and broken imports, then adds only the short sections your file does not cover: style, verification (with the check commands detected in the project), subagent models (Claude Code), secrets, and skills. Nothing is written without --write; --write --dry-run previews the file change, and a written draft goes through the journaled transaction, so preflight rollback undoes it.

Desktop

Health → Doctor groups findings by severity, with the explanation, fix and token cost of each. Count MCP processes runs the --processes check; Measure startup hooks previews and then runs --measure. Health → Instructions shows the instructions file, a line gauge against the limit, imports and lint findings; Draft improvements opens the diff in the review dialog and writes only when you apply it. The Overview shows the number of global skills against the target range.

Adapted in part from agent-compass (MIT); see THIRD_PARTY_NOTICES.md.

Manual skills and switches

preflight skill manual deploy lint-fix        # preview
preflight skill manual deploy lint-fix --apply
preflight skill auto deploy --apply            # undo
preflight disable grafana --apply              # skill, MCP server, plugin, hook, subagent
preflight enable grafana --apply

Without --apply, each command only previews. skill manual changes one frontmatter line and keeps every other byte of SKILL.md. disable uses the switch of the agent when it has one: enabledPlugins for Claude Code plugins, disabledMcpjsonServers for project MCP servers, enabled = false for Codex MCP servers. Otherwise Preflight moves the entry or file to .preflight/disabled/ (in the home or project folder) and enable puts it back. The preview shows the listing tokens saved. There is no doctor --fix yet.

On this page