flight-rules 0.5.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/README.md +270 -0
  2. package/dist/commands/adapter.d.ts +35 -0
  3. package/dist/commands/adapter.js +308 -0
  4. package/dist/commands/init.d.ts +1 -0
  5. package/dist/commands/init.js +197 -0
  6. package/dist/commands/upgrade.d.ts +1 -0
  7. package/dist/commands/upgrade.js +255 -0
  8. package/dist/index.d.ts +2 -0
  9. package/dist/index.js +83 -0
  10. package/dist/utils/files.d.ts +75 -0
  11. package/dist/utils/files.js +245 -0
  12. package/dist/utils/interactive.d.ts +5 -0
  13. package/dist/utils/interactive.js +7 -0
  14. package/package.json +52 -0
  15. package/payload/.editorconfig +15 -0
  16. package/payload/AGENTS.md +247 -0
  17. package/payload/commands/dev-session.end.md +79 -0
  18. package/payload/commands/dev-session.start.md +54 -0
  19. package/payload/commands/impl.create.md +178 -0
  20. package/payload/commands/impl.outline.md +120 -0
  21. package/payload/commands/prd.clarify.md +139 -0
  22. package/payload/commands/prd.create.md +154 -0
  23. package/payload/commands/test.add.md +73 -0
  24. package/payload/commands/test.assess-current.md +75 -0
  25. package/payload/doc-templates/critical-learnings.md +21 -0
  26. package/payload/doc-templates/implementation/overview.md +27 -0
  27. package/payload/doc-templates/prd.md +49 -0
  28. package/payload/doc-templates/progress.md +19 -0
  29. package/payload/doc-templates/session-log.md +62 -0
  30. package/payload/doc-templates/tech-stack.md +101 -0
  31. package/payload/prompts/.gitkeep +0 -0
  32. package/payload/prompts/implementation/README.md +26 -0
  33. package/payload/prompts/implementation/plan-review.md +80 -0
  34. package/payload/prompts/prd/README.md +46 -0
  35. package/payload/prompts/prd/creation-conversational.md +46 -0
