{"id":47383425,"url":"https://github.com/preflight-dev/preflight","last_synced_at":"2026-04-02T20:01:05.048Z","repository":{"id":338060006,"uuid":"1156411733","full_name":"preflight-dev/preflight","owner":"preflight-dev","description":"✈️ 24-tool MCP server for Claude Code: preflight checks for your prompts, cross-service context, session history search with LanceDB vectors, correction pattern learning, cost estimation","archived":false,"fork":false,"pushed_at":"2026-03-13T23:14:49.000Z","size":3807,"stargazers_count":0,"open_issues_count":76,"forks_count":1,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-03-14T03:44:34.988Z","etag":null,"topics":["ai-coding","ai-tools","anthropic","claude","claude-code","code-quality","cost-estimation","developer-tools","devtools","lancedb","mcp","mcp-server","model-context-protocol","preflight","prompt-engineering","prompt-quality","semantic-search","token-optimization","typescript","vector-search"],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/package/preflight-dev","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/preflight-dev.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-02-12T16:09:53.000Z","updated_at":"2026-03-11T16:49:54.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/preflight-dev/preflight","commit_stats":null,"previous_names":["alldigitalrewards/prompt-discipline","terminalgravity/prompt-discipline","preflight-dev/preflight"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/preflight-dev/preflight","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/preflight-dev%2Fpreflight","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/preflight-dev%2Fpreflight/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/preflight-dev%2Fpreflight/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/preflight-dev%2Fpreflight/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/preflight-dev","download_url":"https://codeload.github.com/preflight-dev/preflight/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/preflight-dev%2Fpreflight/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31314782,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-02T12:59:32.332Z","status":"ssl_error","status_checked_at":"2026-04-02T12:54:48.875Z","response_time":89,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai-coding","ai-tools","anthropic","claude","claude-code","code-quality","cost-estimation","developer-tools","devtools","lancedb","mcp","mcp-server","model-context-protocol","preflight","prompt-engineering","prompt-quality","semantic-search","token-optimization","typescript","vector-search"],"created_at":"2026-03-19T16:00:45.138Z","updated_at":"2026-04-02T20:01:05.041Z","avatar_url":"https://github.com/preflight-dev.png","language":"TypeScript","readme":"\u003cdiv align=\"center\"\u003e\n\n# ✈️ preflight\n\n**Stop burning tokens on vague prompts.**\n\nA 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.\n\n[![TypeScript](https://img.shields.io/badge/TypeScript-5.0+-3178C6?logo=typescript\u0026logoColor=white)](https://www.typescriptlang.org/)\n[![MCP](https://img.shields.io/badge/MCP-Compatible-blueviolet)](https://modelcontextprotocol.io/)\n[![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE)\n[![npm](https://img.shields.io/npm/v/preflight-dev)](https://www.npmjs.com/package/preflight-dev)\n[![Node 18+](https://img.shields.io/badge/node-18%2B-brightgreen?logo=node.js\u0026logoColor=white)](https://nodejs.org/)\n\n[Quick Start](#quick-start) · [How It Works](#how-it-works) · [Tool Reference](#tool-reference) · [Configuration](#configuration) · [Scoring](#the-12-category-scorecard)\n\n\u003c/div\u003e\n\n---\n\n## What's New in v3.2.0\n\n- **Unified `preflight_check` entry point** — one tool that triages every prompt and chains the right checks automatically\n- **Smart triage classification** — routes prompts through a decision tree (trivial → ambiguous → multi-step → cross-service)\n- **Correction pattern learning** — remembers past mistakes and warns you before repeating them\n- **Cross-service contracts** — extracts types, interfaces, routes, and schemas across related projects\n- **`.preflight/` config directory** — team-shareable YAML config for triage rules and thresholds\n- **Trend \u0026 comparative scorecards** — weekly/monthly trend lines, cross-project comparisons, radar charts, PDF export\n- **Cost estimator** — estimates token spend and waste from corrections\n\n---\n\n## The Problem\n\nWe 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:\n\n- **41% of prompts were under 50 characters** — things like `fix the tests`, `commit this`, `remove them`\n- Each vague prompt triggers a **wrong→fix cycle costing 2-3x tokens**\n- **~33K characters/day** duplicated from repeated context pastes\n- **124 corrections logged** — places where Claude went the wrong direction and had to be steered back\n- **94 context compactions** from unbounded session scope blowing past the context window\n- Estimated **30-40% of tokens wasted** on avoidable back-and-forth\n\nThe pattern is always the same: vague prompt → Claude guesses → wrong output → you correct → repeat. That's your money evaporating.\n\n## The Solution\n\n24 tools in 5 categories that run as an MCP server inside Claude Code:\n\n| Category | Tools | What it does |\n|----------|-------|-------------|\n| ✈️ **Preflight Core** | 1 | Unified entry point — triages every prompt, chains the right checks automatically |\n| 🎯 **Prompt Discipline** | 12 | Catches vague prompts, enforces structure, prevents waste |\n| 🔍 **Timeline Intelligence** | 4 | LanceDB vector search across months of session history |\n| 📊 **Analysis \u0026 Reporting** | 4 | Scorecards, cost estimation, session stats, pattern detection |\n| ✅ **Verification \u0026 Hygiene** | 3 | Type-check, test, audit, and contract search |\n\n## Before / After\n\n```\n❌  \"fix the auth bug\"\n     → Claude guesses which auth bug, edits wrong file\n     → You correct it, 3 more rounds\n     → 12,000 tokens burned\n\n✅  preflight intercepts → clarify_intent fires\n     → \"Which auth bug? I see 3 open issues:\n        1. JWT expiry not refreshing (src/auth/jwt.ts)\n        2. OAuth callback 404 (src/auth/oauth.ts)\n        3. Session cookie SameSite (src/middleware/session.ts)\n        Pick one and I'll scope the fix.\"\n     → 4,000 tokens, done right the first time\n```\n\n---\n\n## Quick Start\n\n### Option A: npx (fastest — no install)\n\n```bash\nclaude mcp add preflight -- npx -y preflight-dev-serve\n```\n\nWith environment variables:\n\n```bash\nclaude mcp add preflight \\\n  -e CLAUDE_PROJECT_DIR=/path/to/your/project \\\n  -- npx -y preflight-dev-serve\n```\n\n### Option B: Clone \u0026 configure manually\n\n```bash\ngit clone https://github.com/TerminalGravity/preflight.git\ncd preflight \u0026\u0026 npm install\n```\n\nAdd to your project's `.mcp.json`:\n\n```json\n{\n  \"mcpServers\": {\n    \"preflight\": {\n      \"command\": \"npx\",\n      \"args\": [\"tsx\", \"/path/to/preflight/src/index.ts\"],\n      \"env\": {\n        \"CLAUDE_PROJECT_DIR\": \"/path/to/your/project\"\n      }\n    }\n  }\n}\n```\n\nRestart Claude Code. The tools activate automatically.\n\n### Option C: npm (global)\n\n```bash\nnpm install -g preflight-dev\nclaude mcp add preflight -- preflight-dev-serve\n```\n\n\u003e **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.\n\n---\n\n## How It Works\n\n### The Triage Decision Tree\n\nEvery 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):\n\n```mermaid\nflowchart TD\n    A[Prompt Arrives] --\u003e B{Skip keyword?}\n    B --\u003e|Yes| T1[✅ TRIVIAL]\n    B --\u003e|No| C{Multi-step indicators?}\n    C --\u003e|Yes| MS[🔶 MULTI-STEP]\n    C --\u003e|No| D{Cross-service keywords?}\n    D --\u003e|Yes| CS[🔗 CROSS-SERVICE]\n    D --\u003e|No| E{always_check keyword?}\n    E --\u003e|Yes| AM1[⚠️ AMBIGUOUS]\n    E --\u003e|No| F{\"\u003c 20 chars + common cmd?\"}\n    F --\u003e|Yes| T2[✅ TRIVIAL]\n    F --\u003e|No| G{\"\u003c 50 chars, no file refs?\"}\n    G --\u003e|Yes| AM2[⚠️ AMBIGUOUS]\n    G --\u003e|No| H{Vague pronouns or verbs?}\n    H --\u003e|Yes| AM3[⚠️ AMBIGUOUS]\n    H --\u003e|No| CL[✅ CLEAR]\n\n    style T1 fill:#2d6a4f,color:#fff\n    style T2 fill:#2d6a4f,color:#fff\n    style CL fill:#2d6a4f,color:#fff\n    style AM1 fill:#e9c46a,color:#000\n    style AM2 fill:#e9c46a,color:#000\n    style AM3 fill:#e9c46a,color:#000\n    style CS fill:#457b9d,color:#fff\n    style MS fill:#e76f51,color:#fff\n```\n\nEach level triggers different tool chains:\n\n| Level | What fires | Example prompt |\n|-------|-----------|----------------|\n| **Trivial** | Nothing — pass through | `commit` |\n| **Clear** | File verification only | `fix null check in src/auth/jwt.ts line 42` |\n| **Ambiguous** | Clarify intent + git state + workspace priorities | `fix the auth bug` |\n| **Cross-service** | Clarify + search related projects + contracts | `add tiered rewards` |\n| **Multi-step** | Clarify + scope + sequence + checkpoints | `refactor auth to OAuth2 and update all consumers` |\n\nAdditionally, **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.\n\n### Data Flow\n\n```mermaid\nflowchart LR\n    A[User Prompt] --\u003e B[Triage Engine]\n    B --\u003e C[Tool Chain]\n    C --\u003e D[Response]\n\n    B -.-\u003e E[\".preflight/\\nconfig.yml\\ntriage.yml\"]\n    B -.-\u003e F[\"Patterns\\nLog\"]\n    C -.-\u003e G[\"LanceDB\\n(per-project)\"]\n    C -.-\u003e H[\"Contracts\\n(per-project)\"]\n    G -.-\u003e I[\"~/.claude/projects/\\n(session JSONL)\"]\n\n    style A fill:#264653,color:#fff\n    style B fill:#2a9d8f,color:#fff\n    style C fill:#e9c46a,color:#000\n    style D fill:#e76f51,color:#fff\n```\n\n### Session Data Structure\n\nClaude Code stores session data as JSONL files:\n\n```\n~/.claude/projects/\u003cencoded-path\u003e/\n├── \u003csession-uuid\u003e.jsonl              # Main session\n├── \u003csession-uuid\u003e/\n│   └── subagents/\n│       └── \u003csub-uuid\u003e.jsonl          # Sub-agent sessions\n```\n\nEach JSONL line is an event. The [session parser](src/lib/session-parser.ts) extracts **8 event types**:\n\n| Event Type | Source | What it captures |\n|-----------|--------|-----------------|\n| `prompt` | `user` messages | What the dev typed |\n| `assistant` | `assistant` messages | Claude's text response |\n| `tool_call` | `assistant` tool_use blocks | Tool invocations (Read, Write, Bash, etc.) |\n| `sub_agent_spawn` | Task/dispatch_agent tool_use | When Claude delegates to a sub-agent |\n| `correction` | `user` messages after assistant | Detected via negation patterns (no, wrong, actually, undo…) |\n| `compaction` | `system` messages | Context was compressed (session hit token limit) |\n| `error` | `tool_result` with is_error | Failed operations |\n| `commit` | git log integration | Commits made during session |\n\n### LanceDB Schema\n\nEvents are stored in per-project [LanceDB](https://lancedb.github.io/lancedb/) databases with vector embeddings for semantic search:\n\n```\n~/.preflight/projects/\u003csha256-12-char\u003e/\n├── timeline.lance/       # LanceDB vector database\n├── contracts.json        # Extracted API contracts\n└── meta.json             # Project metadata\n\nTable: events\n├── id: string            (UUID)\n├── content: string       (event text)\n├── content_preview: string (first 200 chars)\n├── vector: float32[384]  (Xenova/all-MiniLM-L6-v2) or float32[1536] (OpenAI)\n├── type: string          (event type from above)\n├── timestamp: string     (ISO 8601)\n├── session_id: string    (session UUID)\n├── project: string       (decoded project path)\n├── project_name: string  (short name)\n├── branch: string        (git branch at time of event)\n├── source_file: string   (path to JSONL file)\n├── source_line: number   (line number in JSONL)\n└── metadata: string      (JSON — model, tool name, etc.)\n```\n\nThe project registry at `~/.preflight/projects/index.json` maps absolute paths to their SHA-256 hashes.\n\n### Contract Extraction\n\nThe [contract extractor](src/lib/contracts.ts) scans your project for API surfaces:\n\n| Pattern | What it finds |\n|---------|--------------|\n| `export interface/type/enum` | TypeScript type definitions |\n| `export function GET/POST/…` | Next.js API routes |\n| `router.get/post/…` | Express route handlers |\n| `model Foo { … }` | Prisma models and enums |\n| OpenAPI/Swagger specs | Routes and schema components |\n| `.preflight/contracts/*.yml` | Manual contract definitions |\n\nContracts are stored per-project and searched across related projects during cross-service triage.\n\n---\n\n## Onboarding a Project\n\nRun `onboard_project` to index a project's history. Here's what happens:\n\n1. **Discovers sessions** — finds JSONL files in `~/.claude/projects/\u003cencoded-path\u003e/`, including subagent sessions\n2. **Parses events** — extracts the 8 event types from each session file (streams files \u003e10MB)\n3. **Extracts contracts** — scans source for types, interfaces, enums, routes, Prisma models, OpenAPI schemas\n4. **Loads manual contracts** — merges any `.preflight/contracts/*.yml` definitions (manual wins on name conflicts)\n5. **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)\n6. **Stores in LanceDB** — per-project database at `~/.preflight/projects/\u003csha256-12\u003e/timeline.lance/`\n7. **Updates registry** — records the project in `~/.preflight/projects/index.json`\n\nNo data leaves your machine unless you opt into OpenAI embeddings.\n\nAfter onboarding, you get:\n- 🔎 **Semantic search** — \"How did I set up auth middleware last month?\" actually works\n- 📊 **Timeline view** — see what happened across sessions chronologically\n- 🔄 **Live scanning** — index new sessions as they happen\n- 🔗 **Cross-service search** — query across related projects\n\n---\n\n## Tool Reference\n\n### ✈️ Preflight Core\n\n| Tool | What it does |\n|------|-------------|\n| `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`. |\n\n### 🎯 Prompt Discipline\n\n| Tool | What it does |\n|------|-------------|\n| `scope_work` | Creates structured execution plans before coding starts |\n| `clarify_intent` | Gathers project context (git state, workspace docs, ambiguity signals) to disambiguate vague prompts |\n| `enrich_agent_task` | Enriches sub-agent tasks with file paths, patterns, and cross-service context |\n| `sharpen_followup` | Resolves \"fix it\" / \"do the others\" to actual file targets |\n| `token_audit` | Detects waste patterns, grades your session A–F |\n| `sequence_tasks` | Orders tasks by dependency, locality, and risk |\n| `checkpoint` | Save game before compaction — commits + resumption notes |\n| `check_session_health` | Monitors uncommitted files, time since commit, turn count |\n| `log_correction` | Tracks corrections and identifies recurring error patterns |\n| `check_patterns` | Checks prompts against learned correction patterns — warns about known pitfalls |\n| `session_handoff` | Generates handoff briefs for new sessions |\n| `what_changed` | Summarizes diffs since last checkpoint |\n\n### 🔍 Timeline Intelligence\n\n| Tool | What it does |\n|------|-------------|\n| `onboard_project` | Indexes a project's session history + contracts into per-project LanceDB |\n| `search_history` | Semantic search with scope: current project, related, or all indexed projects |\n| `timeline` | Chronological view of events across sessions |\n| `scan_sessions` | Live scanning of active session data |\n\n### 📊 Analysis \u0026 Reporting\n\n| Tool | What it does |\n|------|-------------|\n| `generate_scorecard` | 12-category report card — session, trend (week/month), or cross-project comparative. Radar chart SVG, PDF or markdown. |\n| `estimate_cost` | Token usage, dollar cost, waste from corrections, preflight savings |\n| `session_stats` | Lightweight session analysis — no embeddings needed |\n| `prompt_score` | Gamified A–F grading on specificity, scope, actionability, done-condition |\n\n### ✅ Verification \u0026 Hygiene\n\n| Tool | What it does |\n|------|-------------|\n| `verify_completion` | Runs type check + tests + build before declaring done |\n| `audit_workspace` | Finds stale/missing workspace docs vs git activity |\n| `search_contracts` | Search API contracts, types, and schemas across current and related projects |\n\n---\n\n## Usage Examples\n\nReal prompts you'd type in Claude Code once preflight is installed. The tools fire automatically via `preflight_check`, or you can call them directly.\n\n### Catch a vague prompt before it wastes tokens\n\n```\n\u003e fix the auth bug\n\npreflight_check intercepts → clarify_intent fires:\n  \"I found 3 auth-related recent changes:\n   1. JWT refresh logic in src/auth/jwt.ts (modified 2h ago)\n   2. OAuth callback route in src/routes/oauth.ts (3 open TODOs)\n   3. Session middleware in src/middleware/auth.ts (failing test)\n   Which one? Or describe the symptoms.\"\n```\n\n### Scope a multi-step task before starting\n\n```\n\u003e refactor the database layer to use Drizzle instead of Prisma\n\npreflight_check triages as MULTI-STEP → scope_work + sequence_tasks fire:\n  Phase 1: Install drizzle-orm, create schema (src/db/schema.ts)\n  Phase 2: Migrate queries in src/services/ (12 files)\n  Phase 3: Update tests (8 files reference prisma mocks)\n  Phase 4: Remove prisma dependencies, delete prisma/ dir\n  Estimated: 4 checkpoints, ~45 min\n```\n\n### Search your session history\n\n```\n\u003e use search_history to find how I set up the rate limiter\n\nSearches LanceDB across your indexed sessions:\n  Found 3 relevant events (similarity \u003e 0.82):\n  - Session abc123 (Jan 15): Added express-rate-limit to src/middleware/\n  - Session def456 (Jan 16): Configured per-route limits in src/routes/api.ts\n  - Session ghi789 (Feb 2): Fixed rate limit bypass via X-Forwarded-For\n```\n\n### Grade your prompting habits\n\n```\n\u003e use prompt_score on \"update the thing\"\n\n  Grade: D\n  - Specificity: 1/5 — no file paths, no identifiers\n  - Scope: 1/5 — \"the thing\" is completely ambiguous\n  - Actionability: 2/5 — \"update\" is vague (refactor? fix? add feature?)\n  - Done-condition: 0/5 — no way to know when it's done\n  Suggestion: \"Update the price formatter in src/utils/currency.ts\n  to handle JPY (zero-decimal currency)\"\n```\n\n### Check session health mid-work\n\n```\n\u003e use check_session_health\n\n  ⚠️ 47 uncommitted files (last commit: 38 min ago)\n  ⚠️ 23 turns since last checkpoint\n  💡 Consider running `checkpoint` before context compaction hits\n```\n\n### Get a cost estimate\n\n```\n\u003e use estimate_cost\n\n  This session: ~$2.40 (148K tokens)\n  Waste from corrections: ~$0.85 (3 wrong→fix cycles)\n  Preflight savings: ~$1.20 (4 vague prompts caught early)\n  Net: saving roughly 35% vs unchecked prompting\n```\n\n---\n\n## The 12-Category Scorecard\n\n`generate_scorecard` evaluates your prompt discipline across 12 categories. Each one measures something specific about how you interact with Claude Code:\n\n| # | Category | What it measures | How it scores |\n|---|----------|-----------------|---------------|\n| 1 | **Plans** | Do you start sessions with a plan? | % of sessions where the first 3 prompts include file references and \u003e100 chars |\n| 2 | **Clarification** | Are your prompts specific? | % of user prompts containing file paths or specific identifiers |\n| 3 | **Delegation** | Are sub-agent tasks well-defined? | % of sub-agent spawns with \u003e200 char descriptions |\n| 4 | **Follow-up Specificity** | Do follow-ups reference files? | % of follow-up prompts (after assistant response) with file refs or ≥50 chars |\n| 5 | **Token Efficiency** | How many tool calls per file? | Ratio of tool_calls to unique files touched (ideal: 5-10 calls/file) |\n| 6 | **Sequencing** | Do you stay focused or context-switch? | Topic switch rate — how often prompts jump between different directory areas |\n| 7 | **Compaction Management** | Do you commit before compaction? | % of compaction events preceded by a commit within 10 messages |\n| 8 | **Session Lifecycle** | Do you commit regularly? | % of sessions with healthy commit frequency (every 15-30 min) |\n| 9 | **Error Recovery** | How quickly do you recover from mistakes? | Correction rate (% of messages) + recovery speed (within 2 messages) |\n| 10 | **Workspace Hygiene** | Do you maintain workspace docs? | Baseline 75 + bonus for sessions referencing `.claude/` or `CLAUDE.md` |\n| 11 | **Cross-Session Continuity** | Do new sessions read context? | % of sessions where first 3 tool calls read project context docs |\n| 12 | **Verification** | Do you test at the end? | % of sessions that ran tests/build/lint in the final 10% of events |\n\n### Report Types\n\n| Type | What you get |\n|------|-------------|\n| **Scorecard** | Single-period snapshot with 12 categories, radar chart, best/worst highlights |\n| **Trend** | Weekly or monthly trend line, per-category movement, top 3 improvement areas, best/worst prompts |\n| **Comparative** | Side-by-side across multiple projects, cross-project pattern detection |\n\nAll three support **PDF export** (requires Playwright) and **historical baselines** that track your rolling averages over time.\n\n---\n\n## Cross-Service Awareness\n\nPreflight 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.\n\n### Setup\n\n**Option 1: `.preflight/config.yml`** (recommended — committed to repo)\n\n```yaml\n# my-api/.preflight/config.yml\nrelated_projects:\n  - path: /Users/jack/Developer/auth-service\n    alias: auth-service\n  - path: /Users/jack/Developer/notifications\n    alias: notifications\n  - path: /Users/jack/Developer/shared-types\n    alias: shared-types\n```\n\n**Option 2: Environment variable** (per-user)\n\n```bash\nPREFLIGHT_RELATED=/path/to/auth-service,/path/to/notifications\n```\n\n### How it works\n\n1. You type: `\"add rewards tier validation\"`\n2. Triage detects `rewards` matches `always_check` keyword → `ambiguous`\n3. Cross-service keywords (`auth`, `notification`) don't match, but if you had typed `\"add rewards with auth check\"` → `cross-service`\n4. Preflight searches related projects' LanceDB indexes and contract registries\n5. Returns relevant types, interfaces, and routes from those projects\n6. You get context like: \"auth-service has `interface AuthToken { userId, tier, permissions }` and `POST /api/validate-tier`\"\n\nThis prevents the common failure mode: changing a shared type in one service and forgetting the consumers.\n\n---\n\n## Configuration Reference\n\n### `.preflight/config.yml`\n\nDrop this in your project root. Every field is optional — defaults are sensible.\n\n```yaml\n# Profile controls overall verbosity\n# \"minimal\" — only flag ambiguous+, skip clarification detail\n# \"standard\" — default behavior\n# \"full\" — maximum detail on every non-trivial prompt\nprofile: standard                          # type: \"minimal\" | \"standard\" | \"full\"\n\n# Related projects for cross-service awareness\nrelated_projects:                          # type: RelatedProject[]\n  - path: /absolute/path/to/service        #   path: string (absolute)\n    alias: service-name                    #   alias: string (used in output + triage matching)\n\n# Behavioral thresholds\nthresholds:\n  session_stale_minutes: 30                # type: number — warn if no activity for this long\n  max_tool_calls_before_checkpoint: 100    # type: number — suggest checkpoint after N tool calls\n  correction_pattern_threshold: 3          # type: number — min corrections to form a pattern\n\n# Embedding configuration\nembeddings:\n  provider: local                          # type: \"local\" | \"openai\"\n  openai_api_key: sk-...                   # type: string — only needed if provider is \"openai\"\n```\n\n### `.preflight/triage.yml`\n\nControls the triage classification engine.\n\n```yaml\n# Keywords that control routing\nrules:\n  # Prompts containing these → always at least AMBIGUOUS\n  always_check:                            # type: string[] — default: [rewards, permissions, migration, schema]\n    - rewards\n    - permissions\n    - migration\n    - schema\n\n  # Prompts containing these → TRIVIAL (pass through)\n  skip:                                    # type: string[] — default: [commit, format, lint]\n    - commit\n    - format\n    - lint\n\n  # Prompts containing these → CROSS-SERVICE\n  cross_service_keywords:                  # type: string[] — default: [auth, notification, event, webhook]\n    - auth\n    - notification\n    - event\n    - webhook\n\n# How aggressively to classify\n# \"relaxed\" — more prompts pass as clear\n# \"standard\" — balanced\n# \"strict\" — more prompts flagged as ambiguous\nstrictness: standard                       # type: \"relaxed\" | \"standard\" | \"strict\"\n```\n\n### `.preflight/contracts/*.yml`\n\nManual contract definitions that supplement auto-extraction:\n\n```yaml\n# .preflight/contracts/api.yml\n- name: RewardsTier\n  kind: interface\n  description: Reward tier levels and their perks\n  fields:\n    - name: tier\n      type: string\n      required: true\n    - name: multiplier\n      type: number\n      required: true\n    - name: perks\n      type: string[]\n```\n\n### Environment Variables\n\n| Variable | Description | Default |\n|----------|-------------|---------|\n| `CLAUDE_PROJECT_DIR` | Project root to monitor | **Required** |\n| `OPENAI_API_KEY` | OpenAI key for embeddings | Uses local Xenova |\n| `PREFLIGHT_RELATED` | Comma-separated related project paths | None |\n| `EMBEDDING_PROVIDER` | `local` or `openai` | `local` |\n| `PROMPT_DISCIPLINE_PROFILE` | `minimal`, `standard`, or `full` | `standard` |\n\nEnvironment variables are **fallbacks** — `.preflight/` config takes precedence when present.\n\n\u003e 💡 **Ready-to-use examples:** Copy [`examples/.preflight/`](examples/.preflight/) into your project root for a working starter config with detailed comments.\n\n---\n\n## Embedding Providers\n\n| Provider | Setup | Speed | Dimensions | Quality | Privacy |\n|----------|-------|-------|-----------|---------|---------|\n| **Local (Xenova)** | Zero config | ~50 events/sec | 384 | Good | 100% local |\n| **OpenAI** | Set `OPENAI_API_KEY` | ~200 events/sec | 1536 | Excellent | API call |\n\nFirst 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.\n\n---\n\n## Architecture\n\n```mermaid\nflowchart TB\n    CC[Claude Code] \u003c--\u003e|MCP Protocol| PS[preflight server]\n    \n    PS --\u003e PC[✈️ Preflight Core]\n    PS --\u003e DT[🎯 Discipline Tools]\n    PS --\u003e TL[🔍 Timeline Tools]\n    PS --\u003e AN[📊 Analysis Tools]\n    PS --\u003e VR[✅ Verify Tools]\n\n    PC --\u003e TE[Triage Engine]\n    DT --\u003e PL[Pattern Learning]\n    TL --\u003e LDB[(LanceDB\\nper-project)]\n    AN --\u003e SCE[Scorecard Engine]\n\n    TE -.-\u003e CFG[\".preflight/\\nconfig.yml\\ntriage.yml\\ncontracts/\"]\n    LDB --\u003e SP[Session Parser]\n    SP --\u003e JSONL[\"~/.claude/projects/\\n(session JSONL files)\"]\n\n    style CC fill:#264653,color:#fff\n    style PS fill:#2a9d8f,color:#fff\n    style PC fill:#e76f51,color:#fff\n    style DT fill:#e9c46a,color:#000\n    style TL fill:#457b9d,color:#fff\n    style AN fill:#6a4c93,color:#fff\n    style VR fill:#2d6a4f,color:#fff\n    style LDB fill:#1d3557,color:#fff\n```\n\n### Per-Project Data Layout\n\n```\n~/.preflight/\n├── config.json                           # Global config (embedding provider, indexed projects)\n└── projects/\n    ├── index.json                        # Registry: path → { hash, onboarded_at }\n    ├── a1b2c3d4e5f6/                     # SHA-256(project_path)[:12]\n    │   ├── timeline.lance/               # LanceDB vector database\n    │   ├── contracts.json                # Extracted API contracts\n    │   ├── meta.json                     # Event count, onboard timestamp\n    │   └── baseline.json                 # Historical scorecard averages\n    └── f6e5d4c3b2a1/\n        └── ...                           # Another project\n```\n\n---\n\n## Troubleshooting\n\n### \"Cannot find module 'vectordb'\" or LanceDB import errors\n\nLanceDB uses native binaries. If you see module resolution errors:\n\n```bash\n# Clean install with native deps rebuilt\nrm -rf node_modules package-lock.json\nnpm install\n\n# If still failing, check your Node version (20+ required)\nnode --version\n```\n\nOn 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`).\n\n### First run is slow (~90MB model download)\n\nThe 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:\n\n```bash\nexport OPENAI_API_KEY=sk-...\nexport EMBEDDING_PROVIDER=openai\n```\n\n### \"OpenAI API key required for openai embedding provider\"\n\nYou set `EMBEDDING_PROVIDER=openai` (or `embeddings.provider: openai` in `.preflight/config.yml`) but didn't provide a key. Either:\n\n- Set `OPENAI_API_KEY` in your environment, or\n- Switch back to local: `export EMBEDDING_PROVIDER=local`\n\n### Tools not showing up in Claude Code\n\n1. Make sure the MCP server is registered. Run `claude mcp list` — you should see `preflight`.\n2. If missing, re-add it:\n   ```bash\n   claude mcp add preflight -- npx tsx /path/to/preflight/src/index.ts\n   ```\n3. Restart Claude Code after adding.\n\n### `CLAUDE_PROJECT_DIR` not set\n\nSome tools (onboarding, session search, contracts) need to know your project root. If they return empty results:\n\n```bash\nclaude mcp add preflight \\\n  -e CLAUDE_PROJECT_DIR=/path/to/your/project \\\n  -- npx tsx /path/to/preflight/src/index.ts\n```\n\nOr set it globally: `export CLAUDE_PROJECT_DIR=/path/to/your/project`\n\n### `.preflight/config.yml` parse errors\n\nIf you see `warning - failed to parse .preflight/config.yml`, your YAML is malformed. Common issues:\n\n- Tabs instead of spaces (YAML requires spaces)\n- Missing quotes around values with special characters\n- Incorrect indentation under `related_projects`\n\nValidate with: `npx yaml-lint .preflight/config.yml` or paste into [yamllint.com](https://www.yamllint.com/).\n\n### No session data found during onboarding\n\n`onboard_project` looks for JSONL files in `~/.claude/projects/\u003cencoded-path\u003e/`. If nothing is found:\n\n- Make sure you've actually used Claude Code on the project (at least one session)\n- Check that `CLAUDE_PROJECT_DIR` matches the exact path Claude Code was opened in\n- The path encoding is URL-style — `/Users/jack/my-app` becomes `%2FUsers%2Fjack%2Fmy-app`\n\n### Ollama embeddings connection refused\n\nIf using Ollama as your embedding provider and getting connection errors:\n\n```bash\n# Make sure Ollama is running\nollama serve\n\n# Pull the embedding model\nollama pull all-minilm\n\n# Verify it works\ncurl http://localhost:11434/api/embed -d '{\"model\":\"all-minilm\",\"input\":\"test\"}'\n```\n\n---\n\n## Contributing\n\nThis project is young and there's plenty to do. Check the [issues](https://github.com/TerminalGravity/preflight/issues) — several are tagged `good first issue`.\n\nPRs welcome. No CLA, no bureaucracy. If it makes the tool better, it gets merged.\n\n### Development\n\n```bash\ngit clone https://github.com/TerminalGravity/preflight.git\ncd preflight\nnpm install\nnpm run build\nnpm test\n```\n\n### Project Structure\n\n```\nsrc/\n├── index.ts                 # MCP server entry point\n├── lib/\n│   ├── triage.ts            # Prompt classification engine\n│   ├── session-parser.ts    # JSONL session file parser\n│   ├── timeline-db.ts       # LanceDB operations\n│   ├── contracts.ts         # Contract extraction \u0026 search\n│   ├── patterns.ts          # Correction pattern learning\n│   ├── config.ts            # .preflight/ config loading\n│   ├── embeddings.ts        # Embedding provider abstraction\n│   ├── state.ts             # Persistent state (logs, patterns)\n│   ├── git.ts               # Git operations\n│   └── files.ts             # File discovery\n└── tools/\n    ├── preflight-check.ts   # Unified entry point\n    ├── generate-scorecard.ts # 12-category scoring + trends\n    └── ...                  # One file per tool\n```\n\n## License\n\nMIT — do whatever you want with it.\n","funding_links":[],"categories":["Plugins","Servers"],"sub_categories":["All Plugins","Typescript"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpreflight-dev%2Fpreflight","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpreflight-dev%2Fpreflight","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpreflight-dev%2Fpreflight/lists"}