speci 0.1.0 → 0.3.0

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.
package/README.md CHANGED
@@ -81,7 +81,7 @@ speci init [options]
81
81
 
82
82
  **Options:**
83
83
 
84
- - `-y, --yes` - Accept all defaults without prompts
84
+ - `-u, --update-agents` - Update agent files even if they already exist
85
85
  - `-v, --verbose` - Show detailed output
86
86
 
87
87
  **Creates:**
@@ -89,23 +89,24 @@ speci init [options]
89
89
  - `speci.config.json` - Configuration file
90
90
  - `docs/tasks/` - Task definition directory
91
91
  - `.speci-logs/` - Log file directory
92
+ - `.github/copilot/agents/` - Copilot agent definitions
92
93
 
93
94
  **Examples:**
94
95
 
95
96
  ```bash
96
- # Interactive setup wizard
97
+ # Initialize with defaults
97
98
  speci init
98
99
 
99
- # Quick setup with defaults
100
- speci init --yes
100
+ # Update agent files to latest version
101
+ speci init --update-agents
101
102
 
102
103
  # Short alias version
103
- speci i -y
104
+ speci i
104
105
  ```
105
106
 
106
107
  ### `speci plan` (alias: `p`)
107
108
 
108
- Generate an implementation plan interactively using Copilot.
109
+ Generate an implementation plan using Copilot with an initial prompt or input files.
109
110
 
110
111
  **Usage:**
111
112
 
@@ -115,21 +116,31 @@ speci plan [options]
115
116
 
116
117
  **Options:**
117
118
 
118
- - `-a, --agent <path>` - Use custom agent file
119
+ - `-p, --prompt <text>` - Initial prompt describing what to plan
120
+ - `-i, --input <files...>` - Input files for context (design docs, specs)
121
+ - `-a, --agent <filename>` - Use custom agent file from `.github/copilot/agents/`
119
122
  - `-o, --output <path>` - Save plan to specific file
120
123
  - `-v, --verbose` - Show detailed output
121
124
 
125
+ **Note:** At least `--prompt` or `--input` must be provided.
126
+
122
127
  **Examples:**
123
128
 
124
129
  ```bash
125
- # Start interactive planning session
126
- speci plan
130
+ # Plan with an initial prompt
131
+ speci plan -p "Build a REST API for user authentication"
132
+
133
+ # Plan using a design doc as context
134
+ speci plan -i docs/design.md
127
135
 
128
- # Save plan to specific file
129
- speci plan --output docs/plan.md
136
+ # Combine input files with a prompt
137
+ speci plan -i spec.md -p "Focus on the authentication module"
130
138
 
131
- # Use custom agent
132
- speci p -a custom-agent.md
139
+ # Save plan to a specific file
140
+ speci plan -i design.md -o docs/plan.md
141
+
142
+ # Use custom agent from .github/copilot/agents/
143
+ speci p -a my-custom-plan.agent.md -p "My feature"
133
144
  ```
134
145
 
135
146
  ### `speci task` (alias: `t`)
@@ -145,7 +156,7 @@ speci task --plan <path> [options]
145
156
  **Options:**
146
157
 
147
158
  - `-p, --plan <path>` - Path to plan file (required)
148
- - `-a, --agent <path>` - Use custom agent file
159
+ - `-a, --agent <filename>` - Use custom agent file from `.github/copilot/agents/`
149
160
  - `-v, --verbose` - Show detailed output
150
161
 
151
162
  **Examples:**
@@ -172,7 +183,7 @@ speci refactor [options]
172
183
 
173
184
  - `-s, --scope <path>` - Directory or glob pattern to analyze
174
185
  - `-o, --output <path>` - Save refactoring plan to file
175
- - `-a, --agent <path>` - Use custom agent file
186
+ - `-a, --agent <filename>` - Use custom agent file from `.github/copilot/agents/`
176
187
  - `-v, --verbose` - Show detailed output
177
188
 
178
189
  **Examples:**
@@ -306,15 +317,6 @@ The configuration file is created by `speci init` and can be customized:
306
317
  "logs": ".speci-logs",
307
318
  "lock": ".speci.lock"
308
319
  },
