# ✈️ preflight **Stop burning tokens on vague prompts.** A 24-tool MCP server for Claude Code that catches ambiguous instructions before they cost you 2-3x in wrong→fix cycles — plus semantic search across your entire session history, cross-service contract awareness, and 12-category scorecards. [![TypeScript](https://img.shields.io/badge/TypeScript-5.0+-3178C6?logo=typescript&logoColor=white)](https://www.typescriptlang.org/) [![MCP](https://img.shields.io/badge/MCP-Compatible-blueviolet)](https://modelcontextprotocol.io/) [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE) [![npm](https://img.shields.io/npm/v/preflight-dev)](https://www.npmjs.com/package/preflight-dev) [![Node 18+](https://img.shields.io/badge/node-18%2B-brightgreen?logo=node.js&logoColor=white)](https://nodejs.org/) [Quick Start](#quick-start) · [How It Works](#how-it-works) · [Tool Reference](#tool-reference) · [Configuration](#configuration) · [Scoring](#the-12-category-scorecard)
--- ## What's New in v3.2.0 - **Unified `preflight_check` entry point** — one tool that triages every prompt and chains the right checks automatically - **Smart triage classification** — routes prompts through a decision tree (trivial → ambiguous → multi-step → cross-service) - **Correction pattern learning** — remembers past mistakes and warns you before repeating them - **Cross-service contracts** — extracts types, interfaces, routes, and schemas across related projects - **`.preflight/` config directory** — team-shareable YAML config for triage rules and thresholds - **Trend & comparative scorecards** — weekly/monthly trend lines, cross-project comparisons, radar charts, PDF export - **Cost estimator** — estimates token spend and waste from corrections --- ## The Problem We built this after analyzing **9 months of real Claude Code usage** — 512 sessions, 32,000+ events, 3,200+ prompts, 1,642 commits, and 258 sub-agent spawns across a production Next.js/Prisma/Supabase app. The findings were brutal: - **41% of prompts were under 50 characters** — things like `fix the tests`, `commit this`, `remove them` - Each vague prompt triggers a **wrong→fix cycle costing 2-3x tokens** - **~33K characters/day** duplicated from repeated context pastes - **124 corrections logged** — places where Claude went the wrong direction and had to be steered back - **94 context compactions** from unbounded session scope blowing past the context window - Estimated **30-40% of tokens wasted** on avoidable back-and-forth The pattern is always the same: vague prompt → Claude guesses → wrong output → you correct → repeat. That's your money evaporating. ## The Solution 24 tools in 5 categories that run as an MCP server inside Claude Code: | Category | Tools | What it does | |----------|-------|-------------| | ✈️ **Preflight Core** | 1 | Unified entry point — triages every prompt, chains the right checks automatically | | 🎯 **Prompt Discipline** | 12 | Catches vague prompts, enforces structure, prevents waste | | 🔍 **Timeline Intelligence** | 4 | LanceDB vector search across months of session history | | 📊 **Analysis & Reporting** | 4 | Scorecards, cost estimation, session stats, pattern detection | | ✅ **Verification & Hygiene** | 3 | Type-check, test, audit, and contract search | ## Before / After ``` ❌ "fix the auth bug" → Claude guesses which auth bug, edits wrong file → You correct it, 3 more rounds → 12,000 tokens burned ✅ preflight intercepts → clarify_intent fires → "Which auth bug? I see 3 open issues: 1. JWT expiry not refreshing (src/auth/jwt.ts) 2. OAuth callback 404 (src/auth/oauth.ts) 3. Session cookie SameSite (src/middleware/session.ts) Pick one and I'll scope the fix." → 4,000 tokens, done right the first time ``` --- ## Quick Start ### Option A: npx (fastest — no install) ```bash claude mcp add preflight -- npx -y preflight-dev-serve ``` With environment variables: ```bash claude mcp add preflight \ -e CLAUDE_PROJECT_DIR=/path/to/your/project \ -- npx -y preflight-dev-serve ``` ### Option B: Clone & configure manually ```bash git clone https://github.com/TerminalGravity/preflight.git cd preflight && npm install ``` Add to your project's `.mcp.json`: ```json { "mcpServers": { "preflight": { "command": "npx", "args": ["tsx", "/path/to/preflight/src/index.ts"], "env": { "CLAUDE_PROJECT_DIR": "/path/to/your/project" } } } } ``` Restart Claude Code. The tools activate automatically. ### Option C: npm (global) ```bash npm install -g preflight-dev claude mcp add preflight -- preflight-dev-serve ``` > **Note:** `preflight-dev` runs the interactive setup wizard. `preflight-dev-serve` starts the MCP server — that's what you want in your Claude Code config. --- ## How It Works ### The Triage Decision Tree Every prompt flows through a classification engine before any work begins. This is the actual decision tree from [`src/lib/triage.ts`](src/lib/triage.ts): ```mermaid flowchart TD A[Prompt Arrives] --> B{Skip keyword?} B -->|Yes| T1[✅ TRIVIAL] B -->|No| C{Multi-step indicators?} C -->|Yes| MS[🔶 MULTI-STEP] C -->|No| D{Cross-service keywords?} D -->|Yes| CS[🔗 CROSS-SERVICE] D -->|No| E{always_check keyword?} E -->|Yes| AM1[⚠️ AMBIGUOUS] E -->|No| F{"< 20 chars + common cmd?"} F -->|Yes| T2[✅ TRIVIAL] F -->|No| G{"< 50 chars, no file refs?"} G -->|Yes| AM2[⚠️ AMBIGUOUS] G -->|No| H{Vague pronouns or verbs?} H -->|Yes| AM3[⚠️ AMBIGUOUS] H -->|No| CL[✅ CLEAR] style T1 fill:#2d6a4f,color:#fff style T2 fill:#2d6a4f,color:#fff style CL fill:#2d6a4f,color:#fff style AM1 fill:#e9c46a,color:#000 style AM2 fill:#e9c46a,color:#000 style AM3 fill:#e9c46a,color:#000 style CS fill:#457b9d,color:#fff style MS fill:#e76f51,color:#fff ``` Each level triggers different tool chains: | Level | What fires | Example prompt | |-------|-----------|----------------| | **Trivial** | Nothing — pass through | `commit` | | **Clear** | File verification only | `fix null check in src/auth/jwt.ts line 42` | | **Ambiguous** | Clarify intent + git state + workspace priorities | `fix the auth bug` | | **Cross-service** | Clarify + search related projects + contracts | `add tiered rewards` | | **Multi-step** | Clarify + scope + sequence + checkpoints | `refactor auth to OAuth2 and update all consumers` | Additionally, **correction pattern matching** can boost any triage level. If your prompt matches 2+ keywords from a previously logged correction, it's bumped to at least `ambiguous` — even if it would otherwise pass through. ### Data Flow ```mermaid flowchart LR A[User Prompt] --> B[Triage Engine] B --> C[Tool Chain] C --> D[Response] B -.-> E[".preflight/\nconfig.yml\ntriage.yml"] B -.-> F["Patterns\nLog"] C -.-> G["LanceDB\n(per-project)"] C -.-> H["Contracts\n(per-project)"] G -.-> I["~/.claude/projects/\n(session JSONL)"] style A fill:#264653,color:#fff style B fill:#2a9d8f,color:#fff style C fill:#e9c46a,color:#000 style D fill:#e76f51,color:#fff ``` ### Session Data Structure Claude Code stores session data as JSONL files: ``` ~/.claude/projects// ├── .jsonl # Main session ├── / │ └── subagents/ │ └── .jsonl # Sub-agent sessions ``` Each JSONL line is an event. The [session parser](src/lib/session-parser.ts) extracts **8 event types**: | Event Type | Source | What it captures | |-----------|--------|-----------------| | `prompt` | `user` messages | What the dev typed | | `assistant` | `assistant` messages | Claude's text response | | `tool_call` | `assistant` tool_use blocks | Tool invocations (Read, Write, Bash, etc.) | | `sub_agent_spawn` | Task/dispatch_agent tool_use | When Claude delegates to a sub-agent | | `correction` | `user` messages after assistant | Detected via negation patterns (no, wrong, actually, undo…) | | `compaction` | `system` messages | Context was compressed (session hit token limit) | | `error` | `tool_result` with is_error | Failed operations | | `commit` | git log integration | Commits made during session | ### LanceDB Schema Events are stored in per-project [LanceDB](https://lancedb.github.io/lancedb/) databases with vector embeddings for semantic search: ``` ~/.preflight/projects// ├── timeline.lance/ # LanceDB vector database ├── contracts.json # Extracted API contracts └── meta.json # Project metadata Table: events ├── id: string (UUID) ├── content: string (event text) ├── content_preview: string (first 200 chars) ├── vector: float32[384] (Xenova/all-MiniLM-L6-v2) or float32[1536] (OpenAI) ├── type: string (event type from above) ├── timestamp: string (ISO 8601) ├── session_id: string (session UUID) ├── project: string (decoded project path) ├── project_name: string (short name) ├── branch: string (git branch at time of event) ├── source_file: string (path to JSONL file) ├── source_line: number (line number in JSONL) └── metadata: string (JSON — model, tool name, etc.) ``` The project registry at `~/.preflight/projects/index.json` maps absolute paths to their SHA-256 hashes. ### Contract Extraction The [contract extractor](src/lib/contracts.ts) scans your project for API surfaces: | Pattern | What it finds | |---------|--------------| | `export interface/type/enum` | TypeScript type definitions | | `export function GET/POST/…` | Next.js API routes | | `router.get/post/…` | Express route handlers | | `model Foo { … }` | Prisma models and enums | | OpenAPI/Swagger specs | Routes and schema components | | `.preflight/contracts/*.yml` | Manual contract definitions | Contracts are stored per-project and searched across related projects during cross-service triage. --- ## Onboarding a Project Run `onboard_project` to index a project's history. Here's what happens: 1. **Discovers sessions** — finds JSONL files in `~/.claude/projects//`, including subagent sessions 2. **Parses events** — extracts the 8 event types from each session file (streams files >10MB) 3. **Extracts contracts** — scans source for types, interfaces, enums, routes, Prisma models, OpenAPI schemas 4. **Loads manual contracts** — merges any `.preflight/contracts/*.yml` definitions (manual wins on name conflicts) 5. **Generates embeddings** — local [Xenova/all-MiniLM-L6-v2](https://huggingface.co/Xenova/all-MiniLM-L6-v2) by default (~90MB model download on first run, ~50 events/sec) or OpenAI if `OPENAI_API_KEY` is set (~200 events/sec) 6. **Stores in LanceDB** — per-project database at `~/.preflight/projects//timeline.lance/` 7. **Updates registry** — records the project in `~/.preflight/projects/index.json` No data leaves your machine unless you opt into OpenAI embeddings. After onboarding, you get: - 🔎 **Semantic search** — "How did I set up auth middleware last month?" actually works - 📊 **Timeline view** — see what happened across sessions chronologically - 🔄 **Live scanning** — index new sessions as they happen - 🔗 **Cross-service search** — query across related projects --- ## Tool Reference ### ✈️ Preflight Core | Tool | What it does | |------|-------------| | `preflight_check` | **The main entry point.** Triages your prompt (trivial → multi-step), chains the right checks automatically, matches against known correction patterns. Accepts `force_level` override: `skip`, `light`, `full`. | ### 🎯 Prompt Discipline | Tool | What it does | |------|-------------| | `scope_work` | Creates structured execution plans before coding starts | | `clarify_intent` | Gathers project context (git state, workspace docs, ambiguity signals) to disambiguate vague prompts | | `enrich_agent_task` | Enriches sub-agent tasks with file paths, patterns, and cross-service context | | `sharpen_followup` | Resolves "fix it" / "do the others" to actual file targets | | `token_audit` | Detects waste patterns, grades your session A–F | | `sequence_tasks` | Orders tasks by dependency, locality, and risk | | `checkpoint` | Save game before compaction — commits + resumption notes | | `check_session_health` | Monitors uncommitted files, time since commit, turn count | | `log_correction` | Tracks corrections and identifies recurring error patterns | | `check_patterns` | Checks prompts against learned correction patterns — warns about known pitfalls | | `session_handoff` | Generates handoff briefs for new sessions | | `what_changed` | Summarizes diffs since last checkpoint | ### 🔍 Timeline Intelligence | Tool | What it does | |------|-------------| | `onboard_project` | Indexes a project's session history + contracts into per-project LanceDB | | `search_history` | Semantic search with scope: current project, related, or all indexed projects | | `timeline` | Chronological view of events across sessions | | `scan_sessions` | Live scanning of active session data | ### 📊 Analysis & Reporting | Tool | What it does | |------|-------------| | `generate_scorecard` | 12-category report card — session, trend (week/month), or cross-project comparative. Radar chart SVG, PDF or markdown. | | `estimate_cost` | Token usage, dollar cost, waste from corrections, preflight savings | | `session_stats` | Lightweight session analysis — no embeddings needed | | `prompt_score` | Gamified A–F grading on specificity, scope, actionability, done-condition | ### ✅ Verification & Hygiene | Tool | What it does | |------|-------------| | `verify_completion` | Runs type check + tests + build before declaring done | | `audit_workspace` | Finds stale/missing workspace docs vs git activity | | `search_contracts` | Search API contracts, types, and schemas across current and related projects | --- ## Usage Examples Real prompts you'd type in Claude Code once preflight is installed. The tools fire automatically via `preflight_check`, or you can call them directly. ### Catch a vague prompt before it wastes tokens ``` > fix the auth bug preflight_check intercepts → clarify_intent fires: "I found 3 auth-related recent changes: 1. JWT refresh logic in src/auth/jwt.ts (modified 2h ago) 2. OAuth callback route in src/routes/oauth.ts (3 open TODOs) 3. Session middleware in src/middleware/auth.ts (failing test) Which one? Or describe the symptoms." ``` ### Scope a multi-step task before starting ``` > refactor the database layer to use Drizzle instead of Prisma preflight_check triages as MULTI-STEP → scope_work + sequence_tasks fire: Phase 1: Install drizzle-orm, create schema (src/db/schema.ts) Phase 2: Migrate queries in src/services/ (12 files) Phase 3: Update tests (8 files reference prisma mocks) Phase 4: Remove prisma dependencies, delete prisma/ dir Estimated: 4 checkpoints, ~45 min ``` ### Search your session history ``` > use search_history to find how I set up the rate limiter Searches LanceDB across your indexed sessions: Found 3 relevant events (similarity > 0.82): - Session abc123 (Jan 15): Added express-rate-limit to src/middleware/ - Session def456 (Jan 16): Configured per-route limits in src/routes/api.ts - Session ghi789 (Feb 2): Fixed rate limit bypass via X-Forwarded-For ``` ### Grade your prompting habits ``` > use prompt_score on "update the thing" Grade: D - Specificity: 1/5 — no file paths, no identifiers - Scope: 1/5 — "the thing" is completely ambiguous - Actionability: 2/5 — "update" is vague (refactor? fix? add feature?) - Done-condition: 0/5 — no way to know when it's done Suggestion: "Update the price formatter in src/utils/currency.ts to handle JPY (zero-decimal currency)" ``` ### Check session health mid-work ``` > use check_session_health ⚠️ 47 uncommitted files (last commit: 38 min ago) ⚠️ 23 turns since last checkpoint 💡 Consider running `checkpoint` before context compaction hits ``` ### Get a cost estimate ``` > use estimate_cost This session: ~$2.40 (148K tokens) Waste from corrections: ~$0.85 (3 wrong→fix cycles) Preflight savings: ~$1.20 (4 vague prompts caught early) Net: saving roughly 35% vs unchecked prompting ``` --- ## The 12-Category Scorecard `generate_scorecard` evaluates your prompt discipline across 12 categories. Each one measures something specific about how you interact with Claude Code: | # | Category | What it measures | How it scores | |---|----------|-----------------|---------------| | 1 | **Plans** | Do you start sessions with a plan? | % of sessions where the first 3 prompts include file references and >100 chars | | 2 | **Clarification** | Are your prompts specific? | % of user prompts containing file paths or specific identifiers | | 3 | **Delegation** | Are sub-agent tasks well-defined? | % of sub-agent spawns with >200 char descriptions | | 4 | **Follow-up Specificity** | Do follow-ups reference files? | % of follow-up prompts (after assistant response) with file refs or ≥50 chars | | 5 | **Token Efficiency** | How many tool calls per file? | Ratio of tool_calls to unique files touched (ideal: 5-10 calls/file) | | 6 | **Sequencing** | Do you stay focused or context-switch? | Topic switch rate — how often prompts jump between different directory areas | | 7 | **Compaction Management** | Do you commit before compaction? | % of compaction events preceded by a commit within 10 messages | | 8 | **Session Lifecycle** | Do you commit regularly? | % of sessions with healthy commit frequency (every 15-30 min) | | 9 | **Error Recovery** | How quickly do you recover from mistakes? | Correction rate (% of messages) + recovery speed (within 2 messages) | | 10 | **Workspace Hygiene** | Do you maintain workspace docs? | Baseline 75 + bonus for sessions referencing `.claude/` or `CLAUDE.md` | | 11 | **Cross-Session Continuity** | Do new sessions read context? | % of sessions where first 3 tool calls read project context docs | | 12 | **Verification** | Do you test at the end? | % of sessions that ran tests/build/lint in the final 10% of events | ### Report Types | Type | What you get | |------|-------------| | **Scorecard** | Single-period snapshot with 12 categories, radar chart, best/worst highlights | | **Trend** | Weekly or monthly trend line, per-category movement, top 3 improvement areas, best/worst prompts | | **Comparative** | Side-by-side across multiple projects, cross-project pattern detection | All three support **PDF export** (requires Playwright) and **historical baselines** that track your rolling averages over time. --- ## Cross-Service Awareness Preflight understands that microservices share contracts. When your prompt mentions a keyword from a related project, triage escalates to `cross-service` and searches those projects for relevant context. ### Setup **Option 1: `.preflight/config.yml`** (recommended — committed to repo) ```yaml # my-api/.preflight/config.yml related_projects: - path: /Users/jack/Developer/auth-service alias: auth-service - path: /Users/jack/Developer/notifications alias: notifications - path: /Users/jack/Developer/shared-types alias: shared-types ``` **Option 2: Environment variable** (per-user) ```bash PREFLIGHT_RELATED=/path/to/auth-service,/path/to/notifications ``` ### How it works 1. You type: `"add rewards tier validation"` 2. Triage detects `rewards` matches `always_check` keyword → `ambiguous` 3. Cross-service keywords (`auth`, `notification`) don't match, but if you had typed `"add rewards with auth check"` → `cross-service` 4. Preflight searches related projects' LanceDB indexes and contract registries 5. Returns relevant types, interfaces, and routes from those projects 6. You get context like: "auth-service has `interface AuthToken { userId, tier, permissions }` and `POST /api/validate-tier`" This prevents the common failure mode: changing a shared type in one service and forgetting the consumers. --- ## Configuration Reference ### `.preflight/config.yml` Drop this in your project root. Every field is optional — defaults are sensible. ```yaml # Profile controls overall verbosity # "minimal" — only flag ambiguous+, skip clarification detail # "standard" — default behavior # "full" — maximum detail on every non-trivial prompt profile: standard # type: "minimal" | "standard" | "full" # Related projects for cross-service awareness related_projects: # type: RelatedProject[] - path: /absolute/path/to/service # path: string (absolute) alias: service-name # alias: string (used in output + triage matching) # Behavioral thresholds thresholds: session_stale_minutes: 30 # type: number — warn if no activity for this long max_tool_calls_before_checkpoint: 100 # type: number — suggest checkpoint after N tool calls correction_pattern_threshold: 3 # type: number — min corrections to form a pattern # Embedding configuration embeddings: provider: local # type: "local" | "openai" openai_api_key: sk-... # type: string — only needed if provider is "openai" ``` ### `.preflight/triage.yml` Controls the triage classification engine. ```yaml # Keywords that control routing rules: # Prompts containing these → always at least AMBIGUOUS always_check: # type: string[] — default: [rewards, permissions, migration, schema] - rewards - permissions - migration - schema # Prompts containing these → TRIVIAL (pass through) skip: # type: string[] — default: [commit, format, lint] - commit - format - lint # Prompts containing these → CROSS-SERVICE cross_service_keywords: # type: string[] — default: [auth, notification, event, webhook] - auth - notification - event - webhook # How aggressively to classify # "relaxed" — more prompts pass as clear # "standard" — balanced # "strict" — more prompts flagged as ambiguous strictness: standard # type: "relaxed" | "standard" | "strict" ``` ### `.preflight/contracts/*.yml` Manual contract definitions that supplement auto-extraction: ```yaml # .preflight/contracts/api.yml - name: RewardsTier kind: interface description: Reward tier levels and their perks fields: - name: tier type: string required: true - name: multiplier type: number required: true - name: perks type: string[] ``` ### Environment Variables | Variable | Description | Default | |----------|-------------|---------| | `CLAUDE_PROJECT_DIR` | Project root to monitor | **Required** | | `OPENAI_API_KEY` | OpenAI key for embeddings | Uses local Xenova | | `PREFLIGHT_RELATED` | Comma-separated related project paths | None | | `EMBEDDING_PROVIDER` | `local` or `openai` | `local` | | `PROMPT_DISCIPLINE_PROFILE` | `minimal`, `standard`, or `full` | `standard` | Environment variables are **fallbacks** — `.preflight/` config takes precedence when present. > 💡 **Ready-to-use examples:** Copy [`examples/.preflight/`](examples/.preflight/) into your project root for a working starter config with detailed comments. --- ## Embedding Providers | Provider | Setup | Speed | Dimensions | Quality | Privacy | |----------|-------|-------|-----------|---------|---------| | **Local (Xenova)** | Zero config | ~50 events/sec | 384 | Good | 100% local | | **OpenAI** | Set `OPENAI_API_KEY` | ~200 events/sec | 1536 | Excellent | API call | First run with local embeddings downloads the [Xenova/all-MiniLM-L6-v2](https://huggingface.co/Xenova/all-MiniLM-L6-v2) model (~90MB). After that, everything runs offline. --- ## Architecture ```mermaid flowchart TB CC[Claude Code] <-->|MCP Protocol| PS[preflight server] PS --> PC[✈️ Preflight Core] PS --> DT[🎯 Discipline Tools] PS --> TL[🔍 Timeline Tools] PS --> AN[📊 Analysis Tools] PS --> VR[✅ Verify Tools] PC --> TE[Triage Engine] DT --> PL[Pattern Learning] TL --> LDB[(LanceDB\nper-project)] AN --> SCE[Scorecard Engine] TE -.-> CFG[".preflight/\nconfig.yml\ntriage.yml\ncontracts/"] LDB --> SP[Session Parser] SP --> JSONL["~/.claude/projects/\n(session JSONL files)"] style CC fill:#264653,color:#fff style PS fill:#2a9d8f,color:#fff style PC fill:#e76f51,color:#fff style DT fill:#e9c46a,color:#000 style TL fill:#457b9d,color:#fff style AN fill:#6a4c93,color:#fff style VR fill:#2d6a4f,color:#fff style LDB fill:#1d3557,color:#fff ``` ### Per-Project Data Layout ``` ~/.preflight/ ├── config.json # Global config (embedding provider, indexed projects) └── projects/ ├── index.json # Registry: path → { hash, onboarded_at } ├── a1b2c3d4e5f6/ # SHA-256(project_path)[:12] │ ├── timeline.lance/ # LanceDB vector database │ ├── contracts.json # Extracted API contracts │ ├── meta.json # Event count, onboard timestamp │ └── baseline.json # Historical scorecard averages └── f6e5d4c3b2a1/ └── ... # Another project ``` --- ## Troubleshooting ### "Cannot find module 'vectordb'" or LanceDB import errors LanceDB uses native binaries. If you see module resolution errors: ```bash # Clean install with native deps rebuilt rm -rf node_modules package-lock.json npm install # If still failing, check your Node version (20+ required) node --version ``` On Apple Silicon Macs, make sure you're running a native arm64 Node — not Rosetta. Check with `node -e "console.log(process.arch)"` (should print `arm64`). ### First run is slow (~90MB model download) The local embedding provider ([Xenova/all-MiniLM-L6-v2](https://huggingface.co/Xenova/all-MiniLM-L6-v2)) downloads a ~90MB model on first use. This is a one-time cost — subsequent runs use the cached model. If the download hangs behind a corporate proxy, switch to OpenAI embeddings: ```bash export OPENAI_API_KEY=sk-... export EMBEDDING_PROVIDER=openai ``` ### "OpenAI API key required for openai embedding provider" You set `EMBEDDING_PROVIDER=openai` (or `embeddings.provider: openai` in `.preflight/config.yml`) but didn't provide a key. Either: - Set `OPENAI_API_KEY` in your environment, or - Switch back to local: `export EMBEDDING_PROVIDER=local` ### Tools not showing up in Claude Code 1. Make sure the MCP server is registered. Run `claude mcp list` — you should see `preflight`. 2. If missing, re-add it: ```bash claude mcp add preflight -- npx tsx /path/to/preflight/src/index.ts ``` 3. Restart Claude Code after adding. ### `CLAUDE_PROJECT_DIR` not set Some tools (onboarding, session search, contracts) need to know your project root. If they return empty results: ```bash claude mcp add preflight \ -e CLAUDE_PROJECT_DIR=/path/to/your/project \ -- npx tsx /path/to/preflight/src/index.ts ``` Or set it globally: `export CLAUDE_PROJECT_DIR=/path/to/your/project` ### `.preflight/config.yml` parse errors If you see `warning - failed to parse .preflight/config.yml`, your YAML is malformed. Common issues: - Tabs instead of spaces (YAML requires spaces) - Missing quotes around values with special characters - Incorrect indentation under `related_projects` Validate with: `npx yaml-lint .preflight/config.yml` or paste into [yamllint.com](https://www.yamllint.com/). ### No session data found during onboarding `onboard_project` looks for JSONL files in `~/.claude/projects//`. If nothing is found: - Make sure you've actually used Claude Code on the project (at least one session) - Check that `CLAUDE_PROJECT_DIR` matches the exact path Claude Code was opened in - The path encoding is URL-style — `/Users/jack/my-app` becomes `%2FUsers%2Fjack%2Fmy-app` ### Ollama embeddings connection refused If using Ollama as your embedding provider and getting connection errors: ```bash # Make sure Ollama is running ollama serve # Pull the embedding model ollama pull all-minilm # Verify it works curl http://localhost:11434/api/embed -d '{"model":"all-minilm","input":"test"}' ``` --- ## Contributing This project is young and there's plenty to do. Check the [issues](https://github.com/TerminalGravity/preflight/issues) — several are tagged `good first issue`. PRs welcome. No CLA, no bureaucracy. If it makes the tool better, it gets merged. ### Development ```bash git clone https://github.com/TerminalGravity/preflight.git cd preflight npm install npm run build npm test ``` ### Project Structure ``` src/ ├── index.ts # MCP server entry point ├── lib/ │ ├── triage.ts # Prompt classification engine │ ├── session-parser.ts # JSONL session file parser │ ├── timeline-db.ts # LanceDB operations │ ├── contracts.ts # Contract extraction & search │ ├── patterns.ts # Correction pattern learning │ ├── config.ts # .preflight/ config loading │ ├── embeddings.ts # Embedding provider abstraction │ ├── state.ts # Persistent state (logs, patterns) │ ├── git.ts # Git operations │ └── files.ts # File discovery └── tools/ ├── preflight-check.ts # Unified entry point ├── generate-scorecard.ts # 12-category scoring + trends └── ... # One file per tool ``` ## License MIT — do whatever you want with it.