package/README.md ADDED
@@ -0,0 +1,270 @@
1
+ # Flight Rules
2
+
3
+ > **Early Development**: This project is in active development (v0.x). APIs and conventions may change between versions. Install with the `dev` tag.
4
+
5
+ An opinionated framework for AI-assisted software development. Provides conventions for docs, implementation specs, and coding session workflows that both humans and agents can navigate.
6
+
7
+ The goal:
8
+ Any agent (or person) should be able to open a project that uses Flight Rules and understand:
9
+
10
+ - What the project is trying to do
11
+ - How the implementation is structured
12
+ - What has already been done
13
+ - What should happen next
14
+ - What we've learned along the way
15
+
16
+ ---
17
+
18
+ ## Quick Start
19
+
20
+ Install the CLI globally:
21
+
22
+ ```bash
23
+ npm install -g flight-rules@dev
24
+ ```
25
+
26
+ Then initialize Flight Rules in any project:
27
+
28
+ ```bash
29
+ cd your-project
30
+ flight-rules init
31
+ ```
32
+
33
+ Or run directly without installing:
34
+
35
+ ```bash
36
+ npx flight-rules@dev init
37
+ ```
38
+
39
+ The `init` command will:
40
+ - Create a `.flight-rules/` directory with framework files
41
+ - Optionally create a `docs/` directory with project documentation from templates
42
+ - Optionally generate agent adapters (AGENTS.md for Cursor, CLAUDE.md for Claude Code, etc.)
43
+
44
+ ---
45
+
46
+ ## How It Works
47
+
48
+ Flight Rules gives your project a structured documentation system that AI agents (and humans) can navigate consistently.
49
+
50
+ ### Project Structure
51
+
52
+ | Location | Purpose |
53
+ |----------|---------|
54
+ | `.flight-rules/` | Framework files (replaced on upgrade) |
55
+ | `docs/` | Your project documentation (new templates added on upgrade, existing files preserved) |
56
+
57
+ **Inside `.flight-rules/`:**
58
+
59
+ | Directory | Purpose |
60
+ |-----------|---------|
61
+ | `AGENTS.md` | Guidelines for AI agents working on your project |
62
+ | `doc-templates/` | Templates for creating project docs |
63
+ | `commands/` | Workflow commands (start/end coding session) |
64
+ | `prompts/` | Reusable prompt templates |
65
+
66
+ ### Implementation Specs (Single Source of Truth)
67
+
68
+ Implementation specs live in `docs/implementation/` and follow a three-level hierarchy:
69
+
70
+ | Level | Name | Example | Description |
71
+ |-------|------|---------|-------------|
72
+ | 1 | **Area** | `1-foundation-shell/` | A major implementation area |
73
+ | 2 | **Task Group** | `1.4-application-shell.md` | A file containing related tasks |
74
+ | 3 | **Task** | `1.4.1. Routing Structure` | A specific unit of work with status |
75
+
76
+ **Key principle:** The spec is the single source of truth. If code diverges from spec, update the spec.
77
+
78
+ ### Coding Sessions
79
+
80
+ Flight Rules distinguishes between:
81
+
82
+ - **Ad-hoc requests** — "Change function X in file Y"
83
+ - **Structured sessions** — Follow a start/end ritual with documentation
84
+
85
+ Two core flows:
86
+
87
+ - **`dev-session.start`** — Review context, set goals, create a plan
88
+ - **`dev-session.end`** — Summarize work, update progress, capture learnings
89
+
90
+ Agents don't start these flows on their own; you explicitly invoke them.
91
+
92
+ ### Versioning
93
+
94
+ Each project tracks which Flight Rules version it uses:
95
+
96
+ ```
97
+ flight_rules_version: 0.1.2
98
+ ```
99
+
100
+ This appears in `.flight-rules/AGENTS.md` and helps coordinate upgrades.
101
+
102
+ ---
103
+
104
+ ## What Gets Installed
105
+
106
+ When you run `flight-rules init`, you get:
107
+
108
+ ```text
109
+ your-project/
110
+ ├── AGENTS.md # (Optional) Adapter for Cursor - points to .flight-rules/
111
+ ├── docs/ # YOUR content (new templates added on upgrade)
112
+ │ ├── prd.md
113
+ │ ├── progress.md
114
+ │ ├── critical-learnings.md
115
+ │ ├── tech-stack.md
116
+ │ ├── implementation/
117
+ │ │ └── overview.md
118
+ │ └── session_logs/
119
+ └── .flight-rules/ # Framework files (can be replaced on upgrade)
120
+ ├── AGENTS.md # Agent guidelines
121
+ ├── doc-templates/ # Templates for creating your docs
122
+ │ ├── prd.md
123
+ │ ├── progress.md
124
+ │ ├── critical-learnings.md
125
+ │ ├── tech-stack.md
126
+ │ ├── session-log.md
127
+ │ └── implementation/
128
+ │ └── overview.md
129
+ ├── commands/
130
+ │ ├── dev-session.start.md
131
+ │ ├── dev-session.end.md
132
+ │ ├── test.add.md
133
+ │ └── test.assess-current.md
134
+ └── prompts/ # Reusable prompt templates
135
+ ```
136
+
137
+ ---
138
+
139
+ ## Day-to-Day Usage
140
+
141
+ ### When you open a project
142
+
143
+ 1. Agents should read `.flight-rules/AGENTS.md`
144
+ 2. Skim `docs/prd.md` and `docs/implementation/overview.md`
145
+ 3. Check `docs/progress.md` for recent work
146
+
147
+ ### For structured work
148
+
149
+ - **"start coding session"** — Sets goals, creates a plan
150
+ - **"end coding session"** — Summarizes work, updates docs
151
+
152
+ ### When making changes
153
+
154
+ - Identify relevant Area, Task Group, and Task
155
+ - Update Tasks when reality diverges from plan
156
+ - Keep `Status:` fields current
157
+
158
+ ---
159
+
160
+ ## CLI Commands
161
+
162
+ | Command | Description |
163
+ |---------|-------------|
164
+ | `flight-rules init` | Install Flight Rules into a project (interactive setup wizard) |
165
+ | `flight-rules upgrade` | Upgrade Flight Rules in an existing project (preserves your docs) |
166
+ | `flight-rules adapter` | Generate agent-specific adapters (`--cursor`, `--claude`) |
167
+
168
+ ---
169
+
170
+ ## Upgrading
171
+
172
+ Upgrade Flight Rules while preserving your content:
173
+
174
+ ```bash
175
+ flight-rules upgrade
176
+ ```
177
+
178
+ **What gets replaced:**
179
+ - The `.flight-rules/` directory (framework files)
180
+
181
+ **What gets added (without overwriting):**
182
+ - New templates are added to `docs/` if they don't already exist
183
+ - Your existing doc files are never modified
184
+
185
+ ---
186
+
187
+ ## Manual Installation
188
+
189
+ If you prefer not to use the CLI:
190
+
191
+ 1. Clone this repo:
192
+
193
+ ```bash
194
+ git clone https://github.com/ryanpacker/flight-rules.git ~/flight-rules
195
+ ```
196
+
197
+ 2. Copy the payload into your project:
198
+
199
+ ```bash
200
+ cp -R ~/flight-rules/payload /path/to/your/project/.flight-rules
201
+ ```
202
+
203
+ 3. Create a `docs/` directory and copy templates from `.flight-rules/doc-templates/` to customize them.
204
+
205
+ ---
206
+
207
+ ## Future Directions
208
+
209
+ - **Skills/MCP integration** — Conventions for documenting tools and workflows
210
+ - **Hosted planning systems** — Potential integration with Linear, etc.
211
+ - **v1.0 stability** — Stabilizing APIs and conventions for a production-ready release
212
+
213
+ Current focus:
214
+
215
+ - A solid, Markdown-based structure
216
+ - Clear expectations for agents
217
+ - CLI tooling for easy installation and upgrades
218
+
219
+ ---
220
+
221
+ ## Contributing
222
+
223
+ This repo is an npm package with the following structure:
224
+
225
+ | Path | Purpose |
226
+ |------|---------|
227
+ | `src/` | CLI source code (TypeScript) |
228
+ | `dist/` | Compiled CLI (committed for GitHub installs) |
229
+ | `payload/` | The content delivered to projects as `.flight-rules/` |
230
+ | `scripts/` | Build and release utilities |
231
+
232
+ ### Development
233
+
234
+ ```bash
235
+ git clone https://github.com/ryanpacker/flight-rules.git
236
+ cd flight-rules
237
+ npm install
238
+ npm run build
239
+ ```
240
+
241
+ ### Testing
242
+
243
+ The project uses [Vitest](https://vitest.dev/) for testing with ~93% code coverage.
244
+
245
+ ```bash
246
+ npm test # Run tests once
247
+ npm run test:watch # Watch mode for development
248
+ npm run test:coverage # Generate coverage report
249
+ ```
250
+
251
+ Tests are located in `tests/` and mirror the `src/` structure:
252
+
253
+ | Test File | Coverage |
254
+ |-----------|----------|
255
+ | `tests/utils/files.test.ts` | 100% |
256
+ | `tests/commands/init.test.ts` | 98.5% |
257
+ | `tests/commands/upgrade.test.ts` | 100% |
258
+ | `tests/commands/adapter.test.ts` | 79% |
259
+
260
+ ### Releasing
261
+
262
+ ```bash
263
+ npm version patch # or minor/major
264
+ git push && git push --tags
265
+ npm publish --tag dev
266
+ ```
267
+
268
+ This automatically builds, syncs the version to `payload/AGENTS.md`, creates a tagged commit, and publishes to npm.
269
+
270
+ > **Note:** Until v1.0, all releases use the `dev` tag. Users install with `npm install -g flight-rules@dev`.
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Copy command files to a destination directory with conflict handling
3
+ */
4
+ export declare function copyCommandsWithConflictHandling(sourceDir: string, destDir: string, skipPrompts?: boolean): Promise<{
5
+ copied: string[];
6
+ skipped: string[];
7
+ }>;
8
+ /**
9
+ * Setup Cursor-specific directories and commands
10
+ */
11
+ export declare function setupCursorCommands(cwd: string, sourceCommandsDir: string, skipPrompts?: boolean): Promise<{
12
+ copied: string[];
13
+ skipped: string[];
14
+ }>;
15
+ /**
16
+ * Check if Cursor adapter is installed (has .cursor/commands/)
17
+ */
18
+ export declare function isCursorAdapterInstalled(cwd: string): boolean;
19
+ /**
20
+ * Setup Claude Code-specific directories and commands
21
+ */
22
+ export declare function setupClaudeCommands(cwd: string, sourceCommandsDir: string, skipPrompts?: boolean): Promise<{
23
+ copied: string[];
24
+ skipped: string[];
25
+ }>;
26
+ /**
27
+ * Check if Claude Code adapter is installed (has .claude/commands/)
28
+ */
29
+ export declare function isClaudeAdapterInstalled(cwd: string): boolean;
30
+ /**
31
+ * Check if a specific adapter file exists
32
+ */
33
+ export declare function isAdapterInstalled(cwd: string, adapterKey: string): boolean;
34
+ export declare function adapter(args: string[]): Promise<void>;
35
+ export declare function generateAdapters(adapterNames: string[], sourceCommandsDir?: string, interactive?: boolean): Promise<void>;
@@ -0,0 +1,308 @@
1
+ import * as p from '@clack/prompts';
2
+ import pc from 'picocolors';
3
+ import { writeFileSync, existsSync, readdirSync, cpSync } from 'fs';
4
+ import { join } from 'path';
5
+ import { ensureDir, getFlightRulesDir } from '../utils/files.js';
6
+ import { isInteractive } from '../utils/interactive.js';
7
+ const ADAPTERS = {
8
+ cursor: {
9
+ name: 'Cursor',
10
+ filename: 'AGENTS.md',
11
+ title: 'Flight Rules – Cursor Adapter',
12
+ description: 'This file is placed at the project root as `AGENTS.md` for Cursor compatibility.',
13
+ hasNativeCommands: true,
14
+ commandsDirectory: '.cursor/commands',
15
+ },
16
+ claude: {
17
+ name: 'Claude Code',
18
+ filename: 'CLAUDE.md',
19
+ title: 'Flight Rules – Claude Code Adapter',
20
+ description: 'This file is placed at the project root as `CLAUDE.md` for Claude Code compatibility.',
21
+ hasNativeCommands: true,
22
+ commandsDirectory: '.claude/commands',
23
+ },
24
+ };
25
+ function generateAdapterContent(config) {
26
+ // Adapter-specific command instructions
27
+ const commandLocation = config.hasNativeCommands && config.commandsDirectory
28
+ ? `\`${config.commandsDirectory}/\` (as slash commands)`
29
+ : `\`.flight-rules/commands/\``;
30
+ const commandInstructions = config.hasNativeCommands
31
+ ? `Use the \`/dev-session.start\` and \`/dev-session.end\` slash commands.`
32
+ : `When the user says "start coding session" or "end coding session", follow the instructions in \`.flight-rules/commands/\`.`;
33
+ return `# ${config.title}
34
+
35
+ ${config.description}
36
+
37
+ ---
38
+
39
+ **This project uses Flight Rules.**
40
+
41
+ Agent guidelines and workflows live in \`.flight-rules/\`. Project documentation lives in \`docs/\`.
42
+
43
+ ## Quick Reference
44
+
45
+ | What | Where |
46
+ |------|-------|
47
+ | Agent Guidelines | \`.flight-rules/AGENTS.md\` |
48
+ | PRD | \`docs/prd.md\` |
49
+ | Implementation Specs | \`docs/implementation/\` |
50
+ | Progress Log | \`docs/progress.md\` |
51
+ | Tech Stack | \`docs/tech-stack.md\` |
52
+ | Session Commands | ${commandLocation} |
53
+
54
+ ## For Agents
55
+
56
+ Please read \`.flight-rules/AGENTS.md\` for complete guidelines on:
57
+ - Project structure
58
+ - Implementation specs
59
+ - Coding sessions
60
+ - How to work with this system
61
+
62
+ ${commandInstructions}
63
+ `;
64
+ }
65
+ /**
66
+ * Copy command files to a destination directory with conflict handling
67
+ */
68
+ export async function copyCommandsWithConflictHandling(sourceDir, destDir, skipPrompts = false) {
69
+ const copied = [];
70
+ const skipped = [];
71
+ if (!existsSync(sourceDir)) {
72
+ return { copied, skipped };
73
+ }
74
+ const files = readdirSync(sourceDir).filter(f => f.endsWith('.md'));
75
+ let batchAction = null;
76
+ for (const file of files) {
77
+ const srcPath = join(sourceDir, file);
78
+ const destPath = join(destDir, file);
79
+ if (existsSync(destPath)) {
80
+ // File already exists - need to handle conflict
81
+ if (skipPrompts) {
82
+ // During upgrade with no prompts, replace by default
83
+ cpSync(srcPath, destPath);
84
+ copied.push(file);
85
+ continue;
86
+ }
87
+ if (batchAction === 'replace_all') {
88
+ cpSync(srcPath, destPath);
89
+ copied.push(file);
90
+ continue;
91
+ }
92
+ else if (batchAction === 'skip_all') {
93
+ skipped.push(file);
94
+ continue;
95
+ }
96
+ // Prompt for this specific file
97
+ const action = await promptForConflict(file, files.length > 1);
98
+ if (action === 'replace_all') {
99
+ batchAction = 'replace_all';
100
+ cpSync(srcPath, destPath);
101
+ copied.push(file);
102
+ }
103
+ else if (action === 'skip_all') {
104
+ batchAction = 'skip_all';
105
+ skipped.push(file);
106
+ }
107
+ else if (action === 'replace') {
108
+ cpSync(srcPath, destPath);
109
+ copied.push(file);
110
+ }
111
+ else {
112
+ skipped.push(file);
113
+ }
114
+ }
115
+ else {
116
+ // No conflict - just copy
117
+ cpSync(srcPath, destPath);
118
+ copied.push(file);
119
+ }
120
+ }
121
+ return { copied, skipped };
122
+ }
123
+ /**
124
+ * Prompt user for how to handle a file conflict
125
+ */
126
+ async function promptForConflict(filename, showBatchOptions) {
127
+ const options = [
128
+ { value: 'replace', label: 'Replace', hint: 'overwrite with Flight Rules version' },
129
+ { value: 'skip', label: 'Skip', hint: 'keep existing file' },
130
+ ];
131
+ if (showBatchOptions) {
132
+ options.push({ value: 'replace_all', label: 'Replace all', hint: 'replace this and all remaining conflicts' }, { value: 'skip_all', label: 'Skip all', hint: 'skip this and all remaining conflicts' });
133
+ }
134
+ const action = await p.select({
135
+ message: `${pc.cyan(filename)} already exists. What would you like to do?`,
136
+ options,
137
+ });
138
+ if (p.isCancel(action)) {
139
+ return 'skip';
140
+ }
141
+ return action;
142
+ }
143
+ /**
144
+ * Setup Cursor-specific directories and commands
145
+ */
146
+ export async function setupCursorCommands(cwd, sourceCommandsDir, skipPrompts = false) {
147
+ const cursorDir = join(cwd, '.cursor');
148
+ const cursorCommandsDir = join(cursorDir, 'commands');
149
+ // Create directories
150
+ ensureDir(cursorDir);
151
+ ensureDir(cursorCommandsDir);
152
+ // Copy commands with conflict handling
153
+ return copyCommandsWithConflictHandling(sourceCommandsDir, cursorCommandsDir, skipPrompts);
154
+ }
155
+ /**
156
+ * Check if Cursor adapter is installed (has .cursor/commands/)
157
+ */
158
+ export function isCursorAdapterInstalled(cwd) {
159
+ return existsSync(join(cwd, '.cursor', 'commands'));
160
+ }
161
+ /**
162
+ * Setup Claude Code-specific directories and commands
163
+ */
164
+ export async function setupClaudeCommands(cwd, sourceCommandsDir, skipPrompts = false) {
165
+ const claudeDir = join(cwd, '.claude');
166
+ const claudeCommandsDir = join(claudeDir, 'commands');
167
+ // Create directories
168
+ ensureDir(claudeDir);
169
+ ensureDir(claudeCommandsDir);
170
+ // Copy commands with conflict handling
171
+ return copyCommandsWithConflictHandling(sourceCommandsDir, claudeCommandsDir, skipPrompts);
172
+ }
173
+ /**
174
+ * Check if Claude Code adapter is installed (has .claude/commands/)
175
+ */
176
+ export function isClaudeAdapterInstalled(cwd) {
177
+ return existsSync(join(cwd, '.claude', 'commands'));
178
+ }
179
+ /**
180
+ * Check if a specific adapter file exists
181
+ */
182
+ export function isAdapterInstalled(cwd, adapterKey) {
183
+ const config = ADAPTERS[adapterKey];
184
+ if (!config)
185
+ return false;
186
+ if (adapterKey === 'cursor') {
187
+ // For Cursor, check both AGENTS.md and .cursor/commands/
188
+ return existsSync(join(cwd, config.filename)) || isCursorAdapterInstalled(cwd);
189
+ }
190
+ if (adapterKey === 'claude') {
191
+ // For Claude, check both CLAUDE.md and .claude/commands/
192
+ return existsSync(join(cwd, config.filename)) || isClaudeAdapterInstalled(cwd);
193
+ }
194
+ return existsSync(join(cwd, config.filename));
195
+ }
196
+ export async function adapter(args) {
197
+ const cwd = process.cwd();
198
+ const interactive = isInteractive();
199
+ // Parse arguments
200
+ let selectedAdapters = [];
201
+ if (args.includes('--all')) {
202
+ selectedAdapters = Object.keys(ADAPTERS);
203
+ }
204
+ else {
205
+ for (const arg of args) {
206
+ const adapterName = arg.replace('--', '');
207
+ if (ADAPTERS[adapterName]) {
208
+ selectedAdapters.push(adapterName);
209
+ }
210
+ }
211
+ }
212
+ // If no adapters specified via args, prompt for selection (or error in non-interactive)
213
+ if (selectedAdapters.length === 0) {
214
+ if (!interactive) {
215
+ // Non-interactive: require explicit adapter flags
216
+ p.log.error('No adapters specified. In non-interactive mode, use:');
217
+ console.log(' flight-rules adapter --cursor');
218
+ console.log(' flight-rules adapter --claude');
219
+ console.log(' flight-rules adapter --all');
220
+ process.exit(1);
221
+ }
222
+ const selection = await p.multiselect({
223
+ message: 'Which adapters would you like to generate?',
224
+ options: Object.entries(ADAPTERS).map(([key, config]) => ({
225
+ value: key,
226
+ label: config.commandsDirectory
227
+ ? `${config.name} (${config.filename} + ${config.commandsDirectory}/)`
228
+ : `${config.name} (${config.filename})`,
229
+ hint: key === 'cursor' ? 'recommended' : undefined,
230
+ })),
231
+ initialValues: ['cursor'],
232
+ });
233
+ if (p.isCancel(selection)) {
234
+ p.log.info('Cancelled.');
235
+ return;
236
+ }
237
+ selectedAdapters = selection;
238
+ }
239
+ await generateAdapters(selectedAdapters, undefined, interactive);
240
+ }
241
+ export async function generateAdapters(adapterNames, sourceCommandsDir, interactive = true) {
242
+ const cwd = process.cwd();
243
+ // Default to .flight-rules/commands if no source specified
244
+ const commandsDir = sourceCommandsDir ?? join(getFlightRulesDir(cwd), 'commands');
245
+ for (const name of adapterNames) {
246
+ const config = ADAPTERS[name];
247
+ if (!config)
248
+ continue;
249
+ const filePath = join(cwd, config.filename);
250
+ let adapterFileWritten = false;
251
+ // Check if file already exists
252
+ if (existsSync(filePath)) {
253
+ if (interactive) {
254
+ const overwrite = await p.confirm({
255
+ message: `${config.filename} already exists. Overwrite?`,
256
+ initialValue: false,
257
+ });
258
+ if (p.isCancel(overwrite) || !overwrite) {
259
+ p.log.info(`Skipped ${config.filename}`);
260
+ // Don't continue - still need to set up commands directory
261
+ }
262
+ else {
263
+ const content = generateAdapterContent(config);
264
+ writeFileSync(filePath, content, 'utf-8');
265
+ p.log.success(`Updated ${pc.cyan(config.filename)} for ${config.name}`);
266
+ adapterFileWritten = true;
267
+ }
268
+ }
269
+ else {
270
+ // Non-interactive: skip overwrite (safe default)
271
+ p.log.info(`Skipped ${config.filename} (already exists)`);
272
+ // Don't continue - still need to set up commands directory
273
+ }
274
+ }
275
+ else {
276
+ const content = generateAdapterContent(config);
277
+ writeFileSync(filePath, content, 'utf-8');
278
+ p.log.success(`Created ${pc.cyan(config.filename)} for ${config.name}`);
279
+ adapterFileWritten = true;
280
+ }
281
+ // For Cursor, also set up .cursor/commands/
282
+ if (name === 'cursor') {
283
+ const skipPrompts = !interactive;
284
+ const commandsDirExists = isCursorAdapterInstalled(cwd);
285
+ const result = await setupCursorCommands(cwd, commandsDir, skipPrompts);
286
+ if (result.copied.length > 0) {
287
+ const action = commandsDirExists ? 'Updated' : 'Created';
288
+ p.log.success(`${action} ${pc.cyan('.cursor/commands/')} with ${result.copied.length} command(s)`);
289
+ }
290
+ if (result.skipped.length > 0) {
291
+ p.log.info(`Skipped ${result.skipped.length} existing command(s) in .cursor/commands/`);
292
+ }
293
+ }
294
+ // For Claude, also set up .claude/commands/
295
+ if (name === 'claude') {
296
+ const skipPrompts = !interactive;
297
+ const commandsDirExists = isClaudeAdapterInstalled(cwd);
298
+ const result = await setupClaudeCommands(cwd, commandsDir, skipPrompts);
299
+ if (result.copied.length > 0) {
300
+ const action = commandsDirExists ? 'Updated' : 'Created';
301
+ p.log.success(`${action} ${pc.cyan('.claude/commands/')} with ${result.copied.length} command(s)`);
302
+ }
303
+ if (result.skipped.length > 0) {
304
+ p.log.info(`Skipped ${result.skipped.length} existing command(s) in .claude/commands/`);
305
+ }
306
+ }
307
+ }
308
+ }
@@ -0,0 +1 @@
1
+ export declare function init(): Promise<void>;