309
- "agents": {
310
- "plan": null,
311
- "task": null,
312
- "refactor": null,
313
- "impl": null,
314
- "review": null,
315
- "fix": null,
316
- "tidy": null
317
- },
318
320
  "copilot": {
319
321
  "permissions": "allow-all",
320
322
  "model": null,
@@ -334,18 +336,19 @@ The configuration file is created by `speci init` and can be customized:
334
336
 
335
337
  Environment variables can override configuration file settings:
336
338
 
337
- | Variable | Config Path | Description |
338
- | ------------------------ | --------------------- | ---------------------------------- |
339
- | `SPECI_PROGRESS_PATH` | `paths.progress` | Path to PROGRESS.md file |
340
- | `SPECI_TASKS_PATH` | `paths.tasks` | Path to tasks directory |
341
- | `SPECI_LOG_PATH` | `paths.logs` | Path to log directory |
342
- | `SPECI_LOCK_PATH` | `paths.lock` | Path to lock file |
343
- | `SPECI_COPILOT_MODEL` | `copilot.model` | Copilot model to use |
344
- | `SPECI_MAX_ITERATIONS` | `loop.maxIterations` | Maximum loop iterations |
345
- | `SPECI_ENABLE_AUTO_FIX` | `loop.enableAutoFix` | Enable automatic gate fix attempts |
346
- | `SPECI_MAX_FIX_ATTEMPTS` | `gate.maxFixAttempts` | Maximum fix attempts |
347
- | `SPECI_DEBUG` | N/A | Enable debug logging (1 or true) |
348
- | `NO_COLOR` | N/A | Disable colored output |
339
+ | Variable | Config Path | Description |
340
+ | ------------------------ | --------------------- | --------------------------------------------- |
341
+ | `SPECI_PROGRESS_PATH` | `paths.progress` | Path to PROGRESS.md file |
342
+ | `SPECI_TASKS_PATH` | `paths.tasks` | Path to tasks directory |
343
+ | `SPECI_LOG_PATH` | `paths.logs` | Path to log directory |
344
+ | `SPECI_LOCK_PATH` | `paths.lock` | Path to lock file |
345
+ | `SPECI_COPILOT_MODEL` | `copilot.model` | Copilot model to use |
346
+ | `SPECI_MAX_ITERATIONS` | `loop.maxIterations` | Maximum loop iterations |
347
+ | `SPECI_ENABLE_AUTO_FIX` | `loop.enableAutoFix` | Enable automatic gate fix attempts |
348
+ | `SPECI_MAX_FIX_ATTEMPTS` | `gate.maxFixAttempts` | Maximum fix attempts |
349
+ | `SPECI_DEBUG` | N/A | Enable debug logging (1 or true) |
350
+ | `SPECI_NO_ANIMATION` | N/A | Disable banner animation (any value disables) |
351
+ | `NO_COLOR` | N/A | Disable colored output |
349
352
 
350
353
  ## Error Codes
351
354
 
@@ -363,13 +366,13 @@ speci uses structured error codes for clear diagnostics:
363
366
 
364
367
  ### Input Errors (ERR-INP-\*)
365
368
 
366
- | Code | Message | Solution |
367
- | ---------- | ------------------------- | --------------------------------------- |
368
- | ERR-INP-01 | Required argument missing | Check command usage with `--help` |
369
- | ERR-INP-02 | Agent file not found | Verify agent path or use bundled agents |
370
- | ERR-INP-03 | Config file is malformed | Fix JSON syntax in speci.config.json |
371
- | ERR-INP-04 | Config validation failed | Check config against schema |
372
- | ERR-INP-05 | Plan file not found | Provide valid path with `--plan` |
369
+ | Code | Message | Solution |
370
+ | ---------- | ------------------------- | ---------------------------------------------------------- |
371
+ | ERR-INP-01 | Required argument missing | Check command usage with `--help` |
372
+ | ERR-INP-02 | Agent file not found | Run `speci init` or add agent to `.github/copilot/agents/` |
373
+ | ERR-INP-03 | Config file is malformed | Fix JSON syntax in speci.config.json |
374
+ | ERR-INP-04 | Config validation failed | Check config against schema |
375
+ | ERR-INP-05 | Plan file not found | Provide valid path with `--plan` |
373
376
 
374
377
  ### State Errors (ERR-STA-\*)
375
378
 
package/bin/speci.ts CHANGED
@@ -8,6 +8,7 @@
8
8
 
9
9
  import { Command } from 'commander';
10
10
  import { renderBanner, VERSION } from '../lib/ui/banner.js';
11
+ import { animateBanner, shouldAnimate } from '../lib/ui/banner-animation.js';
11
12
  import { init } from '../lib/commands/init.js';
12
13
  import { plan } from '../lib/commands/plan.js';
13
14
  import { task } from '../lib/commands/task.js';
@@ -20,9 +21,19 @@ import { setVerbose, debug } from '../lib/utils/logger.js';
20
21
 
21
22
  /**
22
23
  * Display the application banner
24
+ *
25
+ * Conditionally animates the banner when appropriate conditions are met.
26
+ * Returns a Promise when animation is enabled, or void when displaying static banner.
27
+ *
28
+ * @param options - Optional configuration for banner display
23
29
  */
24
- function displayBanner(): void {
25
- console.log('\n' + renderBanner({ showVersion: true }) + '\n');
30
+ function displayBanner(options?: { color?: boolean }): Promise<void> | void {
31
+ if (shouldAnimate(options)) {
32
+ console.log();
33
+ return animateBanner().then(() => console.log());
34
+ } else {
35
+ console.log('\n' + renderBanner({ showVersion: true }) + '\n');
36
+ }
26
37
  }
27
38
 
28
39
  const program = new Command();
@@ -34,7 +45,7 @@ program
34
45
  .description('Speci CLI - AI-powered implementation loop orchestrator')
35
46
  .option('-v, --verbose', 'Enable verbose output')
36
47
  .option('--no-color', 'Disable colored output')
37
- .hook('preAction', (_thisCommand) => {
48
+ .hook('preAction', async (_thisCommand) => {
38
49
  // Enable verbose mode if --verbose flag is set
39
50
  const opts = _thisCommand.opts();
40
51
  if (opts.verbose) {
@@ -53,7 +64,10 @@ program
53
64
  args.includes('--version') ||
54
65
  args.includes('-V');
55
66
  if (!isHelpOrVersion) {
56
- displayBanner();
67
+ const result = displayBanner({ color: opts.color });
68
+ if (result instanceof Promise) {
69
+ await result;
70
+ }
57
71
  }
58
72
  });
59
73
 
@@ -63,6 +77,7 @@ program
63
77
  .alias('i')
64
78
  .description('Initialize Speci in current project')
65
79
  .option('-y, --yes', 'Accept all defaults')
80
+ .option('-u, --update-agents', 'Update agent files even if they exist')
66
81
  .option('-v, --verbose', 'Show detailed output')
67
82
  .addHelpText(
68
83
  'after',
@@ -71,6 +86,7 @@ Examples:
71
86
  $ speci init Interactive setup wizard
72
87
  $ speci init --yes Quick setup with defaults
73
88
  $ speci i -y Force initialize with defaults
89
+ $ speci init -u Update agent files to latest version
74
90
  `
75
91
  )
76
92
  .action(init);
@@ -80,6 +96,11 @@ program
80
96
  .command('plan')
81
97
  .alias('p')
82
98
  .description('Generate implementation plan interactively')
99
+ .option('-p, --prompt <text>', 'Initial prompt describing what to plan')
100
+ .option(
101
+ '-i, --input <files...>',
102
+ 'Input files for context (design docs, specs)'
103
+ )
83
104
  .option('-a, --agent <path>', 'Use custom agent file')
84
105
  .option('-o, --output <path>', 'Output plan to file')
85
106
  .option('-v, --verbose', 'Show detailed output')
@@ -87,9 +108,11 @@ program
87
108
  'after',
88
109
  `
89
110
  Examples:
90
- $ speci plan Start interactive planning session
91
- $ speci plan --output docs/plan.md Save plan to specific file
92
- $ speci p -a custom-agent.md Use custom agent
111
+ $ speci plan -p "Build a REST API" Plan with initial prompt
112
+ $ speci plan -i docs/design.md Plan using design doc as context
113
+ $ speci plan -i spec.md -p "Focus on auth" Combine input files with prompt
114
+ $ speci plan -i design.md -o docs/plan.md Save plan to specific file
115
+ $ speci p -a custom-agent.md -p "My feature" Use custom agent
93
116
  `
94
117
  )
95
118
  .action(plan);
@@ -220,9 +243,14 @@ program.on('command:*', (operands) => {
220
243
 
221
244
  // Show banner and help when no arguments provided
222
245
  if (process.argv.length <= 2) {
223
- displayBanner();
224
- program.help();
246
+ (async () => {
247
+ const result = displayBanner({ color: program.opts().color });
248
+ if (result instanceof Promise) {
249
+ await result;
250
+ }
251
+ program.help();
252
+ })();
253
+ } else {
254
+ // Parse command line arguments (only when a command is provided)
255
+ program.parse(process.argv);
225
256
  }
226
-
227
- // Parse command line arguments
228
- program.parse(process.argv);
@@ -1,126 +1,35 @@
1
1
  /**
2
2
  * Init Command Module
3
3
  *
4
- * Provides interactive project setup for new Speci users.
4
+ * Provides a project setup for new Speci users.
5
5
  * Creates speci.config.json, directory structure, and initial files.
6
- * Uses Node.js readline for zero-dependency interactive prompts.
7
6
  */
8
7
 
9
- import { createInterface } from 'node:readline';
10
- import { existsSync, mkdirSync, writeFileSync } from 'node:fs';
11
- import { resolve, basename } from 'node:path';
8
+ import {
9
+ existsSync,
10
+ mkdirSync,
11
+ writeFileSync,
12
+ copyFileSync,
13
+ readdirSync,
14
+ statSync,
15
+ } from 'node:fs';
16
+ import { join, relative } from 'node:path';
12
17
  import { log } from '../utils/logger.js';
13
18
  import { renderBanner } from '../ui/banner.js';
14
19
  import { colorize } from '../ui/colors.js';
15
- import { getDefaults, type SpeciConfig } from '../config.js';
20
+ import {
21
+ getDefaults,
22
+ getAgentsTemplatePath,
23
+ GITHUB_AGENTS_DIR,
24
+ type SpeciConfig,
25
+ } from '../config.js';
16
26
 
17
27
  /**
18
28
  * Options for the init command
19
29
  */
20
30
  export interface InitOptions {
21
- yes?: boolean; // Skip prompts, use defaults
22
31
  verbose?: boolean; // Show detailed output
23
- }
24
-
25
- /**
26
- * Prompt user for input with default value
27
- * @param question - Question to ask
28
- * @param defaultValue - Default value if no input provided
29
- * @returns User's answer or default value
30
- */
31
- async function prompt(question: string, defaultValue: string): Promise<string> {
32
- const rl = createInterface({
33
- input: process.stdin,
34
- output: process.stdout,
35
- });
36
-
37
- return new Promise((resolve) => {
38
- const styled = `${colorize(question, 'sky400')} ${colorize(`(${defaultValue})`, 'dim')}: `;
39
- rl.question(styled, (answer) => {
40
- rl.close();
41
- resolve(answer.trim() || defaultValue);
42
- });
43
- });
44
- }
45
-
46
- /**
47
- * Validate path to ensure it's safe (no path traversal outside project)
48
- * @param input - Path to validate
49
- * @returns Validated path
50
- * @throws Error if path attempts to escape project directory
51
- */
52
- function validatePath(input: string): string {
53
- const normalized = resolve(process.cwd(), input);
54
- const projectRoot = process.cwd();
55
-
56
- // Check if normalized path starts with project root
57
- if (!normalized.startsWith(projectRoot)) {
58
- throw new Error(
59
- `Invalid path: ${input} attempts to escape project directory`
60
- );
61
- }
62
-
63
- return input;
64
- }
65
-
66
- /**
67
- * Gather configuration through interactive prompts
68
- * @returns Partial config with user answers
69
- */
70
- async function gatherConfig(): Promise<Partial<SpeciConfig>> {
71
- // Project name is prompted but not used in config (for future enhancement)
72
- await prompt('Project name', basename(process.cwd()));
73
-
74
- const progressPath = validatePath(
75
- await prompt('Progress file path', 'docs/PROGRESS.md')
76
- );
77
-
78
- const tasksPath = validatePath(
79
- await prompt('Tasks directory path', 'docs/tasks')
80
- );
81
-
82
- const logsPath = validatePath(
83
- await prompt('Logs directory path', '.speci-logs')
84
- );
85
-
86
- const gateCommands = await prompt(
87
- 'Gate commands (comma-separated)',
88
- 'npm run lint, npm run typecheck, npm test'
89
- );
90
-
91
- return {
92
- paths: {
93
- progress: progressPath,
94
- tasks: tasksPath,
95
- logs: logsPath,
96
- lock: '.speci-lock',
97
- },
98
- gate: {
99
- commands: gateCommands.split(',').map((cmd) => cmd.trim()),
100
- maxFixAttempts: 3,
101
- },
102
- };
103
- }
104
-
105
- /**
106
- * Merge user config with defaults
107
- * @param userConfig - Partial config from user
108
- * @returns Full config merged with defaults
109
- */
110
- function mergeWithDefaults(userConfig: Partial<SpeciConfig>): SpeciConfig {
111
- const defaults = getDefaults();
112
-
113
- return {
114
- ...defaults,
115
- paths: {
116
- ...defaults.paths,
117
- ...userConfig.paths,
118
- },
119
- gate: {
120
- ...defaults.gate,
121
- ...userConfig.gate,
122
- },
123
- };
32
+ updateAgents?: boolean; // Force update agent files even if they exist
124
33
  }
125
34
 
126
35
  /**
@@ -132,11 +41,13 @@ function checkExistingFiles(config: SpeciConfig): {
132
41
  configExists: boolean;
133
42
  tasksExists: boolean;
134
43
  logsExists: boolean;
44
+ agentsExist: boolean;
135
45
  } {
136
46
  return {
137
47
  configExists: existsSync('speci.config.json'),
138
48
  tasksExists: existsSync(config.paths.tasks),
139
49
  logsExists: existsSync(config.paths.logs),
50
+ agentsExist: existsSync(GITHUB_AGENTS_DIR),
140
51
  };
141
52
  }
142
53
 
@@ -144,26 +55,27 @@ function checkExistingFiles(config: SpeciConfig): {
144
55
  * Display summary of actions to be taken
145
56
  * @param config - Config to display
146
57
  * @param existing - Existing files flags
58
+ * @param updateAgents - Whether to force update agent files
147
59
  */
148
60
  function displayActionSummary(
149
61
  config: SpeciConfig,
150
- existing: ReturnType<typeof checkExistingFiles>
62
+ existing: ReturnType<typeof checkExistingFiles>,
63
+ updateAgents: boolean = false
151
64
  ): void {
152
- console.log();
153
- log.info('The following actions will be performed:');
154
- console.log();
155
-
156
65
  if (existing.configExists) {
157
66
  log.warn(' speci.config.json already exists (will skip)');
158
67
  } else {
159
- console.log(colorize(' ✓ Create speci.config.json', 'success'));
68
+ console.log(colorize(' speci.config.json will be created', 'success'));
160
69
  }
161
70
 
162
71
  if (existing.tasksExists) {
163
72
  log.warn(` ${config.paths.tasks}/ already exists (will skip)`);
164
73
  } else {
165
74
  console.log(
166
- colorize(` ✓ Create ${config.paths.tasks}/ directory`, 'success')
75
+ colorize(
76
+ ` ${config.paths.tasks}/ directory will be created`,
77
+ 'success'
78
+ )
167
79
  );
168
80
  }
169
81
 
@@ -171,7 +83,26 @@ function displayActionSummary(
171
83
  log.warn(` ${config.paths.logs}/ already exists (will skip)`);
172
84
  } else {
173
85
  console.log(
174
- colorize(` ✓ Create ${config.paths.logs}/ directory`, 'success')
86
+ colorize(` ${config.paths.logs}/ directory will be created`, 'success')
87
+ );
88
+ }
89
+
90
+ if (existing.agentsExist) {
91
+ if (updateAgents) {
92
+ console.log(
93
+ colorize(
94
+ ` ${GITHUB_AGENTS_DIR}/ directory will be updated`,
95
+ 'success'
96
+ )
97
+ );
98
+ } else {
99
+ log.warn(
100
+ ` ${GITHUB_AGENTS_DIR}/ already exists (will skip, use --update-agents to overwrite)`
101
+ );
102
+ }
103
+ } else {
104
+ console.log(
105
+ colorize(` ${GITHUB_AGENTS_DIR}/ directory will be updated`, 'success')
175
106
  );
176
107
  }
177
108
 
@@ -237,17 +168,97 @@ async function createFiles(
237
168
  }
238
169
  }
239
170
 
171
+ /**
172
+ * Recursively copy a directory
173
+ * @param src - Source directory path
174
+ * @param dest - Destination directory path
175
+ * @returns Number of files copied
176
+ */
177
+ function copyDirectoryRecursive(src: string, dest: string): number {
178
+ let fileCount = 0;
179
+
180
+ // Create destination directory
181
+ mkdirSync(dest, { recursive: true, mode: 0o755 });
182
+
183
+ // Read source directory contents
184
+ const entries = readdirSync(src);
185
+
186
+ for (const entry of entries) {
187
+ const srcPath = join(src, entry);
188
+ const destPath = join(dest, entry);
189
+ const stat = statSync(srcPath);
190
+
191
+ if (stat.isDirectory()) {
192
+ // Recursively copy subdirectories
193
+ fileCount += copyDirectoryRecursive(srcPath, destPath);
194
+ } else if (stat.isFile()) {
195
+ // Copy file
196
+ copyFileSync(srcPath, destPath);
197
+ const relativePath = relative(getAgentsTemplatePath(), srcPath);
198
+ log.debug(`Copied: ${relativePath}`);
199
+ fileCount++;
200
+ }
201
+ }
202
+
203
+ return fileCount;
204
+ }
205
+
206
+ /**
207
+ * Copy agent files to .github/copilot/agents/
208
+ * This allows copilot CLI to use --agent flag with agent names
209
+ * Recursively copies entire agents template directory including subagents
210
+ * @param existing - Existing files flags
211
+ * @param forceUpdate - Force update even if agents exist
212
+ */
213
+ async function copyAgentFiles(
214
+ existing: ReturnType<typeof checkExistingFiles>,
215
+ forceUpdate: boolean = false
216
+ ): Promise<void> {
217
+ if (existing.agentsExist && !forceUpdate) {
218
+ log.debug(`Skipping agent files copy: ${GITHUB_AGENTS_DIR} already exists`);
219
+ return;
220
+ }
221
+
222
+ try {
223
+ const templateDir = getAgentsTemplatePath();
224
+
225
+ if (!existsSync(templateDir)) {
226
+ throw new Error(`Agent templates directory not found: ${templateDir}`);
227
+ }
228
+
229
+ // Recursively copy entire agents directory
230
+ const fileCount = copyDirectoryRecursive(templateDir, GITHUB_AGENTS_DIR);
231
+
232
+ const action = existing.agentsExist ? 'Updated' : 'Copied';
233
+ log.success(
234
+ `${action} ${fileCount} agent files inside ${GITHUB_AGENTS_DIR}/`
235
+ );
236
+ } catch (error) {
237
+ throw new Error(
238
+ `Failed to copy agent files: ${error instanceof Error ? error.message : String(error)}`
239
+ );
240
+ }
241
+ }
242
+
240
243
  /**
241
244
  * Display success message and next steps
242
245
  */
243
246
  function displaySuccess(): void {
244
- console.log();
245
- log.success('Speci initialization complete!');
246
247
  console.log();
247
248
  log.info('Next steps:');
248
- console.log(colorize(' 1. Add tasks to docs/tasks/', 'dim'));
249
- console.log(colorize(' 2. Update docs/PROGRESS.md with your tasks', 'dim'));
250
- console.log(colorize(' 3. Run: speci status', 'dim'));
249
+ console.log(colorize(' 1. Generate your plan with: speci plan', 'dim'));
250
+ console.log(
251
+ colorize(
252
+ ' 2. Generate your tasks and PROGRESS.md with: speci tasks',
253
+ 'dim'
254
+ )
255
+ );
256
+ console.log(
257
+ colorize(
258
+ ' 3. After a manual check start the implementation loop: speci run',
259
+ 'dim'
260
+ )
261
+ );
251
262
  console.log();
252
263
  }
253
264
 
@@ -264,19 +275,14 @@ export async function init(options: InitOptions = {}): Promise<void> {
264
275
  log.info('Initializing Speci in current directory...');
265
276
  console.log();
266
277
 
267
- // Gather configuration (prompts or defaults)
268
- const userConfig = options.yes
269
- ? { paths: getDefaults().paths, gate: getDefaults().gate }
270
- : await gatherConfig();
271
-
272
- // Merge with defaults
273
- const config = mergeWithDefaults(userConfig);
278
+ // Use default configuration
279
+ const config = getDefaults();
274
280
 
275
281
  // Check existing files
276
282
  const existing = checkExistingFiles(config);
277
283
 
278
284
  // Display action summary
279
- displayActionSummary(config, existing);
285
+ displayActionSummary(config, existing, options.updateAgents);
280
286
 
281
287
  // Create directories
282
288
  await createDirectories(config, existing);
@@ -284,6 +290,9 @@ export async function init(options: InitOptions = {}): Promise<void> {
284
290
  // Create files
285
291
  await createFiles(config, existing);
286
292
 
293
+ // Copy agent files to .github/copilot/agents/
294
+ await copyAgentFiles(existing, options.updateAgents);
295
+
287
296
  // Display success and next steps
288
297
  displaySuccess();
289
298
  } catch (error) {