Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ A 24-tool MCP server for Claude Code that catches ambiguous instructions before
[![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/)
[![Node 20+](https://img.shields.io/badge/node-20%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)

Expand Down Expand Up @@ -124,6 +124,16 @@ 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.

### Make Claude use preflight automatically

Add preflight rules to your project's `CLAUDE.md` so Claude runs `preflight_check` on every prompt without you asking:

```bash
cp /path/to/preflight/examples/CLAUDE.md your-project/CLAUDE.md
```

See [`examples/CLAUDE.md`](examples/CLAUDE.md) for a ready-to-use template with recommended rules for when to preflight, session hygiene, and skip-lists.

---

## How It Works
Expand Down
31 changes: 31 additions & 0 deletions examples/.preflight/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# `.preflight/` Config Directory

Drop this directory into your project root to configure preflight for your team.

## Quick Setup

```bash
# From the preflight repo:
cp -r examples/.preflight /path/to/your/project/

# Or from your project:
cp -r /path/to/preflight/examples/.preflight .
```

## Files

| File | Purpose |
|------|---------|
| `config.yml` | Main config — profile, related projects, thresholds, embeddings |
| `triage.yml` | Triage rules — which prompts to check, skip, or flag as cross-service |
| `contracts/*.yml` | Manual contract definitions — types, interfaces, routes |

## What to customize first

1. **`config.yml`** — Add your `related_projects` if you work across multiple repos
2. **`triage.yml`** — Add domain-specific keywords to `always_check` (your project's tricky terms)
3. **`contracts/`** — Define shared types that preflight should know about

## Commit it

These files are meant to be committed to your repo so the whole team shares the same preflight config. No secrets in here — API keys go in env vars.
64 changes: 39 additions & 25 deletions examples/.preflight/config.yml
Original file line number Diff line number Diff line change
@@ -1,35 +1,49 @@
# .preflight/config.yml — Drop this in your project root
# Every field is optional. Defaults are sensible — only override what you need.
#
# This is an example config for a typical Next.js + microservices setup.
# Every field is optional — preflight works with sensible defaults out of the box.
# Commit this to your repo so the whole team gets the same preflight behavior.
# Copy this entire .preflight/ directory into your project:
# cp -r examples/.preflight /path/to/your/project/

# Profile controls how much detail preflight returns.
# "minimal" — only flags ambiguous+ prompts, skips clarification detail
# "standard" — balanced (default)
# "full" — maximum detail on every non-trivial prompt
# ──────────────────────────────────────────────────────────
# Profile: controls how verbose preflight's feedback is
# ──────────────────────────────────────────────────────────
# "minimal" — only flags ambiguous+ prompts, skips detail
# "standard" — balanced (default)
# "full" — maximum detail on every non-trivial prompt
profile: standard

# Related projects for cross-service awareness.
# Preflight will search these for shared types, routes, and contracts
# so it can warn you when a change might break a consumer.
related_projects:
- path: /Users/you/code/auth-service
alias: auth
- path: /Users/you/code/billing-api
alias: billing
- path: /Users/you/code/shared-types
alias: types
# ──────────────────────────────────────────────────────────
# Related projects for cross-service awareness
# ──────────────────────────────────────────────────────────
# When you reference code that lives in another repo (e.g. a shared auth
# service), preflight can search that project's types, routes, and schemas
# to give you relevant context automatically.
#
# related_projects:
# - path: /Users/you/code/auth-service
# alias: auth
# - path: /Users/you/code/shared-types
# alias: types

# Behavioral thresholds — tune these to your workflow
# ──────────────────────────────────────────────────────────
# Behavioral thresholds
# ──────────────────────────────────────────────────────────
thresholds:
session_stale_minutes: 30 # Warn if no activity for this long
max_tool_calls_before_checkpoint: 100 # Suggest a checkpoint after N tool calls
correction_pattern_threshold: 3 # Min corrections before flagging a pattern
# Warn if no session activity for this many minutes
session_stale_minutes: 30

# Suggest a checkpoint after this many tool calls
max_tool_calls_before_checkpoint: 100

# Minimum correction count before preflight detects a pattern
# (e.g. "you've corrected JWT handling 3 times — adding a reminder")
correction_pattern_threshold: 3

# Embedding provider for semantic search over session history.
# "local" uses Xenova transformers (no API key needed, runs on CPU).
# "openai" uses text-embedding-3-small (faster, needs OPENAI_API_KEY).
# ──────────────────────────────────────────────────────────
# Embedding configuration (for semantic search over session history)
# ──────────────────────────────────────────────────────────
# "local" uses Xenova transformers — no API key needed, runs on-device.
# "openai" uses OpenAI embeddings — better quality, requires API key.
embeddings:
provider: local
# openai_api_key: sk-... # Uncomment if using openai provider
# openai_api_key: sk-... # Uncomment if using openai provider
70 changes: 35 additions & 35 deletions examples/.preflight/contracts/api.yml
Original file line number Diff line number Diff line change
@@ -1,58 +1,58 @@
# .preflight/contracts/api.yml — Manual contract definitions
#
# Define shared types and interfaces that preflight should know about.
# These supplement auto-extracted contracts from your codebase.
# Manual definitions win on name conflicts with auto-extracted ones.
# Use them for:
# - API contracts that aren't easily auto-detected
# - Shared types across services that need explicit documentation
# - Domain models that drive business logic
#
# Why manual contracts?
# - Document cross-service interfaces that live in docs, not code
# - Define contracts for external APIs your services consume
# - Pin down types that are implicit (e.g., event payloads)
# Manual definitions win on name conflicts with auto-extracted ones.

- name: User
kind: interface
description: Core user model shared across all services
description: Core user model — referenced across auth, billing, and API layers
fields:
- name: id
type: string
required: true
- name: email
type: string
required: true
- name: tier
type: "'free' | 'pro' | 'enterprise'"
- name: role
type: "'admin' | 'member' | 'viewer'"
required: true
- name: createdAt
type: Date
required: true

- name: AuthToken
kind: interface
description: JWT payload structure from auth-service
fields:
- name: userId
type: string
required: true
- name: permissions
type: string[]
required: true
- name: expiresAt
type: number
required: true

- name: WebhookPayload
- name: ApiResponse
kind: interface
description: Standard webhook envelope for inter-service events
description: Standard API response wrapper used by all endpoints
fields:
- name: event
type: string
required: true
- name: timestamp
type: string
- name: success
type: boolean
required: true
- name: data
type: Record<string, unknown>
required: true
- name: source
type: string
required: true
type: T
required: false
- name: error
type: "{ code: string; message: string }"
required: false

# Add your own contracts below. Examples:
#
# - name: OrderStatus
# kind: enum
# description: Order lifecycle states
# values: [pending, confirmed, shipped, delivered, cancelled]
#
# - name: POST /api/webhooks
# kind: route
# description: Incoming webhook handler
# fields:
# - name: event
# type: string
# required: true
# - name: payload
# type: Record<string, unknown>
# required: true
43 changes: 24 additions & 19 deletions examples/.preflight/triage.yml
Original file line number Diff line number Diff line change
@@ -1,45 +1,50 @@
# .preflight/triage.yml — Controls how preflight classifies your prompts
# .preflight/triage.yml — Controls the prompt triage engine
#
# The triage engine routes prompts into categories:
# Triage classifies every prompt into one of four categories:
# TRIVIAL → pass through (commit, format, lint)
# CLEAR → well-specified, no intervention needed
# AMBIGUOUS → needs clarification before proceeding
# MULTI-STEP → complex task, preflight suggests a plan
# CROSS-SERVICE → touches multiple projects, pulls in contracts
# CROSS-SERVICE → touches multiple projects, needs contract context
#
# Customize the keywords below to match your domain.
# Customize the keywords below to match YOUR project's domain.

rules:
# Prompts containing these words are always flagged as AMBIGUOUS.
# Add domain-specific terms that tend to produce vague prompts.
# ── Always check ──────────────────────────────────────
# Prompts containing these words are always flagged as AMBIGUOUS
# (at minimum) so preflight asks for clarification.
# Add your project's tricky/overloaded terms here.
always_check:
- rewards
- permissions
- migration
- schema
- pricing # example: your billing domain
- onboarding # example: multi-step user flows
# - billing # Uncomment for fintech projects
# - deployment # Uncomment if deploys are complex

# Prompts containing these words skip checks entirely (TRIVIAL).
# These are safe, mechanical tasks that don't need guardrails.
# ── Skip (trivial) ───────────────────────────────────
# Prompts matching these pass through without intervention.
# These are low-risk, well-understood commands.
skip:
- commit
- format
- lint
- prettier
- "git push"
- "git status"
- "run tests"

# Prompts containing these words trigger CROSS-SERVICE classification.
# Preflight will search related_projects for relevant types and routes.
# ── Cross-service keywords ───────────────────────────
# Prompts containing these trigger cross-project search,
# pulling in types/routes/schemas from related_projects.
cross_service_keywords:
- auth
- notification
- event
- webhook
- billing # matches the related_project alias
# - payment # Uncomment if payments are a separate service
# - queue # Uncomment for message queue integrations

# How aggressively to classify prompts.
# "relaxed" — more prompts pass as clear (experienced users)
# ── Strictness ────────────────────────────────────────
# How aggressively to classify prompts:
# "relaxed" — more prompts pass as clear (fewer interruptions)
# "standard" — balanced (default)
# "strict" — more prompts flagged as ambiguous (new teams, complex codebases)
# "strict" — more prompts flagged as ambiguous (safer, more verbose)
strictness: standard
30 changes: 30 additions & 0 deletions examples/CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# CLAUDE.md — Preflight Integration Example
#
# Drop this into your project's CLAUDE.md (or .claude/CLAUDE.md) to make
# Claude Code automatically use preflight tools during your sessions.
# Customize the rules below to match your workflow.

## Preflight Rules

Before starting any non-trivial task, run `preflight_check` with my prompt. This catches vague instructions before they waste tokens on wrong→fix cycles.

### When to use preflight tools:

- **Every prompt**: `preflight_check` triages automatically — let it decide what's needed
- **Before multi-file changes**: Run `scope_work` to get a phased plan
- **Before sub-agent tasks**: Use `enrich_agent_task` to add context
- **After making a mistake**: Use `log_correction` so preflight learns the pattern
- **Before ending a session**: Run `checkpoint` to save state for next time
- **When I say "fix it" or "do the others"**: Use `sharpen_followup` to resolve what I actually mean

### Session hygiene:

- Run `check_session_health` if we've been going for a while without committing
- If I ask about something we did before, use `search_history` to find it
- Before declaring a task done, run `verify_completion` (type check + tests)

### Don't preflight these:

- Simple git commands (commit, push, status)
- Formatting / linting
- Reading files I explicitly named
16 changes: 16 additions & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,22 @@ The `.preflight/` directory contains example configuration files you can copy in
└── api.yml # Manual contract definitions for cross-service types
```

## `CLAUDE.md` Integration

The `CLAUDE.md` file tells Claude Code how to behave in your project. Adding preflight rules here makes Claude automatically use preflight tools without you having to ask.

```bash
# Copy the example into your project:
cp /path/to/preflight/examples/CLAUDE.md my-project/CLAUDE.md

# Or append to your existing CLAUDE.md:
cat /path/to/preflight/examples/CLAUDE.md >> my-project/CLAUDE.md
```

This is the **recommended way** to integrate preflight — once it's in your `CLAUDE.md`, every session automatically runs `preflight_check` on your prompts.

---

### Quick setup

```bash
Expand Down
40 changes: 40 additions & 0 deletions src/cli/init.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,46 @@ import { join, dirname } from "node:path";
import { existsSync } from "node:fs";
import { fileURLToPath } from "node:url";

// Handle --help and --version before launching interactive wizard
const args = process.argv.slice(2);

if (args.includes("--help") || args.includes("-h")) {
console.log(`
✈️ preflight-dev — MCP server for Claude Code prompt discipline

Usage:
preflight-dev Interactive setup wizard (creates .mcp.json)
preflight-dev --help Show this help message
preflight-dev --version Show version

The wizard will:
1. Ask you to choose a profile (minimal / standard / full)
2. Optionally create a .preflight/ config directory
3. Write an .mcp.json so Claude Code auto-connects to preflight

After setup, restart Claude Code and preflight tools will appear.

Profiles:
minimal 4 tools — clarify_intent, check_session_health, session_stats, prompt_score
standard 16 tools — all prompt discipline + session_stats + prompt_score
full 20 tools — everything + timeline/vector search (needs LanceDB)

More info: https://github.com/TerminalGravity/preflight
`);
process.exit(0);
}

if (args.includes("--version") || args.includes("-v")) {
const pkgPath = join(dirname(fileURLToPath(import.meta.url)), "../../package.json");
try {
const pkg = JSON.parse(await readFile(pkgPath, "utf-8"));
console.log(`preflight-dev v${pkg.version}`);
} catch {
console.log("preflight-dev (version unknown)");
}
process.exit(0);
}

const rl = createInterface({ input: process.stdin, output: process.stdout });

function ask(question: string): Promise<string> {
Expand Down
Loading
Loading