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
50 changes: 50 additions & 0 deletions src/cli/init.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,46 @@ async function createPreflightConfig(): Promise<void> {
}
}

/** Inject preflight rules into CLAUDE.md */
async function injectClaudeRules(mode: "strict" | "relaxed"): Promise<void> {
const claudePath = join(process.cwd(), "CLAUDE.md");
const rulesDir = join(process.cwd(), ".claude");
const rulesPath = join(rulesDir, "preflight-rules.md");

try {
// Get the template
const currentFile = fileURLToPath(import.meta.url);
const srcDir = dirname(dirname(currentFile));
const templatesDir = join(srcDir, "templates");
const templateFile = join(templatesDir, `claude-rules-${mode}.md`);
const rules = await readFile(templateFile, "utf-8");

// Write rules to .claude/preflight-rules.md
await mkdir(rulesDir, { recursive: true });
await writeFile(rulesPath, rules);
console.log(`✅ Created .claude/preflight-rules.md (${mode} mode)`);

// Check if CLAUDE.md exists and already imports the rules
const importLine = `@.claude/preflight-rules.md`;
let claudeContent = "";
try {
claudeContent = await readFile(claudePath, "utf-8");
} catch { /* file doesn't exist yet */ }

if (claudeContent.includes(importLine)) {
console.log(" CLAUDE.md already imports preflight rules\n");
return;
}

// Append import to CLAUDE.md
const separator = claudeContent.length > 0 ? "\n\n" : "";
await writeFile(claudePath, claudeContent + separator + importLine + "\n");
console.log(" Added import to CLAUDE.md\n");
} catch (error) {
console.error(`❌ Failed to inject CLAUDE.md rules: ${error}\n`);
}
}

interface McpConfig {
mcpServers: Record<string, {
command: string;
Expand Down Expand Up @@ -86,6 +126,16 @@ async function main(): Promise<void> {
await createPreflightConfig();
}

// Ask about CLAUDE.md rules
console.log("Preflight can inject rules into CLAUDE.md so Claude Code automatically");
console.log("uses preflight tools at the right moments.\n");

const rulesChoice = await ask("Add preflight rules to CLAUDE.md? [strict/relaxed/N] (default: N): ");
const rulesMode = rulesChoice.trim().toLowerCase();
if (rulesMode === "strict" || rulesMode === "relaxed") {
await injectClaudeRules(rulesMode);
}

const env: Record<string, string> = {
PROMPT_DISCIPLINE_PROFILE: profile,
};
Expand Down
9 changes: 9 additions & 0 deletions src/templates/claude-rules-relaxed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Preflight Rules (Relaxed Mode)

## Recommended Practices

- Call `preflight_check` before large or complex tasks spanning multiple files.
- Use `clarify_intent` when a prompt seems vague or underspecified.
- Use `verify_completion` before wrapping up significant tasks.
- Call `checkpoint` periodically during long sessions to save progress.
- Use `what_changed` to review modifications before committing.
25 changes: 25 additions & 0 deletions src/templates/claude-rules-strict.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Preflight Rules (Strict Mode)

## Before Starting Work

- **ALWAYS** call `preflight_check` before any multi-file task or task involving more than 3 tool calls.
- **ALWAYS** call `clarify_intent` when a prompt is ambiguous or could be interpreted multiple ways.
- **ALWAYS** call `scope_work` before tasks that touch more than 2 files.

## During Work

- Call `checkpoint` every 100 tool calls or when completing a logical milestone.
- Call `session_health` if you notice degraded performance or context confusion.
- Call `search_history` before re-implementing something that may already exist in the session.

## Before Completing Work

- **ALWAYS** call `verify_completion` before declaring a task done.
- **ALWAYS** call `prompt_score` on your own summary to ensure clarity.
- Call `generate_scorecard` at the end of significant work sessions.

## Error Handling

- If a task fails, call `log_correction` to record the pattern.
- Call `what_changed` to review your modifications before committing.
- Use `token_audit` if the session feels expensive or bloated.
39 changes: 39 additions & 0 deletions tests/cli/claude-rules.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { describe, it, expect } from "vitest";
import { readFile } from "node:fs/promises";
import { join, dirname } from "node:path";
import { fileURLToPath } from "node:url";

const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const templatesDir = join(__dirname, "../../src/templates");

describe("CLAUDE.md rule templates", () => {
it("strict template exists and contains required rules", async () => {
const content = await readFile(join(templatesDir, "claude-rules-strict.md"), "utf-8");
expect(content).toContain("preflight_check");
expect(content).toContain("verify_completion");
expect(content).toContain("clarify_intent");
expect(content).toContain("checkpoint");
expect(content).toContain("Strict Mode");
});

it("relaxed template exists and is shorter than strict", async () => {
const strict = await readFile(join(templatesDir, "claude-rules-strict.md"), "utf-8");
const relaxed = await readFile(join(templatesDir, "claude-rules-relaxed.md"), "utf-8");
expect(relaxed.length).toBeLessThan(strict.length);
expect(relaxed).toContain("preflight_check");
expect(relaxed).toContain("Relaxed Mode");
});

it("strict template has ALWAYS keywords for critical rules", async () => {
const content = await readFile(join(templatesDir, "claude-rules-strict.md"), "utf-8");
const alwaysCount = (content.match(/ALWAYS/g) || []).length;
expect(alwaysCount).toBeGreaterThanOrEqual(4);
});

it("relaxed template uses softer language", async () => {
const content = await readFile(join(templatesDir, "claude-rules-relaxed.md"), "utf-8");
expect(content).not.toContain("**ALWAYS**");
expect(content).toContain("Recommended");
});
});
Loading