@a3t/rapid 0.1.12 → 0.1.14

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.
@@ -1,18 +1,18 @@
1
1
  // src/index.ts
2
- import { Command as Command13 } from "commander";
3
- import { setLogLevel, logger as logger14 } from "@a3t/rapid-core";
2
+ import { Command as Command14 } from "commander";
3
+ import { setLogLevel, logger as logger16 } from "@a3t/rapid-core";
4
4
  import { readFileSync as readFileSync2 } from "fs";
5
5
  import { fileURLToPath as fileURLToPath3 } from "url";
6
- import { dirname as dirname4, join as join7 } from "path";
6
+ import { dirname as dirname4, join as join8 } from "path";
7
7
 
8
8
  // src/commands/init.ts
9
9
  import { Command } from "commander";
10
- import { writeFile, access, readFile, readdir, mkdir } from "fs/promises";
11
- import { join } from "path";
10
+ import { writeFile as writeFile2, access, readFile, readdir, mkdir as mkdir2 } from "fs/promises";
11
+ import { join as join2 } from "path";
12
12
  import { existsSync } from "fs";
13
13
  import {
14
14
  getDefaultConfig,
15
- logger,
15
+ logger as logger2,
16
16
  MCP_SERVER_TEMPLATES,
17
17
  addMcpServerFromTemplate,
18
18
  getSecretReferences,
@@ -20,9 +20,203 @@ import {
20
20
  writeOpenCodeConfig,
21
21
  RAPID_METHODOLOGY,
22
22
  MCP_USAGE_GUIDELINES,
23
- GIT_GUIDELINES
23
+ GIT_GUIDELINES,
24
+ formatJson as formatJson2
24
25
  } from "@a3t/rapid-core";
25
26
  import ora from "ora";
27
+
28
+ // src/templates/claude-plugin.ts
29
+ import { mkdir, writeFile } from "fs/promises";
30
+ import { join } from "path";
31
+ import { formatJson, logger } from "@a3t/rapid-core";
32
+ function getPluginManifest(projectName) {
33
+ return {
34
+ name: `${projectName}-rapid`,
35
+ version: "1.0.0",
36
+ description: `RAPID plugin for ${projectName}`,
37
+ commands: [
38
+ "commands/rapid-status.md",
39
+ "commands/rapid-worktree.md",
40
+ "commands/rapid-context.md",
41
+ "commands/rapid-mcp.md"
42
+ ],
43
+ skills: ["skills/rapid-methodology.md", "skills/mcp-usage.md"]
44
+ };
45
+ }
46
+ var COMMAND_RAPID_STATUS = `---
47
+ description: Check RAPID environment status
48
+ allowed-tools: Bash(rapid:*)
49
+ argument-hint: [--json]
50
+ ---
51
+
52
+ Check the current RAPID environment status.
53
+
54
+ Run: \`rapid status $ARGUMENTS\`
55
+
56
+ This command shows:
57
+ - Container status (running/stopped)
58
+ - Configured agents
59
+ - MCP server status
60
+ - Secrets status
61
+ `;
62
+ var COMMAND_RAPID_WORKTREE = `---
63
+ description: Manage git worktrees for branch isolation
64
+ allowed-tools: Bash(rapid:*, git:*)
65
+ argument-hint: <create|list|remove> [branch]
66
+ ---
67
+
68
+ Manage git worktrees for isolated feature branch development.
69
+
70
+ ## Usage
71
+
72
+ - \`/rapid-worktree list\` - List all worktrees
73
+ - \`/rapid-worktree create <branch>\` - Create a worktree for a branch
74
+ - \`/rapid-worktree remove <path>\` - Remove a worktree
75
+
76
+ Run: \`rapid worktree $ARGUMENTS\`
77
+ `;
78
+ var COMMAND_RAPID_CONTEXT = `---
79
+ description: Show or inject project context
80
+ allowed-tools: Bash(rapid:*)
81
+ argument-hint: [show|inject]
82
+ ---
83
+
84
+ Show or inject project context from rapid.json configuration.
85
+
86
+ ## Usage
87
+
88
+ - \`/rapid-context show\` - Display current context configuration
89
+ - \`/rapid-context inject\` - Output assembled context (for hooks)
90
+
91
+ Run: \`rapid context $ARGUMENTS\`
92
+ `;
93
+ var COMMAND_RAPID_MCP = `---
94
+ description: Manage MCP servers
95
+ allowed-tools: Bash(rapid:*)
96
+ argument-hint: <add|remove|list> [server]
97
+ ---
98
+
99
+ Manage Model Context Protocol (MCP) servers.
100
+
101
+ ## Usage
102
+
103
+ - \`/rapid-mcp list\` - List configured MCP servers
104
+ - \`/rapid-mcp add <server>\` - Add an MCP server from templates
105
+ - \`/rapid-mcp remove <server>\` - Remove an MCP server
106
+
107
+ Run: \`rapid mcp $ARGUMENTS\`
108
+ `;
109
+ var SKILL_RAPID_METHODOLOGY = `---
110
+ description: Apply the RAPID 5-phase development methodology
111
+ ---
112
+
113
+ # RAPID Methodology
114
+
115
+ When working on this project, follow the RAPID 5-phase approach:
116
+
117
+ ## 1. Research Phase
118
+ - Understand the codebase structure and existing patterns
119
+ - Use grep, find, and read tools to explore before making changes
120
+ - Identify dependencies and potential impacts
121
+
122
+ ## 2. Augment Phase
123
+ - Gather additional context from documentation and MCP servers
124
+ - Use Context7 for library documentation
125
+ - Use Tavily for web searches when needed
126
+
127
+ ## 3. Plan Phase
128
+ - Break down the task into concrete steps
129
+ - Identify files that need to be created or modified
130
+ - Consider edge cases and error handling
131
+
132
+ ## 4. Integrate Phase
133
+ - Make changes incrementally, testing each step
134
+ - Follow existing code patterns and conventions
135
+ - Run tests after each significant change
136
+
137
+ ## 5. Develop Phase
138
+ - Complete the implementation
139
+ - Write or update tests as needed
140
+ - Document changes in code comments where helpful
141
+ `;
142
+ var SKILL_MCP_USAGE = `---
143
+ description: Guidelines for using MCP servers effectively
144
+ ---
145
+
146
+ # MCP Server Usage Guidelines
147
+
148
+ ## Available Servers
149
+
150
+ Check configured MCP servers with: \`rapid mcp list\`
151
+
152
+ ## Common Servers
153
+
154
+ ### Context7
155
+ Use for up-to-date library documentation:
156
+ 1. First resolve library ID: \`mcp__context7__resolve-library-id\`
157
+ 2. Then query docs: \`mcp__context7__query-docs\`
158
+
159
+ ### Tavily
160
+ Use for web searches and content extraction:
161
+ - \`mcp__tavily__tavily_search\` - Search the web
162
+ - \`mcp__tavily__tavily_extract\` - Extract content from URLs
163
+
164
+ ## Best Practices
165
+
166
+ 1. Always check if an MCP server is available before using it
167
+ 2. Prefer MCP servers over manual web searches
168
+ 3. Cache relevant documentation locally when possible
169
+ 4. Use specific queries for better results
170
+ `;
171
+ function getHooksConfig() {
172
+ return {
173
+ // SessionStart hook is not currently supported via JSON config
174
+ // This is a placeholder for future hook support
175
+ };
176
+ }
177
+ async function createClaudePlugin(rootDir, projectName, _options = {}) {
178
+ const pluginDir = join(rootDir, ".claude-plugin");
179
+ const commandsDir = join(pluginDir, "commands");
180
+ const skillsDir = join(pluginDir, "skills");
181
+ const hooksDir = join(pluginDir, "hooks");
182
+ try {
183
+ await mkdir(pluginDir, { recursive: true });
184
+ await mkdir(commandsDir, { recursive: true });
185
+ await mkdir(skillsDir, { recursive: true });
186
+ await mkdir(hooksDir, { recursive: true });
187
+ await writeFile(
188
+ join(pluginDir, "plugin.json"),
189
+ await formatJson(getPluginManifest(projectName))
190
+ );
191
+ await writeFile(join(commandsDir, "rapid-status.md"), COMMAND_RAPID_STATUS);
192
+ await writeFile(join(commandsDir, "rapid-worktree.md"), COMMAND_RAPID_WORKTREE);
193
+ await writeFile(join(commandsDir, "rapid-context.md"), COMMAND_RAPID_CONTEXT);
194
+ await writeFile(join(commandsDir, "rapid-mcp.md"), COMMAND_RAPID_MCP);
195
+ await writeFile(join(skillsDir, "rapid-methodology.md"), SKILL_RAPID_METHODOLOGY);
196
+ await writeFile(join(skillsDir, "mcp-usage.md"), SKILL_MCP_USAGE);
197
+ await writeFile(join(hooksDir, "hooks.json"), await formatJson(getHooksConfig()));
198
+ return true;
199
+ } catch (error) {
200
+ logger.debug(
201
+ `Failed to create Claude plugin: ${error instanceof Error ? error.message : String(error)}`
202
+ );
203
+ return false;
204
+ }
205
+ }
206
+ function getClaudePluginFiles() {
207
+ return [
208
+ ".claude-plugin/plugin.json",
209
+ ".claude-plugin/commands/rapid-status.md",
210
+ ".claude-plugin/commands/rapid-worktree.md",
211
+ ".claude-plugin/commands/rapid-context.md",
212
+ ".claude-plugin/commands/rapid-mcp.md",
213
+ ".claude-plugin/skills/rapid-methodology.md",
214
+ ".claude-plugin/skills/mcp-usage.md",
215
+ ".claude-plugin/hooks/hooks.json"
216
+ ];
217
+ }
218
+
219
+ // src/commands/init.ts
26
220
  async function detectProjectType(dir) {
27
221
  const files = await readdir(dir).catch(() => []);
28
222
  const fileSet = new Set(files);
@@ -33,7 +227,7 @@ async function detectProjectType(dir) {
33
227
  return { language: "go", confidence: "high" };
34
228
  }
35
229
  if (fileSet.has("pyproject.toml")) {
36
- const content = await readFile(join(dir, "pyproject.toml"), "utf-8").catch(() => "");
230
+ const content = await readFile(join2(dir, "pyproject.toml"), "utf-8").catch(() => "");
37
231
  const framework = content.includes("fastapi") ? "fastapi" : content.includes("django") ? "django" : content.includes("flask") ? "flask" : void 0;
38
232
  if (framework) {
39
233
  return { language: "python", framework, confidence: "high" };
@@ -53,7 +247,7 @@ async function detectProjectType(dir) {
53
247
  const pkgManager = fileSet.has("pnpm-lock.yaml") ? "pnpm" : fileSet.has("yarn.lock") ? "yarn" : fileSet.has("bun.lockb") || fileSet.has("bun.lock") ? "bun" : "npm";
54
248
  let framework;
55
249
  if (fileSet.has("package.json")) {
56
- const pkg = await readFile(join(dir, "package.json"), "utf-8").catch(() => "{}");
250
+ const pkg = await readFile(join2(dir, "package.json"), "utf-8").catch(() => "{}");
57
251
  try {
58
252
  const parsed = JSON.parse(pkg);
59
253
  const deps = { ...parsed.dependencies, ...parsed.devDependencies };
@@ -80,7 +274,11 @@ async function detectProjectType(dir) {
80
274
  }
81
275
  if (fileSet.has("package.json")) {
82
276
  const pkgManager = fileSet.has("pnpm-lock.yaml") ? "pnpm" : fileSet.has("yarn.lock") ? "yarn" : "npm";
83
- return { language: "javascript", packageManager: pkgManager, confidence: "medium" };
277
+ return {
278
+ language: "javascript",
279
+ packageManager: pkgManager,
280
+ confidence: "medium"
281
+ };
84
282
  }
85
283
  return { language: "unknown", confidence: "low" };
86
284
  }
@@ -190,7 +388,7 @@ async function downloadRemoteTemplate(parsed, destDir, spinner) {
190
388
  });
191
389
  return true;
192
390
  } catch (error) {
193
- logger.debug(
391
+ logger2.debug(
194
392
  `Failed to download template: ${error instanceof Error ? error.message : String(error)}`
195
393
  );
196
394
  return false;
@@ -458,21 +656,21 @@ function getDevContainerConfig(detected, usePrebuilt = false) {
458
656
  }
459
657
  }
460
658
  async function createDevContainer(dir, detected, force = false, usePrebuilt = false) {
461
- const devcontainerDir = join(dir, ".devcontainer");
462
- const devcontainerJsonPath = join(devcontainerDir, "devcontainer.json");
659
+ const devcontainerDir = join2(dir, ".devcontainer");
660
+ const devcontainerJsonPath = join2(devcontainerDir, "devcontainer.json");
463
661
  if (!force && existsSync(devcontainerJsonPath)) {
464
662
  return false;
465
663
  }
466
- await mkdir(devcontainerDir, { recursive: true });
664
+ await mkdir2(devcontainerDir, { recursive: true });
467
665
  const config = getDevContainerConfig(detected, usePrebuilt);
468
- await writeFile(devcontainerJsonPath, JSON.stringify(config, null, 2) + "\n");
666
+ await writeFile2(devcontainerJsonPath, await formatJson2(config));
469
667
  return true;
470
668
  }
471
- var initCommand = new Command("init").description("Initialize RAPID in a project").argument("[template]", "Template: builtin name, github:user/repo, npm:package, or URL").option("--force", "Overwrite existing files", false).option("--agent <name>", "Default agent to configure", "claude").option("--no-devcontainer", "Skip devcontainer creation").option("--prebuilt", "Use pre-built devcontainer images from ghcr.io (faster startup)", false).option("--mcp <servers>", "MCP servers to enable (comma-separated)", "context7,tavily").option("--no-mcp", "Skip MCP server configuration").option("--no-detect", "Skip auto-detection of project type").action(async (templateArg, options) => {
669
+ var initCommand = new Command("init").description("Initialize RAPID in a project").argument("[template]", "Template: builtin name, github:user/repo, npm:package, or URL").option("--force", "Overwrite existing files", false).option("--agent <name>", "Default agent to configure", "claude").option("--no-devcontainer", "Skip devcontainer creation").option("--prebuilt", "Use pre-built devcontainer images from ghcr.io (faster startup)", false).option("--mcp <servers>", "MCP servers to enable (comma-separated)", "context7,tavily").option("--no-mcp", "Skip MCP server configuration").option("--no-detect", "Skip auto-detection of project type").option("--no-claude-plugin", "Skip Claude Code plugin generation").action(async (templateArg, options) => {
472
670
  const spinner = ora("Initializing RAPID...").start();
473
671
  try {
474
672
  const cwd = process.cwd();
475
- const configPath = join(cwd, "rapid.json");
673
+ const configPath = join2(cwd, "rapid.json");
476
674
  if (!options.force) {
477
675
  try {
478
676
  await access(configPath);
@@ -492,7 +690,7 @@ var initCommand = new Command("init").description("Initialize RAPID in a project
492
690
  `Detected ${detectedProject.language}${detectedProject.framework ? ` (${detectedProject.framework})` : ""} project`
493
691
  );
494
692
  templateSource = suggested;
495
- logger.info(`Using ${logger.brand(suggested)} template`);
693
+ logger2.info(`Using ${logger2.brand(suggested)} template`);
496
694
  } else {
497
695
  spinner.info("Could not detect project type, using universal template");
498
696
  templateSource = "universal";
@@ -509,16 +707,16 @@ var initCommand = new Command("init").description("Initialize RAPID in a project
509
707
  const downloaded = await downloadRemoteTemplate(parsed, cwd, spinner);
510
708
  if (!downloaded) {
511
709
  spinner.fail(`Failed to download template from ${parsed.source}`);
512
- logger.info("Make sure the repository exists and is accessible.");
513
- logger.info("For private repos, set GIGET_AUTH environment variable.");
710
+ logger2.info("Make sure the repository exists and is accessible.");
711
+ logger2.info("For private repos, set GIGET_AUTH environment variable.");
514
712
  process.exit(1);
515
713
  }
516
714
  spinner.succeed(`Downloaded template from ${parsed.source}`);
517
715
  try {
518
- await access(join(cwd, "rapid.json"));
519
- logger.blank();
520
- logger.info("Template includes rapid.json configuration.");
521
- logger.info("Run `rapid dev` to start coding!");
716
+ await access(join2(cwd, "rapid.json"));
717
+ logger2.blank();
718
+ logger2.info("Template includes rapid.json configuration.");
719
+ logger2.info("Run `rapid dev` to start coding!");
522
720
  return;
523
721
  } catch {
524
722
  spinner.start("Creating RAPID configuration...");
@@ -532,7 +730,7 @@ var initCommand = new Command("init").description("Initialize RAPID in a project
532
730
  if (MCP_SERVER_TEMPLATES[serverName]) {
533
731
  config = addMcpServerFromTemplate(config, serverName);
534
732
  } else {
535
- logger.warn(`Unknown MCP server template: ${serverName}`);
733
+ logger2.warn(`Unknown MCP server template: ${serverName}`);
536
734
  }
537
735
  }
538
736
  const secretRefs = getSecretReferences(mcpServers);
@@ -549,7 +747,7 @@ var initCommand = new Command("init").description("Initialize RAPID in a project
549
747
  }
550
748
  }
551
749
  spinner.text = "Writing rapid.json...";
552
- await writeFile(configPath, JSON.stringify(config, null, 2) + "\n");
750
+ await writeFile2(configPath, await formatJson2(config));
553
751
  if (mcpServers.length > 0) {
554
752
  spinner.text = "Generating MCP configuration files...";
555
753
  await writeMcpConfig(cwd, config);
@@ -557,12 +755,12 @@ var initCommand = new Command("init").description("Initialize RAPID in a project
557
755
  }
558
756
  if (config.agents.available.claude) {
559
757
  spinner.text = "Creating CLAUDE.md...";
560
- const claudeMdPath = join(cwd, "CLAUDE.md");
561
- await writeFile(claudeMdPath, getClaudeMdTemplate(cwd, detectedProject));
758
+ const claudeMdPath = join2(cwd, "CLAUDE.md");
759
+ await writeFile2(claudeMdPath, getClaudeMdTemplate(cwd, detectedProject));
562
760
  }
563
761
  spinner.text = "Creating AGENTS.md...";
564
- const agentsMdPath = join(cwd, "AGENTS.md");
565
- await writeFile(agentsMdPath, getAgentsMdTemplate(cwd, detectedProject));
762
+ const agentsMdPath = join2(cwd, "AGENTS.md");
763
+ await writeFile2(agentsMdPath, getAgentsMdTemplate(cwd, detectedProject));
566
764
  let devcontainerCreated = false;
567
765
  const usePrebuilt = options.prebuilt === true;
568
766
  if (options.devcontainer !== false) {
@@ -574,63 +772,75 @@ var initCommand = new Command("init").description("Initialize RAPID in a project
574
772
  usePrebuilt
575
773
  );
576
774
  }
775
+ let claudePluginCreated = false;
776
+ if (options.claudePlugin !== false && config.agents.available.claude) {
777
+ spinner.text = "Creating Claude Code plugin...";
778
+ const projectName = cwd.split("/").pop() || "project";
779
+ claudePluginCreated = await createClaudePlugin(cwd, projectName, { force: options.force });
780
+ }
577
781
  spinner.succeed("RAPID initialized successfully!");
578
782
  if (detectedProject && detectedProject.language !== "unknown") {
579
- logger.blank();
580
- logger.info("Project detected:");
581
- console.log(` ${logger.dim("Language:")} ${detectedProject.language}`);
783
+ logger2.blank();
784
+ logger2.info("Project detected:");
785
+ console.log(` ${logger2.dim("Language:")} ${detectedProject.language}`);
582
786
  if (detectedProject.framework) {
583
- console.log(` ${logger.dim("Framework:")} ${detectedProject.framework}`);
787
+ console.log(` ${logger2.dim("Framework:")} ${detectedProject.framework}`);
584
788
  }
585
789
  if (detectedProject.packageManager) {
586
- console.log(` ${logger.dim("Package Mgr:")} ${detectedProject.packageManager}`);
790
+ console.log(` ${logger2.dim("Package Mgr:")} ${detectedProject.packageManager}`);
587
791
  }
588
792
  }
589
- logger.blank();
590
- logger.info("Created files:");
591
- console.log(` ${logger.dim("\u2022")} rapid.json`);
793
+ logger2.blank();
794
+ logger2.info("Created files:");
795
+ console.log(` ${logger2.dim("\u2022")} rapid.json`);
592
796
  if (mcpServers.length > 0) {
593
- console.log(` ${logger.dim("\u2022")} .mcp.json`);
594
- console.log(` ${logger.dim("\u2022")} opencode.json`);
797
+ console.log(` ${logger2.dim("\u2022")} .mcp.json`);
798
+ console.log(` ${logger2.dim("\u2022")} opencode.json`);
595
799
  }
596
800
  if (devcontainerCreated) {
597
- console.log(` ${logger.dim("\u2022")} .devcontainer/devcontainer.json`);
801
+ console.log(` ${logger2.dim("\u2022")} .devcontainer/devcontainer.json`);
802
+ }
803
+ if (claudePluginCreated) {
804
+ console.log(` ${logger2.dim("\u2022")} .claude-plugin/`);
805
+ for (const file of getClaudePluginFiles()) {
806
+ console.log(` ${logger2.dim("\u2022")} ${file.replace(".claude-plugin/", "")}`);
807
+ }
598
808
  }
599
- console.log(` ${logger.dim("\u2022")} CLAUDE.md`);
600
- console.log(` ${logger.dim("\u2022")} AGENTS.md`);
809
+ console.log(` ${logger2.dim("\u2022")} CLAUDE.md`);
810
+ console.log(` ${logger2.dim("\u2022")} AGENTS.md`);
601
811
  if (mcpServers.length > 0) {
602
- logger.blank();
603
- logger.info("MCP servers configured:");
812
+ logger2.blank();
813
+ logger2.info("MCP servers configured:");
604
814
  for (const serverName of mcpServers) {
605
815
  const template = MCP_SERVER_TEMPLATES[serverName];
606
816
  if (template) {
607
- console.log(` ${logger.brand("\u2022")} ${serverName} - ${template.description}`);
817
+ console.log(` ${logger2.brand("\u2022")} ${serverName} - ${template.description}`);
608
818
  }
609
819
  }
610
820
  }
611
- logger.blank();
612
- logger.info("Next steps:");
821
+ logger2.blank();
822
+ logger2.info("Next steps:");
613
823
  let stepNum = 1;
614
824
  console.log(
615
- ` ${logger.dim(`${stepNum++}.`)} Run ${logger.brand("rapid dev")} to start coding`
825
+ ` ${logger2.dim(`${stepNum++}.`)} Run ${logger2.brand("rapid dev")} to start coding`
616
826
  );
617
827
  console.log(
618
- ` ${logger.dim(`${stepNum++}.`)} Edit ${logger.dim("rapid.json")} to customize your setup`
828
+ ` ${logger2.dim(`${stepNum++}.`)} Edit ${logger2.dim("rapid.json")} to customize your setup`
619
829
  );
620
830
  if (mcpServers.length > 0) {
621
831
  console.log(
622
- ` ${logger.dim(`${stepNum++}.`)} Add API keys to ${logger.dim("secrets.items")} in rapid.json`
832
+ ` ${logger2.dim(`${stepNum++}.`)} Add API keys to ${logger2.dim("secrets.items")} in rapid.json`
623
833
  );
624
834
  }
625
835
  if (devcontainerCreated) {
626
836
  console.log(
627
- ` ${logger.dim(`${stepNum++}.`)} Set ${logger.dim("OP_SERVICE_ACCOUNT_TOKEN")} env var for 1Password secrets`
837
+ ` ${logger2.dim(`${stepNum++}.`)} Set ${logger2.dim("OP_SERVICE_ACCOUNT_TOKEN")} env var for 1Password secrets`
628
838
  );
629
839
  }
630
- logger.blank();
840
+ logger2.blank();
631
841
  } catch (error) {
632
842
  spinner.fail("Failed to initialize RAPID");
633
- logger.error(error instanceof Error ? error.message : String(error));
843
+ logger2.error(error instanceof Error ? error.message : String(error));
634
844
  process.exit(1);
635
845
  }
636
846
  });
@@ -746,13 +956,13 @@ ${GIT_GUIDELINES}
746
956
 
747
957
  // src/commands/dev.ts
748
958
  import { Command as Command2 } from "commander";
749
- import { writeFile as writeFile3 } from "fs/promises";
750
- import { isAbsolute, join as join4 } from "path";
959
+ import { writeFile as writeFile4 } from "fs/promises";
960
+ import { isAbsolute, join as join5 } from "path";
751
961
  import {
752
962
  loadConfig,
753
963
  getAgent,
754
964
  checkAgentAvailable,
755
- logger as logger2,
965
+ logger as logger3,
756
966
  getContainerStatus,
757
967
  startContainer,
758
968
  execInContainer,
@@ -763,14 +973,17 @@ import {
763
973
  hasVaultCli,
764
974
  isVaultAuthenticated,
765
975
  buildAgentArgs,
766
- agentSupportsRuntimeInjection
976
+ agentSupportsRuntimeInjection,
977
+ formatJson as formatJson3,
978
+ assembleContext,
979
+ generateMcpConfig
767
980
  } from "@a3t/rapid-core";
768
981
  import ora2 from "ora";
769
982
 
770
983
  // src/utils/worktree.ts
771
984
  import { execa } from "execa";
772
985
  import { access as access2 } from "fs/promises";
773
- import { basename, dirname, join as join2, resolve } from "path";
986
+ import { basename, dirname, join as join3, resolve } from "path";
774
987
  function getErrorMessage(err) {
775
988
  if (typeof err.stderr === "string" && err.stderr) {
776
989
  return err.stderr;
@@ -880,7 +1093,7 @@ function generateWorktreePath(repoRoot, branchName) {
880
1093
  const projectName = basename(repoRoot);
881
1094
  const parentDir = dirname(repoRoot);
882
1095
  const safeBranchName = branchName.replace(/\//g, "-").replace(/[^a-zA-Z0-9-_]/g, "").toLowerCase();
883
- return join2(parentDir, `${projectName}-${safeBranchName}`);
1096
+ return join3(parentDir, `${projectName}-${safeBranchName}`);
884
1097
  }
885
1098
  async function createWorktree(repoRoot, worktreePath, branch, options = {}) {
886
1099
  try {
@@ -991,9 +1204,9 @@ async function cleanupMergedWorktrees(repoRoot) {
991
1204
 
992
1205
  // src/isolation/lima.ts
993
1206
  import { execa as execa2 } from "execa";
994
- import { readFile as readFile2, writeFile as writeFile2, mkdir as mkdir2, access as access3 } from "fs/promises";
1207
+ import { readFile as readFile2, writeFile as writeFile3, mkdir as mkdir3, access as access3 } from "fs/promises";
995
1208
  import { homedir, platform } from "os";
996
- import { join as join3, dirname as dirname2 } from "path";
1209
+ import { join as join4, dirname as dirname2 } from "path";
997
1210
  import { fileURLToPath } from "url";
998
1211
  function getErrorMessage2(err) {
999
1212
  if (typeof err.stderr === "string" && err.stderr) {
@@ -1008,7 +1221,7 @@ function getOutputString(output) {
1008
1221
  return void 0;
1009
1222
  }
1010
1223
  var RAPID_LIMA_INSTANCE = "rapid";
1011
- var RAPID_LIMA_DIR = join3(homedir(), ".rapid", "lima");
1224
+ var RAPID_LIMA_DIR = join4(homedir(), ".rapid", "lima");
1012
1225
  async function hasLima() {
1013
1226
  try {
1014
1227
  await execa2("limactl", ["--version"]);
@@ -1023,11 +1236,11 @@ function isMacOS() {
1023
1236
  function getLimaTemplatePath() {
1024
1237
  const __dirname3 = dirname2(fileURLToPath(import.meta.url));
1025
1238
  const possiblePaths = [
1026
- join3(__dirname3, "../../../../templates/lima.yaml"),
1239
+ join4(__dirname3, "../../../../templates/lima.yaml"),
1027
1240
  // From dist/isolation/
1028
- join3(__dirname3, "../../../templates/lima.yaml"),
1241
+ join4(__dirname3, "../../../templates/lima.yaml"),
1029
1242
  // From src/isolation/
1030
- join3(homedir(), ".rapid", "lima.yaml")
1243
+ join4(homedir(), ".rapid", "lima.yaml")
1031
1244
  // User config
1032
1245
  ];
1033
1246
  return possiblePaths[0];
@@ -1067,7 +1280,7 @@ async function instanceExists(name = RAPID_LIMA_INSTANCE) {
1067
1280
  return instanceDirExists(name);
1068
1281
  }
1069
1282
  async function instanceDirExists(name = RAPID_LIMA_INSTANCE) {
1070
- const instanceDir = join3(homedir(), ".lima", name);
1283
+ const instanceDir = join4(homedir(), ".lima", name);
1071
1284
  try {
1072
1285
  await access3(instanceDir);
1073
1286
  return true;
@@ -1092,8 +1305,8 @@ ${homeMount}${projectMount}`;
1092
1305
  async function createLimaConfig(projectDir, options = {}) {
1093
1306
  const templatePath = getLimaTemplatePath();
1094
1307
  const configDir = RAPID_LIMA_DIR;
1095
- const configPath = join3(configDir, "lima.yaml");
1096
- await mkdir2(configDir, { recursive: true });
1308
+ const configPath = join4(configDir, "lima.yaml");
1309
+ await mkdir3(configDir, { recursive: true });
1097
1310
  let template;
1098
1311
  try {
1099
1312
  template = await readFile2(templatePath, "utf-8");
@@ -1117,7 +1330,11 @@ async function createLimaConfig(projectDir, options = {}) {
1117
1330
  ${envLines}
1118
1331
  `);
1119
1332
  }
1120
- await writeFile2(configPath, config);
1333
+ if (options.installGh === false) {
1334
+ const ghInstallPattern = /\s*# Install GitHub CLI\n\s*curl -fsSL https:\/\/cli\.github\.com\/packages\/githubcli-archive-keyring\.gpg \| dd of=\/usr\/share\/keyrings\/githubcli-archive-keyring\.gpg\n\s*chmod go\+r \/usr\/share\/keyrings\/githubcli-archive-keyring\.gpg\n\s*echo "deb \[arch=\$\(dpkg --print-architecture\) signed-by=\/usr\/share\/keyrings\/githubcli-archive-keyring\.gpg\] https:\/\/cli\.github\.com\/packages stable main" \| tee \/etc\/apt\/sources\.list\.d\/github-cli\.list > \/dev\/null\n\s*apt-get update\n\s*apt-get install -y gh\n/;
1335
+ config = config.replace(ghInstallPattern, "\n");
1336
+ }
1337
+ await writeFile3(configPath, config);
1121
1338
  return configPath;
1122
1339
  }
1123
1340
  function getMinimalLimaConfig() {
@@ -1298,6 +1515,56 @@ async function shellInLima(options = {}) {
1298
1515
  }
1299
1516
  await execa2("limactl", args, { stdio: "inherit" });
1300
1517
  }
1518
+ var AGENT_INSTALL_COMMANDS = {
1519
+ claude: ["sudo", "npm", "install", "-g", "@anthropic-ai/claude-code"],
1520
+ opencode: ["bash", "-c", "curl -fsSL https://opencode.ai/install | bash"],
1521
+ aider: ["pip3", "install", "--user", "aider-chat"]
1522
+ };
1523
+ async function isAgentInstalled(agentCli, name = RAPID_LIMA_INSTANCE) {
1524
+ try {
1525
+ const result = await execInLima(["which", agentCli], { name });
1526
+ return result.success && !!result.stdout?.trim();
1527
+ } catch {
1528
+ return false;
1529
+ }
1530
+ }
1531
+ async function installAgent(agentCli, name = RAPID_LIMA_INSTANCE) {
1532
+ const installCmd = AGENT_INSTALL_COMMANDS[agentCli];
1533
+ if (!installCmd) {
1534
+ return {
1535
+ success: false,
1536
+ error: `Unknown agent "${agentCli}". No install command available.`
1537
+ };
1538
+ }
1539
+ try {
1540
+ const result = await execInLima(installCmd, { name });
1541
+ if (!result.success) {
1542
+ return {
1543
+ success: false,
1544
+ error: result.error || result.stderr || `Failed to install ${agentCli}`
1545
+ };
1546
+ }
1547
+ const installed = await isAgentInstalled(agentCli, name);
1548
+ if (!installed) {
1549
+ return {
1550
+ success: false,
1551
+ error: `Installation command succeeded but ${agentCli} is not in PATH`
1552
+ };
1553
+ }
1554
+ return { success: true };
1555
+ } catch (err) {
1556
+ return {
1557
+ success: false,
1558
+ error: err instanceof Error ? err.message : String(err)
1559
+ };
1560
+ }
1561
+ }
1562
+ async function ensureAgentInstalled(agentCli, name = RAPID_LIMA_INSTANCE) {
1563
+ if (await isAgentInstalled(agentCli, name)) {
1564
+ return { success: true };
1565
+ }
1566
+ return installAgent(agentCli, name);
1567
+ }
1301
1568
  async function setupGitSsh(name = RAPID_LIMA_INSTANCE) {
1302
1569
  try {
1303
1570
  const result = await execInLima(["ssh-add", "-l"], { name });
@@ -1352,7 +1619,7 @@ var devCommand = new Command2("dev").description("Launch AI coding session in th
1352
1619
  }
1353
1620
  } catch (err) {
1354
1621
  spinner.warn("Could not create worktree, using main directory");
1355
- logger2.debug(err instanceof Error ? err.message : String(err));
1622
+ logger3.debug(err instanceof Error ? err.message : String(err));
1356
1623
  }
1357
1624
  }
1358
1625
  }
@@ -1363,8 +1630,8 @@ var devCommand = new Command2("dev").description("Launch AI coding session in th
1363
1630
  const agentName = options.agent || config.agents.default;
1364
1631
  const agent = getAgent(config, agentName);
1365
1632
  if (!agent) {
1366
- logger2.error(`Agent "${agentName}" not found in configuration`);
1367
- logger2.info("Available agents:");
1633
+ logger3.error(`Agent "${agentName}" not found in configuration`);
1634
+ logger3.info("Available agents:");
1368
1635
  Object.keys(config.agents.available).forEach((name) => {
1369
1636
  const isDefault = name === config.agents.default;
1370
1637
  console.log(` ${isDefault ? "* " : " "}${name}${isDefault ? " (default)" : ""}`);
@@ -1372,18 +1639,18 @@ var devCommand = new Command2("dev").description("Launch AI coding session in th
1372
1639
  process.exit(1);
1373
1640
  }
1374
1641
  if (options.local) {
1375
- logger2.warn("Running locally instead of in container");
1376
- logger2.dim("This bypasses the isolated dev environment");
1377
- logger2.blank();
1642
+ logger3.warn("Running locally instead of in container");
1643
+ logger3.dim("This bypasses the isolated dev environment");
1644
+ logger3.blank();
1378
1645
  await runLocally(agent, agentName, rootDir, config);
1379
1646
  return;
1380
1647
  }
1381
1648
  const hasDevCli = await hasDevcontainerCli();
1382
1649
  if (!hasDevCli) {
1383
- logger2.error("devcontainer CLI not found");
1384
- logger2.info("Install with: npm install -g @devcontainers/cli");
1385
- logger2.blank();
1386
- logger2.info("Or use --local to run without container (not recommended)");
1650
+ logger3.error("devcontainer CLI not found");
1651
+ logger3.info("Install with: npm install -g @devcontainers/cli");
1652
+ logger3.blank();
1653
+ logger3.info("Or use --local to run without container (not recommended)");
1387
1654
  process.exit(1);
1388
1655
  }
1389
1656
  spinner.start("Checking container status...");
@@ -1397,12 +1664,12 @@ var devCommand = new Command2("dev").description("Launch AI coding session in th
1397
1664
  spinner.stopAndPersist({ symbol: "\u{1F433}", text: "Starting container..." });
1398
1665
  const result = await startContainer(rootDir, config, { quiet: false });
1399
1666
  if (!result.success) {
1400
- logger2.blank();
1401
- logger2.error("Failed to start container");
1402
- logger2.error(result.error || "Unknown error");
1667
+ logger3.blank();
1668
+ logger3.error("Failed to start container");
1669
+ logger3.error(result.error || "Unknown error");
1403
1670
  process.exit(1);
1404
1671
  }
1405
- logger2.blank();
1672
+ logger3.blank();
1406
1673
  } else {
1407
1674
  spinner.succeed(`Container running (${status.containerName})`);
1408
1675
  }
@@ -1415,12 +1682,12 @@ var devCommand = new Command2("dev").description("Launch AI coding session in th
1415
1682
  const hasOp = await hasOpCli();
1416
1683
  if (!hasOp) {
1417
1684
  spinner.warn("1Password CLI not found - secrets will not be loaded");
1418
- logger2.info("Install with: brew install 1password-cli");
1685
+ logger3.info("Install with: brew install 1password-cli");
1419
1686
  } else {
1420
1687
  const authenticated = await isOpAuthenticated();
1421
1688
  if (!authenticated) {
1422
1689
  spinner.warn("1Password not authenticated - secrets will not be loaded");
1423
- logger2.info("Run: eval $(op signin)");
1690
+ logger3.info("Run: eval $(op signin)");
1424
1691
  } else {
1425
1692
  try {
1426
1693
  secrets = await loadSecrets(secretsConfig);
@@ -1428,7 +1695,7 @@ var devCommand = new Command2("dev").description("Launch AI coding session in th
1428
1695
  spinner.succeed(`Loaded ${count} secret${count !== 1 ? "s" : ""} from 1Password`);
1429
1696
  } catch (err) {
1430
1697
  spinner.warn("Failed to load secrets from 1Password");
1431
- logger2.debug(err instanceof Error ? err.message : String(err));
1698
+ logger3.debug(err instanceof Error ? err.message : String(err));
1432
1699
  }
1433
1700
  }
1434
1701
  }
@@ -1437,12 +1704,12 @@ var devCommand = new Command2("dev").description("Launch AI coding session in th
1437
1704
  const hasVault = await hasVaultCli();
1438
1705
  if (!hasVault) {
1439
1706
  spinner.warn("Vault CLI not found - secrets will not be loaded");
1440
- logger2.info("Install from: https://developer.hashicorp.com/vault/docs/install");
1707
+ logger3.info("Install from: https://developer.hashicorp.com/vault/docs/install");
1441
1708
  } else {
1442
1709
  const authenticated = await isVaultAuthenticated();
1443
1710
  if (!authenticated) {
1444
1711
  spinner.warn("Vault not authenticated - secrets will not be loaded");
1445
- logger2.info("Run: vault login");
1712
+ logger3.info("Run: vault login");
1446
1713
  } else {
1447
1714
  try {
1448
1715
  secrets = await loadSecrets(secretsConfig);
@@ -1450,7 +1717,7 @@ var devCommand = new Command2("dev").description("Launch AI coding session in th
1450
1717
  spinner.succeed(`Loaded ${count} secret${count !== 1 ? "s" : ""} from Vault`);
1451
1718
  } catch (err) {
1452
1719
  spinner.warn("Failed to load secrets from Vault");
1453
- logger2.debug(err instanceof Error ? err.message : String(err));
1720
+ logger3.debug(err instanceof Error ? err.message : String(err));
1454
1721
  }
1455
1722
  }
1456
1723
  }
@@ -1466,17 +1733,44 @@ var devCommand = new Command2("dev").description("Launch AI coding session in th
1466
1733
  }
1467
1734
  } catch (err) {
1468
1735
  spinner.warn("Failed to load secrets from environment");
1469
- logger2.debug(err instanceof Error ? err.message : String(err));
1736
+ logger3.debug(err instanceof Error ? err.message : String(err));
1470
1737
  }
1471
1738
  }
1472
1739
  }
1473
- logger2.blank();
1474
- logger2.info(`Launching ${logger2.brand(agentName)} in container...`);
1475
- const builtArgs = buildAgentArgs(agent, { injectSystemPrompt: true });
1740
+ let contextContent;
1741
+ if (config.context?.files?.length || config.context?.dirs?.length) {
1742
+ const spinner2 = ora2("Assembling context files...").start();
1743
+ try {
1744
+ const assembled = await assembleContext(rootDir, config.context);
1745
+ if (assembled.files.length > 0) {
1746
+ contextContent = assembled.content;
1747
+ spinner2.succeed(
1748
+ `Assembled ${assembled.files.length} context file${assembled.files.length !== 1 ? "s" : ""} (${Math.round(assembled.totalSize / 1024)}KB)`
1749
+ );
1750
+ if (assembled.skippedFiles.length > 0) {
1751
+ logger3.dim(` Skipped ${assembled.skippedFiles.length} file(s)`);
1752
+ }
1753
+ } else {
1754
+ spinner2.warn("No context files found");
1755
+ }
1756
+ } catch (err) {
1757
+ spinner2.warn("Failed to assemble context files");
1758
+ logger3.debug(err instanceof Error ? err.message : String(err));
1759
+ }
1760
+ }
1761
+ logger3.blank();
1762
+ logger3.info(`Launching ${logger3.brand(agentName)} in container...`);
1763
+ const builtArgs = buildAgentArgs(agent, {
1764
+ injectSystemPrompt: true,
1765
+ ...contextContent && { contextContent }
1766
+ });
1476
1767
  if (agentSupportsRuntimeInjection(agent)) {
1477
- logger2.dim("Injecting RAPID methodology via CLI args");
1768
+ logger3.dim("Injecting RAPID methodology via CLI args");
1769
+ if (contextContent) {
1770
+ logger3.dim("Injecting context files via CLI args");
1771
+ }
1478
1772
  }
1479
- logger2.blank();
1773
+ logger3.blank();
1480
1774
  const agentArgs = [agent.cli, ...builtArgs];
1481
1775
  const mcpEnv = await prepareMcpEnv(rootDir, config.mcp);
1482
1776
  const mergedEnv = { ...secrets, ...mcpEnv ?? {} };
@@ -1486,7 +1780,7 @@ var devCommand = new Command2("dev").description("Launch AI coding session in th
1486
1780
  env: mergedEnv
1487
1781
  });
1488
1782
  } catch (error) {
1489
- logger2.error(error instanceof Error ? error.message : String(error));
1783
+ logger3.error(error instanceof Error ? error.message : String(error));
1490
1784
  process.exit(1);
1491
1785
  }
1492
1786
  });
@@ -1495,24 +1789,16 @@ async function prepareMcpEnv(rootDir, mcp) {
1495
1789
  return void 0;
1496
1790
  }
1497
1791
  const configFile = mcp.configFile ?? ".mcp.json";
1498
- const configPath = isAbsolute(configFile) ? configFile : join4(rootDir, configFile);
1499
- const mcpServers = {};
1500
- for (const [name, serverConfig] of Object.entries(mcp.servers)) {
1501
- if (!serverConfig || typeof serverConfig !== "object") {
1502
- continue;
1503
- }
1504
- const { enabled, type, ...rest } = serverConfig;
1505
- if (enabled === false) {
1506
- continue;
1507
- }
1508
- const outputType = type === "remote" ? "http" : type;
1509
- mcpServers[name] = { type: outputType, ...rest };
1510
- }
1511
- if (Object.keys(mcpServers).length === 0) {
1792
+ const configPath = isAbsolute(configFile) ? configFile : join5(rootDir, configFile);
1793
+ const mcpConfig = generateMcpConfig({
1794
+ version: "1.0",
1795
+ agents: { default: "", available: {} },
1796
+ mcp
1797
+ });
1798
+ if (Object.keys(mcpConfig.mcpServers).length === 0) {
1512
1799
  return void 0;
1513
1800
  }
1514
- await writeFile3(configPath, `${JSON.stringify({ mcpServers }, null, 2)}
1515
- `, "utf-8");
1801
+ await writeFile4(configPath, await formatJson3(mcpConfig), "utf-8");
1516
1802
  return {
1517
1803
  MCP_CONFIG_FILE: configFile
1518
1804
  };
@@ -1521,7 +1807,7 @@ async function runLocally(agent, agentName, rootDir, config) {
1521
1807
  const { execa: execa4 } = await import("execa");
1522
1808
  const status = await checkAgentAvailable(agent);
1523
1809
  if (!status.available) {
1524
- logger2.error(`${agentName} CLI not found locally`);
1810
+ logger3.error(`${agentName} CLI not found locally`);
1525
1811
  process.exit(1);
1526
1812
  }
1527
1813
  let secrets = {};
@@ -1534,12 +1820,12 @@ async function runLocally(agent, agentName, rootDir, config) {
1534
1820
  const hasOp = await hasOpCli();
1535
1821
  if (!hasOp) {
1536
1822
  spinner.warn("1Password CLI not found - secrets will not be loaded");
1537
- logger2.info("Install with: brew install 1password-cli");
1823
+ logger3.info("Install with: brew install 1password-cli");
1538
1824
  } else {
1539
1825
  const authenticated = await isOpAuthenticated();
1540
1826
  if (!authenticated) {
1541
1827
  spinner.warn("1Password not authenticated - secrets will not be loaded");
1542
- logger2.info("Run: eval $(op signin)");
1828
+ logger3.info("Run: eval $(op signin)");
1543
1829
  } else {
1544
1830
  try {
1545
1831
  secrets = await loadSecrets(secretsConfig);
@@ -1547,7 +1833,7 @@ async function runLocally(agent, agentName, rootDir, config) {
1547
1833
  spinner.succeed(`Loaded ${count} secret${count !== 1 ? "s" : ""} from 1Password`);
1548
1834
  } catch (err) {
1549
1835
  spinner.warn("Failed to load secrets from 1Password");
1550
- logger2.debug(err instanceof Error ? err.message : String(err));
1836
+ logger3.debug(err instanceof Error ? err.message : String(err));
1551
1837
  }
1552
1838
  }
1553
1839
  }
@@ -1556,12 +1842,12 @@ async function runLocally(agent, agentName, rootDir, config) {
1556
1842
  const hasVault = await hasVaultCli();
1557
1843
  if (!hasVault) {
1558
1844
  spinner.warn("Vault CLI not found - secrets will not be loaded");
1559
- logger2.info("Install from: https://developer.hashicorp.com/vault/docs/install");
1845
+ logger3.info("Install from: https://developer.hashicorp.com/vault/docs/install");
1560
1846
  } else {
1561
1847
  const authenticated = await isVaultAuthenticated();
1562
1848
  if (!authenticated) {
1563
1849
  spinner.warn("Vault not authenticated - secrets will not be loaded");
1564
- logger2.info("Run: vault login");
1850
+ logger3.info("Run: vault login");
1565
1851
  } else {
1566
1852
  try {
1567
1853
  secrets = await loadSecrets(secretsConfig);
@@ -1569,7 +1855,7 @@ async function runLocally(agent, agentName, rootDir, config) {
1569
1855
  spinner.succeed(`Loaded ${count} secret${count !== 1 ? "s" : ""} from Vault`);
1570
1856
  } catch (err) {
1571
1857
  spinner.warn("Failed to load secrets from Vault");
1572
- logger2.debug(err instanceof Error ? err.message : String(err));
1858
+ logger3.debug(err instanceof Error ? err.message : String(err));
1573
1859
  }
1574
1860
  }
1575
1861
  }
@@ -1585,23 +1871,50 @@ async function runLocally(agent, agentName, rootDir, config) {
1585
1871
  }
1586
1872
  } catch (err) {
1587
1873
  spinner.warn("Failed to load secrets from environment");
1588
- logger2.debug(err instanceof Error ? err.message : String(err));
1874
+ logger3.debug(err instanceof Error ? err.message : String(err));
1589
1875
  }
1590
1876
  }
1591
1877
  }
1592
1878
  const mcpEnv = await prepareMcpEnv(rootDir, config.mcp);
1593
1879
  const mergedEnv = { ...secrets, ...mcpEnv ?? {} };
1594
- const builtArgs = buildAgentArgs(agent, { injectSystemPrompt: true });
1880
+ let contextContent;
1881
+ if (config.context?.files?.length || config.context?.dirs?.length) {
1882
+ const spinner = ora2("Assembling context files...").start();
1883
+ try {
1884
+ const assembled = await assembleContext(rootDir, config.context);
1885
+ if (assembled.files.length > 0) {
1886
+ contextContent = assembled.content;
1887
+ spinner.succeed(
1888
+ `Assembled ${assembled.files.length} context file${assembled.files.length !== 1 ? "s" : ""} (${Math.round(assembled.totalSize / 1024)}KB)`
1889
+ );
1890
+ if (assembled.skippedFiles.length > 0) {
1891
+ logger3.dim(` Skipped ${assembled.skippedFiles.length} file(s)`);
1892
+ }
1893
+ } else {
1894
+ spinner.warn("No context files found");
1895
+ }
1896
+ } catch (err) {
1897
+ spinner.warn("Failed to assemble context files");
1898
+ logger3.debug(err instanceof Error ? err.message : String(err));
1899
+ }
1900
+ }
1901
+ const builtArgs = buildAgentArgs(agent, {
1902
+ injectSystemPrompt: true,
1903
+ ...contextContent && { contextContent }
1904
+ });
1595
1905
  if (isMacOS() && await hasLima()) {
1596
- await runInLimaVm(agent, agentName, rootDir, builtArgs, mergedEnv);
1906
+ await runInLimaVm(agent, agentName, rootDir, builtArgs, mergedEnv, config.lima);
1597
1907
  return;
1598
1908
  }
1599
- logger2.info(`Launching ${logger2.brand(agentName)}...`);
1600
- logger2.dim(`Working directory: ${rootDir}`);
1909
+ logger3.info(`Launching ${logger3.brand(agentName)}...`);
1910
+ logger3.dim(`Working directory: ${rootDir}`);
1601
1911
  if (agentSupportsRuntimeInjection(agent)) {
1602
- logger2.dim("Injecting RAPID methodology via CLI args");
1912
+ logger3.dim("Injecting RAPID methodology via CLI args");
1913
+ if (contextContent) {
1914
+ logger3.dim("Injecting context files via CLI args");
1915
+ }
1603
1916
  }
1604
- logger2.blank();
1917
+ logger3.blank();
1605
1918
  await execa4(agent.cli, builtArgs, {
1606
1919
  cwd: rootDir,
1607
1920
  stdio: "inherit",
@@ -1611,21 +1924,22 @@ async function runLocally(agent, agentName, rootDir, config) {
1611
1924
  }
1612
1925
  });
1613
1926
  }
1614
- async function runInLimaVm(agent, agentName, rootDir, args, env) {
1927
+ async function runInLimaVm(agent, agentName, rootDir, args, env, limaConfig) {
1615
1928
  const spinner = ora2();
1616
1929
  if (!await isRunning()) {
1617
1930
  spinner.start(`Starting Lima VM (${RAPID_LIMA_INSTANCE})...`);
1618
1931
  const result = await startInstance(rootDir, {
1619
1932
  env,
1620
- timeout: 600
1933
+ timeout: 600,
1621
1934
  // 10 minutes for first-time setup
1935
+ ...limaConfig?.installGh !== void 0 && { installGh: limaConfig.installGh }
1622
1936
  });
1623
1937
  if (!result.success) {
1624
1938
  spinner.fail("Failed to start Lima VM");
1625
- logger2.error(result.error ?? "Unknown error");
1626
- logger2.blank();
1627
- logger2.info("Falling back to running directly on host...");
1628
- logger2.blank();
1939
+ logger3.error(result.error ?? "Unknown error");
1940
+ logger3.blank();
1941
+ logger3.info("Falling back to running directly on host...");
1942
+ logger3.blank();
1629
1943
  const { execa: execa4 } = await import("execa");
1630
1944
  await execa4(agent.cli, args, {
1631
1945
  cwd: rootDir,
@@ -1639,12 +1953,32 @@ async function runInLimaVm(agent, agentName, rootDir, args, env) {
1639
1953
  }
1640
1954
  spinner.succeed("Lima VM started");
1641
1955
  } else {
1642
- logger2.info(`Lima VM (${RAPID_LIMA_INSTANCE}) is running`);
1956
+ logger3.info(`Lima VM (${RAPID_LIMA_INSTANCE}) is running`);
1957
+ }
1958
+ spinner.start(`Checking if ${agentName} is installed in Lima VM...`);
1959
+ const installResult = await ensureAgentInstalled(agent.cli);
1960
+ if (!installResult.success) {
1961
+ spinner.fail(`Failed to install ${agentName} in Lima VM`);
1962
+ logger3.error(installResult.error ?? "Unknown error");
1963
+ logger3.blank();
1964
+ logger3.info("Falling back to running directly on host...");
1965
+ logger3.blank();
1966
+ const { execa: execa4 } = await import("execa");
1967
+ await execa4(agent.cli, args, {
1968
+ cwd: rootDir,
1969
+ stdio: "inherit",
1970
+ env: {
1971
+ ...process.env,
1972
+ ...env
1973
+ }
1974
+ });
1975
+ return;
1643
1976
  }
1644
- logger2.info(`Launching ${logger2.brand(agentName)} in Lima VM...`);
1645
- logger2.dim(`Working directory: ${rootDir}`);
1646
- logger2.dim("SSH agent forwarded for commit signing");
1647
- logger2.blank();
1977
+ spinner.succeed(`${agentName} is available in Lima VM`);
1978
+ logger3.info(`Launching ${logger3.brand(agentName)} in Lima VM...`);
1979
+ logger3.dim(`Working directory: ${rootDir}`);
1980
+ logger3.dim("SSH agent forwarded for commit signing");
1981
+ logger3.blank();
1648
1982
  await execInLima([agent.cli, ...args], {
1649
1983
  cwd: rootDir,
1650
1984
  env,
@@ -1653,20 +1987,20 @@ async function runInLimaVm(agent, agentName, rootDir, args, env) {
1653
1987
  });
1654
1988
  }
1655
1989
  function listAgents(config) {
1656
- logger2.header("Available Agents");
1990
+ logger3.header("Available Agents");
1657
1991
  Object.keys(config.agents.available).forEach((name) => {
1658
1992
  const isDefault = name === config.agents.default;
1659
1993
  console.log(
1660
- ` ${isDefault ? logger2.brand("*") : " "} ${name}${isDefault ? logger2.dim(" (default)") : ""}`
1994
+ ` ${isDefault ? logger3.brand("*") : " "} ${name}${isDefault ? logger3.dim(" (default)") : ""}`
1661
1995
  );
1662
1996
  });
1663
- logger2.blank();
1664
- logger2.dim("Use --agent <name> to select a specific agent");
1997
+ logger3.blank();
1998
+ logger3.dim("Use --agent <name> to select a specific agent");
1665
1999
  }
1666
2000
  async function runMultiAgent(config, rootDir, options) {
1667
2001
  const availableAgents = Object.keys(config.agents.available);
1668
2002
  if (availableAgents.length === 0) {
1669
- logger2.error("No agents configured");
2003
+ logger3.error("No agents configured");
1670
2004
  process.exit(1);
1671
2005
  }
1672
2006
  let selectedAgents;
@@ -1674,48 +2008,48 @@ async function runMultiAgent(config, rootDir, options) {
1674
2008
  selectedAgents = options.multi.split(",").map((a) => a.trim()).filter(Boolean);
1675
2009
  for (const name of selectedAgents) {
1676
2010
  if (!config.agents.available[name]) {
1677
- logger2.error(`Agent "${name}" not found in configuration`);
1678
- logger2.info("Available agents: " + availableAgents.join(", "));
2011
+ logger3.error(`Agent "${name}" not found in configuration`);
2012
+ logger3.info("Available agents: " + availableAgents.join(", "));
1679
2013
  process.exit(1);
1680
2014
  }
1681
2015
  }
1682
2016
  } else {
1683
- logger2.header("Multi-Agent Mode");
2017
+ logger3.header("Multi-Agent Mode");
1684
2018
  console.log();
1685
2019
  console.log(" Available agents:");
1686
2020
  for (const name of availableAgents) {
1687
2021
  const isDefault = name === config.agents.default;
1688
- console.log(` ${logger2.brand("\u2022")} ${name}${isDefault ? logger2.dim(" (default)") : ""}`);
2022
+ console.log(` ${logger3.brand("\u2022")} ${name}${isDefault ? logger3.dim(" (default)") : ""}`);
1689
2023
  }
1690
2024
  console.log();
1691
- logger2.info("To run multiple agents, specify them with:");
1692
- console.log(` ${logger2.brand("rapid dev --multi claude,aider")}`);
2025
+ logger3.info("To run multiple agents, specify them with:");
2026
+ console.log(` ${logger3.brand("rapid dev --multi claude,aider")}`);
1693
2027
  console.log();
1694
- logger2.info("Or run agents in separate terminals:");
2028
+ logger3.info("Or run agents in separate terminals:");
1695
2029
  for (const name of availableAgents) {
1696
- console.log(` ${logger2.dim("$")} rapid dev --agent ${name}`);
2030
+ console.log(` ${logger3.dim("$")} rapid dev --agent ${name}`);
1697
2031
  }
1698
2032
  console.log();
1699
- logger2.warn("Note: Running multiple agents simultaneously requires separate terminal windows.");
1700
- logger2.info("Each agent maintains its own session and context.");
2033
+ logger3.warn("Note: Running multiple agents simultaneously requires separate terminal windows.");
2034
+ logger3.info("Each agent maintains its own session and context.");
1701
2035
  console.log();
1702
2036
  return;
1703
2037
  }
1704
2038
  if (selectedAgents.length === 0) {
1705
- logger2.error("No agents specified");
2039
+ logger3.error("No agents specified");
1706
2040
  process.exit(1);
1707
2041
  }
1708
2042
  if (selectedAgents.length === 1) {
1709
- logger2.info(
1710
- `Only one agent specified. Use ${logger2.brand("rapid dev --agent " + selectedAgents[0])} instead.`
2043
+ logger3.info(
2044
+ `Only one agent specified. Use ${logger3.brand("rapid dev --agent " + selectedAgents[0])} instead.`
1711
2045
  );
1712
2046
  process.exit(0);
1713
2047
  }
1714
- logger2.header("Multi-Agent Session");
2048
+ logger3.header("Multi-Agent Session");
1715
2049
  console.log();
1716
2050
  console.log(" Selected agents:");
1717
2051
  for (const name of selectedAgents) {
1718
- console.log(` ${logger2.brand("\u2022")} ${name}`);
2052
+ console.log(` ${logger3.brand("\u2022")} ${name}`);
1719
2053
  }
1720
2054
  console.log();
1721
2055
  const { execa: execa4 } = await import("execa");
@@ -1727,7 +2061,7 @@ async function runMultiAgent(config, rootDir, options) {
1727
2061
  hasTmux = false;
1728
2062
  }
1729
2063
  if (hasTmux) {
1730
- logger2.info("Launching agents in tmux panes...");
2064
+ logger3.info("Launching agents in tmux panes...");
1731
2065
  console.log();
1732
2066
  const sessionName = `rapid-${Date.now()}`;
1733
2067
  const firstAgent = selectedAgents[0];
@@ -1743,29 +2077,29 @@ async function runMultiAgent(config, rootDir, options) {
1743
2077
  });
1744
2078
  await execa4("tmux", ["select-layout", "-t", sessionName, "tiled"]);
1745
2079
  }
1746
- logger2.success(`Started ${selectedAgents.length} agents in tmux session: ${sessionName}`);
2080
+ logger3.success(`Started ${selectedAgents.length} agents in tmux session: ${sessionName}`);
1747
2081
  console.log();
1748
- logger2.info("Attaching to tmux session...");
1749
- logger2.dim("Press Ctrl+B then D to detach, or Ctrl+B then arrow keys to switch panes");
2082
+ logger3.info("Attaching to tmux session...");
2083
+ logger3.dim("Press Ctrl+B then D to detach, or Ctrl+B then arrow keys to switch panes");
1750
2084
  console.log();
1751
2085
  await execa4("tmux", ["attach-session", "-t", sessionName], {
1752
2086
  stdio: "inherit"
1753
2087
  });
1754
2088
  } else {
1755
- logger2.warn("tmux not found. Multi-agent mode works best with tmux installed.");
2089
+ logger3.warn("tmux not found. Multi-agent mode works best with tmux installed.");
1756
2090
  console.log();
1757
- logger2.info("To run multiple agents, open separate terminal windows and run:");
2091
+ logger3.info("To run multiple agents, open separate terminal windows and run:");
1758
2092
  console.log();
1759
2093
  for (const name of selectedAgents) {
1760
2094
  const cmd = options.local ? `--local` : "";
1761
2095
  console.log(
1762
- ` ${logger2.dim("Terminal " + (selectedAgents.indexOf(name) + 1) + ":")} rapid dev --agent ${name} ${cmd}`.trim()
2096
+ ` ${logger3.dim("Terminal " + (selectedAgents.indexOf(name) + 1) + ":")} rapid dev --agent ${name} ${cmd}`.trim()
1763
2097
  );
1764
2098
  }
1765
2099
  console.log();
1766
- logger2.info("Install tmux for integrated multi-pane support:");
1767
- console.log(` ${logger2.dim("macOS:")} brew install tmux`);
1768
- console.log(` ${logger2.dim("Ubuntu:")} sudo apt install tmux`);
2100
+ logger3.info("Install tmux for integrated multi-pane support:");
2101
+ console.log(` ${logger3.dim("macOS:")} brew install tmux`);
2102
+ console.log(` ${logger3.dim("Ubuntu:")} sudo apt install tmux`);
1769
2103
  console.log();
1770
2104
  }
1771
2105
  }
@@ -1775,7 +2109,7 @@ import { Command as Command3 } from "commander";
1775
2109
  import {
1776
2110
  loadConfig as loadConfig2,
1777
2111
  checkAllAgents,
1778
- logger as logger3,
2112
+ logger as logger4,
1779
2113
  getContainerStatus as getContainerStatus2,
1780
2114
  hasDevcontainerCli as hasDevcontainerCli2,
1781
2115
  hasDocker,
@@ -1871,39 +2205,39 @@ var statusCommand = new Command3("status").description("Show environment status"
1871
2205
  return;
1872
2206
  }
1873
2207
  console.log();
1874
- console.log(` ${logger3.brand("RAPID")} Status`);
1875
- console.log(` ${logger3.dim("\u2500".repeat(24))}`);
2208
+ console.log(` ${logger4.brand("RAPID")} Status`);
2209
+ console.log(` ${logger4.dim("\u2500".repeat(24))}`);
1876
2210
  console.log();
1877
- console.log(` ${logger3.dim("Config:")} ${filepath}`);
1878
- console.log(` ${logger3.dim("Root:")} ${rootDir}`);
2211
+ console.log(` ${logger4.dim("Config:")} ${filepath}`);
2212
+ console.log(` ${logger4.dim("Root:")} ${rootDir}`);
1879
2213
  console.log();
1880
- console.log(` ${logger3.dim("Container:")}`);
2214
+ console.log(` ${logger4.dim("Container:")}`);
1881
2215
  if (!devcontainerConfig) {
1882
- console.log(` ${logger3.dim("\u25CB")} ${logger3.dim("No devcontainer.json configured")}`);
2216
+ console.log(` ${logger4.dim("\u25CB")} ${logger4.dim("No devcontainer.json configured")}`);
1883
2217
  } else if (!dockerRunning) {
1884
- console.log(` ${logger3.dim("\u25CB")} ${logger3.dim("Docker not running")}`);
2218
+ console.log(` ${logger4.dim("\u25CB")} ${logger4.dim("Docker not running")}`);
1885
2219
  } else if (!hasDevCli) {
1886
- console.log(` ${logger3.dim("\u25CB")} ${logger3.dim("devcontainer CLI not installed")}`);
2220
+ console.log(` ${logger4.dim("\u25CB")} ${logger4.dim("devcontainer CLI not installed")}`);
1887
2221
  } else if (containerStatus.running) {
1888
2222
  console.log(
1889
- ` ${logger3.brand("\u25CF")} Running ${logger3.dim(`(${containerStatus.containerName})`)}`
2223
+ ` ${logger4.brand("\u25CF")} Running ${logger4.dim(`(${containerStatus.containerName})`)}`
1890
2224
  );
1891
2225
  } else if (containerStatus.exists) {
1892
2226
  console.log(
1893
- ` ${logger3.dim("\u25CB")} Stopped ${logger3.dim(`(${containerStatus.containerName})`)}`
2227
+ ` ${logger4.dim("\u25CB")} Stopped ${logger4.dim(`(${containerStatus.containerName})`)}`
1894
2228
  );
1895
2229
  } else {
1896
- console.log(` ${logger3.dim("\u25CB")} Not started`);
2230
+ console.log(` ${logger4.dim("\u25CB")} Not started`);
1897
2231
  }
1898
2232
  console.log();
1899
2233
  console.log(
1900
- ` ${logger3.dim("Agents:")} ${logger3.dim(`(default: ${config.agents.default})`)}`
2234
+ ` ${logger4.dim("Agents:")} ${logger4.dim(`(default: ${config.agents.default})`)}`
1901
2235
  );
1902
2236
  agentStatuses.forEach((status) => {
1903
2237
  const isDefault = status.name === config.agents.default;
1904
- const icon = status.available ? logger3.brand("\u2713") : logger3.dim("\u25CB");
1905
- const name = isDefault ? logger3.bold(status.name) : status.name;
1906
- const version = status.version ? logger3.dim(` (${status.version})`) : "";
2238
+ const icon = status.available ? logger4.brand("\u2713") : logger4.dim("\u25CB");
2239
+ const name = isDefault ? logger4.bold(status.name) : status.name;
2240
+ const version = status.version ? logger4.dim(` (${status.version})`) : "";
1907
2241
  console.log(` ${icon} ${name}${version}`);
1908
2242
  });
1909
2243
  console.log();
@@ -1911,38 +2245,38 @@ var statusCommand = new Command3("status").description("Show environment status"
1911
2245
  const providerInfo = getProviderInfo(
1912
2246
  secretsStatus.provider
1913
2247
  );
1914
- console.log(` ${logger3.dim("Secrets:")} ${logger3.dim(`(${providerInfo.name})`)}`);
2248
+ console.log(` ${logger4.dim("Secrets:")} ${logger4.dim(`(${providerInfo.name})`)}`);
1915
2249
  if (providerInfo.cliRequired) {
1916
- const cliIcon = secretsStatus.cliInstalled ? logger3.brand("\u2713") : logger3.dim("\u25CB");
2250
+ const cliIcon = secretsStatus.cliInstalled ? logger4.brand("\u2713") : logger4.dim("\u25CB");
1917
2251
  console.log(
1918
2252
  ` ${cliIcon} CLI ${secretsStatus.cliInstalled ? "installed" : "not installed"}`
1919
2253
  );
1920
2254
  if (secretsStatus.cliInstalled) {
1921
- const authIcon = secretsStatus.authenticated ? logger3.brand("\u2713") : logger3.dim("\u25CB");
2255
+ const authIcon = secretsStatus.authenticated ? logger4.brand("\u2713") : logger4.dim("\u25CB");
1922
2256
  console.log(
1923
2257
  ` ${authIcon} ${secretsStatus.authenticated ? "Authenticated" : "Not authenticated"}`
1924
2258
  );
1925
2259
  }
1926
2260
  }
1927
2261
  if (secretsStatus.secretsCount > 0) {
1928
- const allIcon = secretsStatus.allAvailable ? logger3.brand("\u2713") : logger3.dim("\u25CB");
2262
+ const allIcon = secretsStatus.allAvailable ? logger4.brand("\u2713") : logger4.dim("\u25CB");
1929
2263
  console.log(
1930
2264
  ` ${allIcon} ${secretsStatus.secretsCount} secret${secretsStatus.secretsCount !== 1 ? "s" : ""} ${secretsStatus.allAvailable ? "available" : "configured"}`
1931
2265
  );
1932
2266
  }
1933
- const envrcIcon = secretsStatus.envrcExists ? logger3.brand("\u2713") : logger3.dim("\u25CB");
2267
+ const envrcIcon = secretsStatus.envrcExists ? logger4.brand("\u2713") : logger4.dim("\u25CB");
1934
2268
  console.log(
1935
2269
  ` ${envrcIcon} .envrc ${secretsStatus.envrcExists ? "exists" : "not generated"}`
1936
2270
  );
1937
2271
  console.log();
1938
2272
  }
1939
- console.log(` ${logger3.dim("Auth:")}`);
2273
+ console.log(` ${logger4.dim("Auth:")}`);
1940
2274
  if (!authStatus.authenticated) {
1941
- console.log(` ${logger3.dim("\u25CB")} ${logger3.dim("No authentication detected")}`);
1942
- console.log(` ${logger3.dim(" Run `rapid auth` for options")}`);
2275
+ console.log(` ${logger4.dim("\u25CB")} ${logger4.dim("No authentication detected")}`);
2276
+ console.log(` ${logger4.dim(" Run `rapid auth` for options")}`);
1943
2277
  } else {
1944
2278
  for (const cred of authStatus.sources) {
1945
- const icon = cred.authType === "oauth" ? logger3.brand("\u25CF") : logger3.dim("\u25CB");
2279
+ const icon = cred.authType === "oauth" ? logger4.brand("\u25CF") : logger4.dim("\u25CB");
1946
2280
  const authType = cred.authType === "oauth" ? "OAuth" : "API Key";
1947
2281
  let info = `${cred.source} (${cred.provider}, ${authType})`;
1948
2282
  if (cred.accountInfo?.email) {
@@ -1953,32 +2287,32 @@ var statusCommand = new Command3("status").description("Show environment status"
1953
2287
  }
1954
2288
  console.log();
1955
2289
  if (!containerStatus.running && devcontainerConfig && dockerRunning && hasDevCli) {
1956
- logger3.info("Run `rapid start` to start the container");
2290
+ logger4.info("Run `rapid start` to start the container");
1957
2291
  } else if (containerStatus.running) {
1958
- logger3.info("Run `rapid dev` to start coding");
2292
+ logger4.info("Run `rapid dev` to start coding");
1959
2293
  }
1960
2294
  console.log();
1961
2295
  } catch (error) {
1962
- logger3.error(error instanceof Error ? error.message : String(error));
2296
+ logger4.error(error instanceof Error ? error.message : String(error));
1963
2297
  process.exit(1);
1964
2298
  }
1965
2299
  });
1966
2300
 
1967
2301
  // src/commands/agent.ts
1968
- import { writeFile as writeFile4 } from "fs/promises";
2302
+ import { writeFile as writeFile5 } from "fs/promises";
1969
2303
  import { Command as Command4 } from "commander";
1970
- import { loadConfig as loadConfig3, checkAllAgents as checkAllAgents2, logger as logger4 } from "@a3t/rapid-core";
2304
+ import { loadConfig as loadConfig3, checkAllAgents as checkAllAgents2, logger as logger5, formatJson as formatJson4 } from "@a3t/rapid-core";
1971
2305
  var agentCommand = new Command4("agent").description("Manage AI agents");
1972
2306
  agentCommand.command("list").description("List available agents").action(async () => {
1973
2307
  try {
1974
2308
  const loaded = await loadConfig3();
1975
2309
  if (!loaded) {
1976
- logger4.error("No rapid.json found. Run `rapid init` first.");
2310
+ logger5.error("No rapid.json found. Run `rapid init` first.");
1977
2311
  process.exit(1);
1978
2312
  }
1979
2313
  const { config } = loaded;
1980
2314
  const statuses = await checkAllAgents2(config);
1981
- logger4.header("Available Agents");
2315
+ logger5.header("Available Agents");
1982
2316
  statuses.forEach((status) => {
1983
2317
  const isDefault = status.name === config.agents.default;
1984
2318
  const icon = status.available ? "\u2713" : "\u25CB";
@@ -1986,17 +2320,17 @@ agentCommand.command("list").description("List available agents").action(async (
1986
2320
  const versionTag = status.version ? ` - ${status.version}` : "";
1987
2321
  if (status.available) {
1988
2322
  console.log(
1989
- ` ${logger4.brand(icon)} ${status.name}${defaultTag}${logger4.dim(versionTag)}`
2323
+ ` ${logger5.brand(icon)} ${status.name}${defaultTag}${logger5.dim(versionTag)}`
1990
2324
  );
1991
2325
  } else {
1992
2326
  console.log(
1993
- ` ${logger4.dim(icon)} ${logger4.dim(status.name)}${defaultTag} ${logger4.dim("[not installed]")}`
2327
+ ` ${logger5.dim(icon)} ${logger5.dim(status.name)}${defaultTag} ${logger5.dim("[not installed]")}`
1994
2328
  );
1995
2329
  }
1996
2330
  });
1997
- logger4.blank();
2331
+ logger5.blank();
1998
2332
  } catch (error) {
1999
- logger4.error(error instanceof Error ? error.message : String(error));
2333
+ logger5.error(error instanceof Error ? error.message : String(error));
2000
2334
  process.exit(1);
2001
2335
  }
2002
2336
  });
@@ -2004,7 +2338,7 @@ agentCommand.command("default [name]").description("Get or set default agent").a
2004
2338
  try {
2005
2339
  const loaded = await loadConfig3();
2006
2340
  if (!loaded) {
2007
- logger4.error("No rapid.json found. Run `rapid init` first.");
2341
+ logger5.error("No rapid.json found. Run `rapid init` first.");
2008
2342
  process.exit(1);
2009
2343
  }
2010
2344
  const { config } = loaded;
@@ -2013,18 +2347,18 @@ agentCommand.command("default [name]").description("Get or set default agent").a
2013
2347
  return;
2014
2348
  }
2015
2349
  if (!config.agents.available[name]) {
2016
- logger4.error(`Agent "${name}" not found in configuration`);
2017
- logger4.info("Available agents:");
2350
+ logger5.error(`Agent "${name}" not found in configuration`);
2351
+ logger5.info("Available agents:");
2018
2352
  Object.keys(config.agents.available).forEach((n) => {
2019
2353
  console.log(` - ${n}`);
2020
2354
  });
2021
2355
  process.exit(1);
2022
2356
  }
2023
2357
  config.agents.default = name;
2024
- await writeFile4(loaded.filepath, JSON.stringify(config, null, 2) + "\n");
2025
- logger4.success(`Default agent set to "${name}"`);
2358
+ await writeFile5(loaded.filepath, await formatJson4(config));
2359
+ logger5.success(`Default agent set to "${name}"`);
2026
2360
  } catch (error) {
2027
- logger4.error(error instanceof Error ? error.message : String(error));
2361
+ logger5.error(error instanceof Error ? error.message : String(error));
2028
2362
  process.exit(1);
2029
2363
  }
2030
2364
  });
@@ -2032,14 +2366,14 @@ agentCommand.command("yolo [name]").description("Enable YOLO mode (skip all perm
2032
2366
  try {
2033
2367
  const loaded = await loadConfig3();
2034
2368
  if (!loaded) {
2035
- logger4.error("No rapid.json found. Run `rapid init` first.");
2369
+ logger5.error("No rapid.json found. Run `rapid init` first.");
2036
2370
  process.exit(1);
2037
2371
  }
2038
2372
  const { config } = loaded;
2039
2373
  const agentName = name || config.agents.default;
2040
2374
  if (!config.agents.available[agentName]) {
2041
- logger4.error(`Agent "${agentName}" not found in configuration`);
2042
- logger4.info("Available agents:");
2375
+ logger5.error(`Agent "${agentName}" not found in configuration`);
2376
+ logger5.info("Available agents:");
2043
2377
  Object.keys(config.agents.available).forEach((n) => {
2044
2378
  console.log(` - ${n}`);
2045
2379
  });
@@ -2048,19 +2382,19 @@ agentCommand.command("yolo [name]").description("Enable YOLO mode (skip all perm
2048
2382
  const agent = config.agents.available[agentName];
2049
2383
  const enabling = !options.off;
2050
2384
  if (enabling && agent.cli !== "claude") {
2051
- logger4.warn(`YOLO mode is only supported for Claude (${agentName} uses ${agent.cli})`);
2052
- logger4.info("Continuing anyway...");
2385
+ logger5.warn(`YOLO mode is only supported for Claude (${agentName} uses ${agent.cli})`);
2386
+ logger5.info("Continuing anyway...");
2053
2387
  }
2054
2388
  agent.yolo = enabling;
2055
- await writeFile4(loaded.filepath, JSON.stringify(config, null, 2) + "\n");
2389
+ await writeFile5(loaded.filepath, await formatJson4(config));
2056
2390
  if (enabling) {
2057
- logger4.success(`YOLO mode enabled for "${agentName}"`);
2058
- logger4.dim("Permission prompts will be skipped (--dangerously-skip-permissions)");
2391
+ logger5.success(`YOLO mode enabled for "${agentName}"`);
2392
+ logger5.dim("Permission prompts will be skipped (--dangerously-skip-permissions)");
2059
2393
  } else {
2060
- logger4.success(`YOLO mode disabled for "${agentName}"`);
2394
+ logger5.success(`YOLO mode disabled for "${agentName}"`);
2061
2395
  }
2062
2396
  } catch (error) {
2063
- logger4.error(error instanceof Error ? error.message : String(error));
2397
+ logger5.error(error instanceof Error ? error.message : String(error));
2064
2398
  process.exit(1);
2065
2399
  }
2066
2400
  });
@@ -2069,7 +2403,7 @@ agentCommand.command("yolo [name]").description("Enable YOLO mode (skip all perm
2069
2403
  import { Command as Command5 } from "commander";
2070
2404
  import {
2071
2405
  loadConfig as loadConfig4,
2072
- logger as logger5,
2406
+ logger as logger6,
2073
2407
  hasDevcontainerCli as hasDevcontainerCli3,
2074
2408
  hasDocker as hasDocker2,
2075
2409
  loadDevcontainerConfig as loadDevcontainerConfig2,
@@ -2091,36 +2425,36 @@ var startCommand = new Command5("start").description("Start the development cont
2091
2425
  const hasDevCli = await hasDevcontainerCli3();
2092
2426
  if (!hasDevCli) {
2093
2427
  spinner.fail("devcontainer CLI not found");
2094
- logger5.blank();
2095
- logger5.info("Install with:");
2428
+ logger6.blank();
2429
+ logger6.info("Install with:");
2096
2430
  console.log(" npm install -g @devcontainers/cli");
2097
- logger5.blank();
2431
+ logger6.blank();
2098
2432
  process.exit(1);
2099
2433
  }
2100
2434
  spinner.text = "Checking Docker...";
2101
2435
  const dockerAvailable = await hasDocker2();
2102
2436
  if (!dockerAvailable) {
2103
2437
  spinner.fail("Docker is not running");
2104
- logger5.info("Please start Docker Desktop and try again.");
2438
+ logger6.info("Please start Docker Desktop and try again.");
2105
2439
  process.exit(1);
2106
2440
  }
2107
2441
  spinner.text = "Checking devcontainer configuration...";
2108
2442
  const devcontainerConfig = await loadDevcontainerConfig2(rootDir, config);
2109
2443
  if (!devcontainerConfig) {
2110
2444
  spinner.fail("No devcontainer.json found");
2111
- logger5.blank();
2112
- logger5.info("Create a .devcontainer/devcontainer.json or run:");
2445
+ logger6.blank();
2446
+ logger6.info("Create a .devcontainer/devcontainer.json or run:");
2113
2447
  console.log(" rapid init --template <template>");
2114
- logger5.blank();
2448
+ logger6.blank();
2115
2449
  process.exit(1);
2116
2450
  }
2117
2451
  spinner.text = "Checking container status...";
2118
2452
  const status = await getContainerStatus3(rootDir, config);
2119
2453
  if (status.running && !options.rebuild) {
2120
2454
  spinner.succeed("Container already running");
2121
- logger5.info(`Container: ${status.containerName}`);
2122
- logger5.blank();
2123
- logger5.info("Run `rapid dev` to start coding");
2455
+ logger6.info(`Container: ${status.containerName}`);
2456
+ logger6.blank();
2457
+ logger6.info("Run `rapid dev` to start coding");
2124
2458
  return;
2125
2459
  }
2126
2460
  spinner.text = options.rebuild ? "Rebuilding container..." : "Starting container...";
@@ -2130,28 +2464,28 @@ var startCommand = new Command5("start").description("Start the development cont
2130
2464
  quiet: false
2131
2465
  });
2132
2466
  if (!result.success) {
2133
- logger5.blank();
2134
- logger5.error("Failed to start container");
2135
- logger5.error(result.error || "Unknown error");
2467
+ logger6.blank();
2468
+ logger6.error("Failed to start container");
2469
+ logger6.error(result.error || "Unknown error");
2136
2470
  process.exit(1);
2137
2471
  }
2138
- logger5.blank();
2139
- logger5.success("Development environment ready!");
2140
- logger5.blank();
2141
- logger5.info("Next steps:");
2142
- console.log(` ${logger5.dim("\u2022")} Run ${logger5.brand("rapid dev")} to start coding`);
2143
- console.log(` ${logger5.dim("\u2022")} Run ${logger5.brand("rapid stop")} when done`);
2144
- logger5.blank();
2472
+ logger6.blank();
2473
+ logger6.success("Development environment ready!");
2474
+ logger6.blank();
2475
+ logger6.info("Next steps:");
2476
+ console.log(` ${logger6.dim("\u2022")} Run ${logger6.brand("rapid dev")} to start coding`);
2477
+ console.log(` ${logger6.dim("\u2022")} Run ${logger6.brand("rapid stop")} when done`);
2478
+ logger6.blank();
2145
2479
  } catch (error) {
2146
2480
  spinner.fail("Failed to start environment");
2147
- logger5.error(error instanceof Error ? error.message : String(error));
2481
+ logger6.error(error instanceof Error ? error.message : String(error));
2148
2482
  process.exit(1);
2149
2483
  }
2150
2484
  });
2151
2485
 
2152
2486
  // src/commands/stop.ts
2153
2487
  import { Command as Command6 } from "commander";
2154
- import { loadConfig as loadConfig5, logger as logger6, getContainerStatus as getContainerStatus4, stopContainer } from "@a3t/rapid-core";
2488
+ import { loadConfig as loadConfig5, logger as logger7, getContainerStatus as getContainerStatus4, stopContainer } from "@a3t/rapid-core";
2155
2489
  import ora5 from "ora";
2156
2490
  var stopCommand = new Command6("stop").description("Stop the development container").option("--remove", "Remove container after stopping", false).action(async (options) => {
2157
2491
  const spinner = ora5("Stopping development environment...").start();
@@ -2182,13 +2516,13 @@ var stopCommand = new Command6("stop").description("Stop the development contain
2182
2516
  const result = await stopContainer(rootDir, config, { remove: options.remove });
2183
2517
  if (!result.success) {
2184
2518
  spinner.fail("Failed to stop container");
2185
- logger6.error(result.error || "Unknown error");
2519
+ logger7.error(result.error || "Unknown error");
2186
2520
  process.exit(1);
2187
2521
  }
2188
2522
  spinner.succeed(options.remove ? "Container stopped and removed" : "Container stopped");
2189
2523
  } catch (error) {
2190
2524
  spinner.fail("Failed to stop environment");
2191
- logger6.error(error instanceof Error ? error.message : String(error));
2525
+ logger7.error(error instanceof Error ? error.message : String(error));
2192
2526
  process.exit(1);
2193
2527
  }
2194
2528
  });
@@ -2197,7 +2531,7 @@ var stopCommand = new Command6("stop").description("Stop the development contain
2197
2531
  import { Command as Command7 } from "commander";
2198
2532
  import {
2199
2533
  loadConfig as loadConfig6,
2200
- logger as logger7,
2534
+ logger as logger8,
2201
2535
  verifySecrets as verifySecrets2,
2202
2536
  loadSecrets as loadSecrets2,
2203
2537
  hasOpCli as hasOpCli3,
@@ -2234,15 +2568,15 @@ secretsCommand.command("verify").description("Verify all secrets are accessible"
2234
2568
  if (!hasOp) {
2235
2569
  spinner.fail("1Password CLI (op) not found");
2236
2570
  console.log();
2237
- logger7.info("Install with: brew install 1password-cli");
2238
- logger7.info("More info: https://developer.1password.com/docs/cli/get-started/");
2571
+ logger8.info("Install with: brew install 1password-cli");
2572
+ logger8.info("More info: https://developer.1password.com/docs/cli/get-started/");
2239
2573
  process.exit(1);
2240
2574
  }
2241
2575
  const authenticated = await isOpAuthenticated3();
2242
2576
  if (!authenticated) {
2243
2577
  spinner.fail("1Password CLI not authenticated");
2244
2578
  console.log();
2245
- logger7.info("Run: eval $(op signin)");
2579
+ logger8.info("Run: eval $(op signin)");
2246
2580
  process.exit(1);
2247
2581
  }
2248
2582
  } else if (provider === "vault") {
@@ -2250,14 +2584,14 @@ secretsCommand.command("verify").description("Verify all secrets are accessible"
2250
2584
  if (!hasVault) {
2251
2585
  spinner.fail("Vault CLI not found");
2252
2586
  console.log();
2253
- logger7.info("Install from: https://developer.hashicorp.com/vault/docs/install");
2587
+ logger8.info("Install from: https://developer.hashicorp.com/vault/docs/install");
2254
2588
  process.exit(1);
2255
2589
  }
2256
2590
  const authenticated = await isVaultAuthenticated3();
2257
2591
  if (!authenticated) {
2258
2592
  spinner.fail("Vault CLI not authenticated");
2259
2593
  console.log();
2260
- logger7.info("Run: vault login");
2594
+ logger8.info("Run: vault login");
2261
2595
  process.exit(1);
2262
2596
  }
2263
2597
  }
@@ -2269,37 +2603,37 @@ secretsCommand.command("verify").description("Verify all secrets are accessible"
2269
2603
  return;
2270
2604
  }
2271
2605
  console.log();
2272
- console.log(` ${logger7.brand("Secrets")} Verification`);
2273
- console.log(` ${logger7.dim("\u2500".repeat(24))}`);
2606
+ console.log(` ${logger8.brand("Secrets")} Verification`);
2607
+ console.log(` ${logger8.dim("\u2500".repeat(24))}`);
2274
2608
  console.log();
2275
- console.log(` ${logger7.dim("Provider:")} ${getProviderInfo2(provider).name}`);
2609
+ console.log(` ${logger8.dim("Provider:")} ${getProviderInfo2(provider).name}`);
2276
2610
  console.log(
2277
- ` ${logger7.dim("Auth:")} ${status.authenticated ? logger7.brand("\u2713") : logger7.dim("\u25CB")} ${status.authenticated ? "Authenticated" : "Not authenticated"}`
2611
+ ` ${logger8.dim("Auth:")} ${status.authenticated ? logger8.brand("\u2713") : logger8.dim("\u25CB")} ${status.authenticated ? "Authenticated" : "Not authenticated"}`
2278
2612
  );
2279
2613
  console.log();
2280
2614
  if (status.secrets.length === 0) {
2281
- console.log(` ${logger7.dim("No secrets configured in rapid.json")}`);
2615
+ console.log(` ${logger8.dim("No secrets configured in rapid.json")}`);
2282
2616
  console.log();
2283
2617
  return;
2284
2618
  }
2285
- console.log(` ${logger7.dim("Secrets:")}`);
2619
+ console.log(` ${logger8.dim("Secrets:")}`);
2286
2620
  for (const secret of status.secrets) {
2287
- const icon = secret.available ? logger7.brand("\u2713") : "\u2717";
2288
- const ref = logger7.dim(`(${provider})`);
2289
- const error = secret.error ? logger7.dim(` - ${secret.error}`) : "";
2621
+ const icon = secret.available ? logger8.brand("\u2713") : "\u2717";
2622
+ const ref = logger8.dim(`(${provider})`);
2623
+ const error = secret.error ? logger8.dim(` - ${secret.error}`) : "";
2290
2624
  console.log(` ${icon} ${secret.name} ${ref}${error}`);
2291
2625
  }
2292
2626
  console.log();
2293
2627
  if (status.allAvailable) {
2294
- logger7.info("All secrets verified successfully!");
2628
+ logger8.info("All secrets verified successfully!");
2295
2629
  } else {
2296
- logger7.error("Some secrets are not available");
2630
+ logger8.error("Some secrets are not available");
2297
2631
  process.exit(1);
2298
2632
  }
2299
2633
  console.log();
2300
2634
  } catch (error) {
2301
2635
  spinner.fail("Failed to verify secrets");
2302
- logger7.error(error instanceof Error ? error.message : String(error));
2636
+ logger8.error(error instanceof Error ? error.message : String(error));
2303
2637
  process.exit(1);
2304
2638
  }
2305
2639
  });
@@ -2307,7 +2641,7 @@ secretsCommand.command("list").description("List configured secrets (names only,
2307
2641
  try {
2308
2642
  const loaded = await loadConfig6();
2309
2643
  if (!loaded) {
2310
- logger7.error("No rapid.json found");
2644
+ logger8.error("No rapid.json found");
2311
2645
  process.exit(1);
2312
2646
  }
2313
2647
  const { config } = loaded;
@@ -2316,7 +2650,7 @@ secretsCommand.command("list").description("List configured secrets (names only,
2316
2650
  if (options.json) {
2317
2651
  console.log(JSON.stringify({ secrets: [] }, null, 2));
2318
2652
  } else {
2319
- logger7.info("No secrets configured");
2653
+ logger8.info("No secrets configured");
2320
2654
  }
2321
2655
  return;
2322
2656
  }
@@ -2331,19 +2665,19 @@ secretsCommand.command("list").description("List configured secrets (names only,
2331
2665
  return;
2332
2666
  }
2333
2667
  console.log();
2334
- console.log(` ${logger7.brand("Configured Secrets")}`);
2335
- console.log(` ${logger7.dim("\u2500".repeat(24))}`);
2668
+ console.log(` ${logger8.brand("Configured Secrets")}`);
2669
+ console.log(` ${logger8.dim("\u2500".repeat(24))}`);
2336
2670
  console.log();
2337
- console.log(` ${logger7.dim("Provider:")} ${getProviderInfo2(provider).name}`);
2671
+ console.log(` ${logger8.dim("Provider:")} ${getProviderInfo2(provider).name}`);
2338
2672
  console.log();
2339
2673
  const maxNameLen = Math.max(...Object.keys(secretsConfig.items).map((n) => n.length));
2340
2674
  for (const [name, reference] of Object.entries(secretsConfig.items)) {
2341
2675
  const paddedName = name.padEnd(maxNameLen);
2342
- console.log(` ${logger7.brand("\u2022")} ${paddedName} ${logger7.dim(reference)}`);
2676
+ console.log(` ${logger8.brand("\u2022")} ${paddedName} ${logger8.dim(reference)}`);
2343
2677
  }
2344
2678
  console.log();
2345
2679
  } catch (error) {
2346
- logger7.error(error instanceof Error ? error.message : String(error));
2680
+ logger8.error(error instanceof Error ? error.message : String(error));
2347
2681
  process.exit(1);
2348
2682
  }
2349
2683
  });
@@ -2351,13 +2685,13 @@ secretsCommand.command("generate").description("Generate .envrc file from rapid.
2351
2685
  try {
2352
2686
  const loaded = await loadConfig6();
2353
2687
  if (!loaded) {
2354
- logger7.error("No rapid.json found");
2688
+ logger8.error("No rapid.json found");
2355
2689
  process.exit(1);
2356
2690
  }
2357
2691
  const { config, rootDir } = loaded;
2358
2692
  const secretsConfig = config.secrets;
2359
2693
  if (!secretsConfig) {
2360
- logger7.error("No secrets configuration in rapid.json");
2694
+ logger8.error("No secrets configuration in rapid.json");
2361
2695
  process.exit(1);
2362
2696
  }
2363
2697
  const content = generateEnvrc(secretsConfig);
@@ -2367,21 +2701,21 @@ secretsCommand.command("generate").description("Generate .envrc file from rapid.
2367
2701
  }
2368
2702
  const envrcExists = await hasEnvrc2(rootDir, secretsConfig);
2369
2703
  if (envrcExists && !options.force) {
2370
- logger7.error(".envrc already exists. Use --force to overwrite.");
2704
+ logger8.error(".envrc already exists. Use --force to overwrite.");
2371
2705
  process.exit(1);
2372
2706
  }
2373
2707
  const spinner = ora6("Generating .envrc...").start();
2374
2708
  const filepath = await writeEnvrc(rootDir, secretsConfig);
2375
2709
  spinner.succeed("Generated .envrc");
2376
2710
  console.log();
2377
- console.log(` ${logger7.dim("File:")} ${filepath}`);
2711
+ console.log(` ${logger8.dim("File:")} ${filepath}`);
2378
2712
  console.log();
2379
2713
  const itemCount = secretsConfig.items ? Object.keys(secretsConfig.items).length : 0;
2380
- logger7.info(`Generated .envrc with ${itemCount} secret${itemCount !== 1 ? "s" : ""}`);
2381
- logger7.info(`Run ${logger7.brand("direnv allow")} to activate`);
2714
+ logger8.info(`Generated .envrc with ${itemCount} secret${itemCount !== 1 ? "s" : ""}`);
2715
+ logger8.info(`Run ${logger8.brand("direnv allow")} to activate`);
2382
2716
  console.log();
2383
2717
  } catch (error) {
2384
- logger7.error(error instanceof Error ? error.message : String(error));
2718
+ logger8.error(error instanceof Error ? error.message : String(error));
2385
2719
  process.exit(1);
2386
2720
  }
2387
2721
  });
@@ -2433,59 +2767,59 @@ secretsCommand.command("info").description("Show secrets provider information an
2433
2767
  return;
2434
2768
  }
2435
2769
  console.log();
2436
- console.log(` ${logger7.brand("Secrets")} Provider Info`);
2437
- console.log(` ${logger7.dim("\u2500".repeat(24))}`);
2770
+ console.log(` ${logger8.brand("Secrets")} Provider Info`);
2771
+ console.log(` ${logger8.dim("\u2500".repeat(24))}`);
2438
2772
  console.log();
2439
- console.log(` ${logger7.dim("Provider:")} ${info.name}`);
2773
+ console.log(` ${logger8.dim("Provider:")} ${info.name}`);
2440
2774
  if (info.cliRequired) {
2441
- const cliIcon = cliInstalled ? logger7.brand("\u2713") : "\u2717";
2775
+ const cliIcon = cliInstalled ? logger8.brand("\u2713") : "\u2717";
2442
2776
  console.log(
2443
- ` ${logger7.dim("CLI:")} ${cliIcon} ${info.cliRequired} ${cliInstalled ? "" : logger7.dim("(not installed)")}`
2777
+ ` ${logger8.dim("CLI:")} ${cliIcon} ${info.cliRequired} ${cliInstalled ? "" : logger8.dim("(not installed)")}`
2444
2778
  );
2445
2779
  if (cliInstalled && provider === "1password" && opAuthStatus) {
2446
- const authIcon = authenticated ? logger7.brand("\u2713") : "\u2717";
2780
+ const authIcon = authenticated ? logger8.brand("\u2713") : "\u2717";
2447
2781
  const methodLabel = opAuthStatus.method === "service-account" ? "Service Account" : opAuthStatus.method === "user" ? "User" : "Not authenticated";
2448
2782
  const accountLabel = opAuthStatus.accountInfo ? ` (${opAuthStatus.accountInfo})` : "";
2449
- console.log(` ${logger7.dim("Auth:")} ${authIcon} ${methodLabel}${accountLabel}`);
2783
+ console.log(` ${logger8.dim("Auth:")} ${authIcon} ${methodLabel}${accountLabel}`);
2450
2784
  if (hasServiceToken) {
2451
2785
  console.log(
2452
- ` ${logger7.dim("Token:")} ${logger7.brand("\u2713")} OP_SERVICE_ACCOUNT_TOKEN set`
2786
+ ` ${logger8.dim("Token:")} ${logger8.brand("\u2713")} OP_SERVICE_ACCOUNT_TOKEN set`
2453
2787
  );
2454
2788
  }
2455
2789
  } else if (cliInstalled) {
2456
- const authIcon = authenticated ? logger7.brand("\u2713") : "\u2717";
2790
+ const authIcon = authenticated ? logger8.brand("\u2713") : "\u2717";
2457
2791
  console.log(
2458
- ` ${logger7.dim("Auth:")} ${authIcon} ${authenticated ? "Authenticated" : "Not authenticated"}`
2792
+ ` ${logger8.dim("Auth:")} ${authIcon} ${authenticated ? "Authenticated" : "Not authenticated"}`
2459
2793
  );
2460
2794
  }
2461
2795
  if (info.installUrl && !cliInstalled) {
2462
2796
  console.log();
2463
- console.log(` ${logger7.dim("Install:")} ${info.installUrl}`);
2797
+ console.log(` ${logger8.dim("Install:")} ${info.installUrl}`);
2464
2798
  }
2465
2799
  if (info.authCommand && cliInstalled && !authenticated) {
2466
2800
  console.log();
2467
- console.log(` ${logger7.dim("Authenticate:")} ${info.authCommand}`);
2801
+ console.log(` ${logger8.dim("Authenticate:")} ${info.authCommand}`);
2468
2802
  if (provider === "1password") {
2469
2803
  console.log(
2470
- ` ${logger7.dim("Or set:")} OP_SERVICE_ACCOUNT_TOKEN for non-interactive auth`
2804
+ ` ${logger8.dim("Or set:")} OP_SERVICE_ACCOUNT_TOKEN for non-interactive auth`
2471
2805
  );
2472
2806
  }
2473
2807
  }
2474
2808
  }
2475
2809
  console.log();
2476
- const envrcIcon = envrcExists ? logger7.brand("\u2713") : logger7.dim("\u25CB");
2810
+ const envrcIcon = envrcExists ? logger8.brand("\u2713") : logger8.dim("\u25CB");
2477
2811
  console.log(
2478
- ` ${logger7.dim(".envrc:")} ${envrcIcon} ${envrcExists ? "Exists" : "Not generated"}`
2812
+ ` ${logger8.dim(".envrc:")} ${envrcIcon} ${envrcExists ? "Exists" : "Not generated"}`
2479
2813
  );
2480
- console.log(` ${logger7.dim("Secrets:")} ${status.secretsCount} configured`);
2814
+ console.log(` ${logger8.dim("Secrets:")} ${status.secretsCount} configured`);
2481
2815
  console.log();
2482
2816
  if (!envrcExists && status.secretsCount > 0) {
2483
- logger7.info(`Run ${logger7.brand("rapid secrets generate")} to create .envrc`);
2817
+ logger8.info(`Run ${logger8.brand("rapid secrets generate")} to create .envrc`);
2484
2818
  console.log();
2485
2819
  }
2486
2820
  } catch (error) {
2487
2821
  spinner.fail("Failed to get provider info");
2488
- logger7.error(error instanceof Error ? error.message : String(error));
2822
+ logger8.error(error instanceof Error ? error.message : String(error));
2489
2823
  process.exit(1);
2490
2824
  }
2491
2825
  });
@@ -2493,45 +2827,45 @@ secretsCommand.command("run").description("Run a command with secrets loaded int
2493
2827
  try {
2494
2828
  const loaded = await loadConfig6();
2495
2829
  if (!loaded) {
2496
- logger7.error("No rapid.json found");
2830
+ logger8.error("No rapid.json found");
2497
2831
  process.exit(1);
2498
2832
  }
2499
2833
  const { config } = loaded;
2500
2834
  const secretsConfig = config.secrets;
2501
2835
  if (!secretsConfig || !secretsConfig.items) {
2502
- logger7.error("No secrets configured in rapid.json");
2836
+ logger8.error("No secrets configured in rapid.json");
2503
2837
  process.exit(1);
2504
2838
  }
2505
2839
  const provider = secretsConfig.provider || "env";
2506
2840
  if (provider === "1password") {
2507
2841
  const hasOp = await hasOpCli3();
2508
2842
  if (!hasOp) {
2509
- logger7.error("1Password CLI (op) not found");
2510
- logger7.info("Install with: brew install 1password-cli");
2843
+ logger8.error("1Password CLI (op) not found");
2844
+ logger8.info("Install with: brew install 1password-cli");
2511
2845
  process.exit(1);
2512
2846
  }
2513
2847
  const authenticated = await isOpAuthenticated3();
2514
2848
  if (!authenticated) {
2515
- logger7.error("1Password not authenticated");
2516
- logger7.info("Run: eval $(op signin)");
2849
+ logger8.error("1Password not authenticated");
2850
+ logger8.info("Run: eval $(op signin)");
2517
2851
  process.exit(1);
2518
2852
  }
2519
2853
  }
2520
2854
  const secrets = await loadSecrets2(secretsConfig);
2521
2855
  const secretCount = Object.keys(secrets).length;
2522
2856
  if (secretCount === 0) {
2523
- logger7.warn("No secrets were loaded");
2857
+ logger8.warn("No secrets were loaded");
2524
2858
  } else if (options.show) {
2525
- logger7.info(`Loaded ${secretCount} secret${secretCount !== 1 ? "s" : ""}:`);
2859
+ logger8.info(`Loaded ${secretCount} secret${secretCount !== 1 ? "s" : ""}:`);
2526
2860
  for (const name of Object.keys(secrets)) {
2527
- console.log(` ${logger7.brand("\u2022")} ${name}`);
2861
+ console.log(` ${logger8.brand("\u2022")} ${name}`);
2528
2862
  }
2529
2863
  console.log();
2530
2864
  }
2531
2865
  const { execa: execa4 } = await import("execa");
2532
2866
  const [cmd, ...args] = commandArgs;
2533
2867
  if (!cmd) {
2534
- logger7.error("No command specified");
2868
+ logger8.error("No command specified");
2535
2869
  process.exit(1);
2536
2870
  }
2537
2871
  await execa4(cmd, args, {
@@ -2545,7 +2879,7 @@ secretsCommand.command("run").description("Run a command with secrets loaded int
2545
2879
  if (error.exitCode !== void 0) {
2546
2880
  process.exit(error.exitCode);
2547
2881
  }
2548
- logger7.error(error instanceof Error ? error.message : String(error));
2882
+ logger8.error(error instanceof Error ? error.message : String(error));
2549
2883
  process.exit(1);
2550
2884
  }
2551
2885
  });
@@ -2553,7 +2887,7 @@ secretsCommand.command("run").description("Run a command with secrets loaded int
2553
2887
  // src/commands/auth.ts
2554
2888
  import { Command as Command8 } from "commander";
2555
2889
  import {
2556
- logger as logger8,
2890
+ logger as logger9,
2557
2891
  getAuthStatus as getAuthStatus2,
2558
2892
  detectAllCredentials
2559
2893
  } from "@a3t/rapid-core";
@@ -2597,24 +2931,24 @@ var authCommand = new Command8("auth").description("Show authentication status f
2597
2931
  return;
2598
2932
  }
2599
2933
  console.log();
2600
- console.log(` ${logger8.brand("RAPID")} Authentication`);
2601
- console.log(` ${logger8.dim("\u2500".repeat(24))}`);
2934
+ console.log(` ${logger9.brand("RAPID")} Authentication`);
2935
+ console.log(` ${logger9.dim("\u2500".repeat(24))}`);
2602
2936
  console.log();
2603
2937
  if (!status.authenticated) {
2604
- console.log(` ${logger8.dim("No authentication detected")}`);
2938
+ console.log(` ${logger9.dim("No authentication detected")}`);
2605
2939
  console.log();
2606
2940
  console.log(" To authenticate, use one of these methods:");
2607
2941
  console.log();
2608
- console.log(` ${logger8.brand("Claude Pro/Max:")}`);
2942
+ console.log(` ${logger9.brand("Claude Pro/Max:")}`);
2609
2943
  console.log(" Run `claude` and sign in with your Anthropic account");
2610
2944
  console.log();
2611
- console.log(` ${logger8.brand("OpenAI (ChatGPT Plus/Pro):")}`);
2945
+ console.log(` ${logger9.brand("OpenAI (ChatGPT Plus/Pro):")}`);
2612
2946
  console.log(" Run `codex` and sign in with ChatGPT");
2613
2947
  console.log();
2614
- console.log(` ${logger8.brand("Gemini:")}`);
2948
+ console.log(` ${logger9.brand("Gemini:")}`);
2615
2949
  console.log(" Run `gemini` and sign in with your Google account");
2616
2950
  console.log();
2617
- console.log(` ${logger8.brand("API Keys:")}`);
2951
+ console.log(` ${logger9.brand("API Keys:")}`);
2618
2952
  console.log(" Set ANTHROPIC_API_KEY, OPENAI_API_KEY, or GEMINI_API_KEY");
2619
2953
  console.log();
2620
2954
  return;
@@ -2623,9 +2957,9 @@ var authCommand = new Command8("auth").description("Show authentication status f
2623
2957
  if (options.source && cred.source !== options.source) continue;
2624
2958
  if (options.provider && cred.provider !== options.provider) continue;
2625
2959
  const isPrimary = cred === status.preferredSource;
2626
- const icon = isPrimary ? logger8.brand("\u25CF") : logger8.dim("\u25CB");
2627
- const authIcon = cred.authType === "oauth" ? logger8.brand("OAuth") : logger8.dim("API Key");
2628
- console.log(` ${icon} ${logger8.bold(cred.source)}`);
2960
+ const icon = isPrimary ? logger9.brand("\u25CF") : logger9.dim("\u25CB");
2961
+ const authIcon = cred.authType === "oauth" ? logger9.brand("OAuth") : logger9.dim("API Key");
2962
+ console.log(` ${icon} ${logger9.bold(cred.source)}`);
2629
2963
  console.log(` Provider: ${cred.provider}`);
2630
2964
  console.log(` Auth: ${authIcon}`);
2631
2965
  if (cred.accountInfo?.email) {
@@ -2635,7 +2969,7 @@ var authCommand = new Command8("auth").description("Show authentication status f
2635
2969
  console.log(` Org: ${cred.accountInfo.organization}`);
2636
2970
  }
2637
2971
  if (cred.accountInfo?.plan) {
2638
- console.log(` Plan: ${logger8.brand(cred.accountInfo.plan)}`);
2972
+ console.log(` Plan: ${logger9.brand(cred.accountInfo.plan)}`);
2639
2973
  }
2640
2974
  if (cred.expiresAt) {
2641
2975
  const now = /* @__PURE__ */ new Date();
@@ -2643,32 +2977,32 @@ var authCommand = new Command8("auth").description("Show authentication status f
2643
2977
  if (expiresIn > 0) {
2644
2978
  console.log(` Expires: in ${expiresIn} minutes`);
2645
2979
  } else {
2646
- console.log(` Expires: ${logger8.dim("EXPIRED")}`);
2980
+ console.log(` Expires: ${logger9.dim("EXPIRED")}`);
2647
2981
  }
2648
2982
  }
2649
2983
  if (cred.configPath) {
2650
- console.log(` Config: ${logger8.dim(cred.configPath)}`);
2984
+ console.log(` Config: ${logger9.dim(cred.configPath)}`);
2651
2985
  }
2652
2986
  if (cred.envVar) {
2653
- console.log(` Env: ${logger8.dim(cred.envVar)}`);
2987
+ console.log(` Env: ${logger9.dim(cred.envVar)}`);
2654
2988
  }
2655
2989
  if (isPrimary) {
2656
- console.log(` ${logger8.brand("\u2192 Primary source")}`);
2990
+ console.log(` ${logger9.brand("\u2192 Primary source")}`);
2657
2991
  }
2658
2992
  console.log();
2659
2993
  }
2660
2994
  if (status.warnings && status.warnings.length > 0) {
2661
- console.log(` ${logger8.dim("Warnings:")}`);
2995
+ console.log(` ${logger9.dim("Warnings:")}`);
2662
2996
  for (const warning of status.warnings) {
2663
2997
  console.log(` ! ${warning}`);
2664
2998
  }
2665
2999
  console.log();
2666
3000
  }
2667
- console.log(` ${logger8.dim("Tip:")} RAPID will automatically use detected`);
2668
- console.log(` ${logger8.dim(" ")} credentials when launching AI agents.`);
3001
+ console.log(` ${logger9.dim("Tip:")} RAPID will automatically use detected`);
3002
+ console.log(` ${logger9.dim(" ")} credentials when launching AI agents.`);
2669
3003
  console.log();
2670
3004
  } catch (error) {
2671
- logger8.error(error instanceof Error ? error.message : String(error));
3005
+ logger9.error(error instanceof Error ? error.message : String(error));
2672
3006
  process.exit(1);
2673
3007
  }
2674
3008
  });
@@ -2714,34 +3048,34 @@ authCommand.command("env").description("Show environment variables for detected
2714
3048
  return;
2715
3049
  }
2716
3050
  console.log();
2717
- console.log(` ${logger8.brand("RAPID")} Auth Environment`);
2718
- console.log(` ${logger8.dim("\u2500".repeat(24))}`);
3051
+ console.log(` ${logger9.brand("RAPID")} Auth Environment`);
3052
+ console.log(` ${logger9.dim("\u2500".repeat(24))}`);
2719
3053
  console.log();
2720
3054
  if (byProvider.size === 0) {
2721
- console.log(` ${logger8.dim("No credentials detected")}`);
3055
+ console.log(` ${logger9.dim("No credentials detected")}`);
2722
3056
  console.log();
2723
3057
  return;
2724
3058
  }
2725
3059
  for (const [provider, { envVar, masked }] of byProvider) {
2726
- console.log(` ${logger8.brand(provider)}`);
3060
+ console.log(` ${logger9.brand(provider)}`);
2727
3061
  console.log(` ${envVar}=${masked}`);
2728
3062
  console.log();
2729
3063
  }
2730
- console.log(` ${logger8.dim("These will be automatically injected when running agents.")}`);
3064
+ console.log(` ${logger9.dim("These will be automatically injected when running agents.")}`);
2731
3065
  console.log();
2732
3066
  } catch (error) {
2733
- logger8.error(error instanceof Error ? error.message : String(error));
3067
+ logger9.error(error instanceof Error ? error.message : String(error));
2734
3068
  process.exit(1);
2735
3069
  }
2736
3070
  });
2737
3071
 
2738
3072
  // src/commands/mcp.ts
2739
3073
  import { Command as Command9 } from "commander";
2740
- import { writeFile as writeFile5 } from "fs/promises";
2741
- import { join as join5 } from "path";
3074
+ import { writeFile as writeFile6 } from "fs/promises";
3075
+ import { join as join6 } from "path";
2742
3076
  import {
2743
3077
  loadConfig as loadConfig7,
2744
- logger as logger9,
3078
+ logger as logger10,
2745
3079
  getMcpServers,
2746
3080
  getMcpServerStatus,
2747
3081
  addMcpServerFromTemplate as addMcpServerFromTemplate2,
@@ -2752,15 +3086,16 @@ import {
2752
3086
  writeMcpConfig as writeMcpConfig2,
2753
3087
  writeOpenCodeConfig as writeOpenCodeConfig2,
2754
3088
  MCP_SERVER_TEMPLATES as MCP_SERVER_TEMPLATES2,
2755
- getMcpTemplate
3089
+ getMcpTemplate,
3090
+ formatJson as formatJson5
2756
3091
  } from "@a3t/rapid-core";
2757
3092
  import ora8 from "ora";
2758
3093
  var mcpCommand = new Command9("mcp").description(
2759
3094
  "Manage MCP (Model Context Protocol) servers"
2760
3095
  );
2761
3096
  async function saveConfig(rootDir, config) {
2762
- const configPath = join5(rootDir, "rapid.json");
2763
- await writeFile5(configPath, JSON.stringify(config, null, 2) + "\n", "utf-8");
3097
+ const configPath = join6(rootDir, "rapid.json");
3098
+ await writeFile6(configPath, await formatJson5(config), "utf-8");
2764
3099
  }
2765
3100
  mcpCommand.command("list").description("List configured MCP servers").option("--json", "Output as JSON").option("--templates", "Show available templates instead of configured servers").action(async (options) => {
2766
3101
  try {
@@ -2770,23 +3105,23 @@ mcpCommand.command("list").description("List configured MCP servers").option("--
2770
3105
  return;
2771
3106
  }
2772
3107
  console.log();
2773
- console.log(` ${logger9.brand("Available MCP Server Templates")}`);
2774
- console.log(` ${logger9.dim("\u2500".repeat(40))}`);
3108
+ console.log(` ${logger10.brand("Available MCP Server Templates")}`);
3109
+ console.log(` ${logger10.dim("\u2500".repeat(40))}`);
2775
3110
  console.log();
2776
3111
  for (const [name, template] of Object.entries(MCP_SERVER_TEMPLATES2)) {
2777
- const typeLabel = template.type === "remote" ? logger9.dim("(remote)") : logger9.dim("(stdio)");
2778
- const secretsLabel = template.requiredSecrets.length > 0 ? logger9.dim(` - requires: ${template.requiredSecrets.join(", ")}`) : logger9.dim(" - no secrets required");
2779
- console.log(` ${logger9.brand("\u2022")} ${name} ${typeLabel}`);
3112
+ const typeLabel = template.type === "remote" ? logger10.dim("(remote)") : logger10.dim("(stdio)");
3113
+ const secretsLabel = template.requiredSecrets.length > 0 ? logger10.dim(` - requires: ${template.requiredSecrets.join(", ")}`) : logger10.dim(" - no secrets required");
3114
+ console.log(` ${logger10.brand("\u2022")} ${name} ${typeLabel}`);
2780
3115
  console.log(` ${template.description}${secretsLabel}`);
2781
3116
  console.log();
2782
3117
  }
2783
- logger9.info(`Use ${logger9.brand("rapid mcp add <name>")} to add a server`);
3118
+ logger10.info(`Use ${logger10.brand("rapid mcp add <name>")} to add a server`);
2784
3119
  console.log();
2785
3120
  return;
2786
3121
  }
2787
3122
  const loaded = await loadConfig7();
2788
3123
  if (!loaded) {
2789
- logger9.error("No rapid.json found. Run `rapid init` first.");
3124
+ logger10.error("No rapid.json found. Run `rapid init` first.");
2790
3125
  process.exit(1);
2791
3126
  }
2792
3127
  const { config } = loaded;
@@ -2796,22 +3131,22 @@ mcpCommand.command("list").description("List configured MCP servers").option("--
2796
3131
  return;
2797
3132
  }
2798
3133
  console.log();
2799
- console.log(` ${logger9.brand("MCP Servers")}`);
2800
- console.log(` ${logger9.dim("\u2500".repeat(40))}`);
3134
+ console.log(` ${logger10.brand("MCP Servers")}`);
3135
+ console.log(` ${logger10.dim("\u2500".repeat(40))}`);
2801
3136
  console.log();
2802
3137
  if (servers.length === 0) {
2803
- console.log(` ${logger9.dim("No MCP servers configured")}`);
3138
+ console.log(` ${logger10.dim("No MCP servers configured")}`);
2804
3139
  console.log();
2805
- logger9.info(`Use ${logger9.brand("rapid mcp add <name>")} to add a server`);
2806
- logger9.info(`Use ${logger9.brand("rapid mcp list --templates")} to see available templates`);
3140
+ logger10.info(`Use ${logger10.brand("rapid mcp add <name>")} to add a server`);
3141
+ logger10.info(`Use ${logger10.brand("rapid mcp list --templates")} to see available templates`);
2807
3142
  console.log();
2808
3143
  return;
2809
3144
  }
2810
3145
  for (const server of servers) {
2811
- const icon = server.enabled ? logger9.brand("\u2713") : logger9.dim("\u25CB");
2812
- const typeLabel = server.type === "remote" ? logger9.dim("(remote)") : logger9.dim("(stdio)");
2813
- const statusLabel = server.enabled ? "" : logger9.dim(" [disabled]");
2814
- const location = server.type === "remote" ? logger9.dim(server.url || "") : logger9.dim(server.command || "");
3146
+ const icon = server.enabled ? logger10.brand("\u2713") : logger10.dim("\u25CB");
3147
+ const typeLabel = server.type === "remote" ? logger10.dim("(remote)") : logger10.dim("(stdio)");
3148
+ const statusLabel = server.enabled ? "" : logger10.dim(" [disabled]");
3149
+ const location = server.type === "remote" ? logger10.dim(server.url || "") : logger10.dim(server.command || "");
2815
3150
  console.log(` ${icon} ${server.name} ${typeLabel}${statusLabel}`);
2816
3151
  if (location) {
2817
3152
  console.log(` ${location}`);
@@ -2819,7 +3154,7 @@ mcpCommand.command("list").description("List configured MCP servers").option("--
2819
3154
  console.log();
2820
3155
  }
2821
3156
  } catch (error) {
2822
- logger9.error(error instanceof Error ? error.message : String(error));
3157
+ logger10.error(error instanceof Error ? error.message : String(error));
2823
3158
  process.exit(1);
2824
3159
  }
2825
3160
  });
@@ -2836,7 +3171,7 @@ mcpCommand.command("add").description("Add an MCP server").argument("<name>", "S
2836
3171
  const existingServers = getMcpServers(config);
2837
3172
  if (existingServers.some((s) => s.name === name)) {
2838
3173
  spinner.fail(`MCP server '${name}' already exists`);
2839
- logger9.info(`Use ${logger9.brand(`rapid mcp remove ${name}`)} to remove it first`);
3174
+ logger10.info(`Use ${logger10.brand(`rapid mcp remove ${name}`)} to remove it first`);
2840
3175
  process.exit(1);
2841
3176
  }
2842
3177
  const template = getMcpTemplate(name);
@@ -2869,8 +3204,8 @@ mcpCommand.command("add").description("Add an MCP server").argument("<name>", "S
2869
3204
  config = addMcpServerFromTemplate2(config, name);
2870
3205
  } else {
2871
3206
  spinner.fail(`Unknown MCP server template: ${name}`);
2872
- logger9.info(`Use ${logger9.brand("rapid mcp list --templates")} to see available templates`);
2873
- logger9.info("Or specify --type, --url, or --command for a custom server");
3207
+ logger10.info(`Use ${logger10.brand("rapid mcp list --templates")} to see available templates`);
3208
+ logger10.info("Or specify --type, --url, or --command for a custom server");
2874
3209
  process.exit(1);
2875
3210
  }
2876
3211
  await saveConfig(rootDir, config);
@@ -2879,18 +3214,18 @@ mcpCommand.command("add").description("Add an MCP server").argument("<name>", "S
2879
3214
  spinner.succeed(`Added MCP server '${name}'`);
2880
3215
  console.log();
2881
3216
  if (template?.requiredSecrets.length) {
2882
- logger9.info("Required secrets:");
3217
+ logger10.info("Required secrets:");
2883
3218
  for (const secret of template.requiredSecrets) {
2884
3219
  const ref = template.secretReferences?.[secret];
2885
- console.log(` ${logger9.brand("\u2022")} ${secret}${ref ? logger9.dim(` (${ref})`) : ""}`);
3220
+ console.log(` ${logger10.brand("\u2022")} ${secret}${ref ? logger10.dim(` (${ref})`) : ""}`);
2886
3221
  }
2887
3222
  console.log();
2888
- logger9.info(`Add these to ${logger9.brand("rapid.json")} secrets.items section`);
3223
+ logger10.info(`Add these to ${logger10.brand("rapid.json")} secrets.items section`);
2889
3224
  console.log();
2890
3225
  }
2891
3226
  } catch (error) {
2892
3227
  spinner.fail("Failed to add MCP server");
2893
- logger9.error(error instanceof Error ? error.message : String(error));
3228
+ logger10.error(error instanceof Error ? error.message : String(error));
2894
3229
  process.exit(1);
2895
3230
  }
2896
3231
  });
@@ -2912,7 +3247,7 @@ mcpCommand.command("remove").description("Remove an MCP server").argument("<name
2912
3247
  console.log();
2913
3248
  } catch (error) {
2914
3249
  spinner.fail("Failed to remove MCP server");
2915
- logger9.error(error instanceof Error ? error.message : String(error));
3250
+ logger10.error(error instanceof Error ? error.message : String(error));
2916
3251
  process.exit(1);
2917
3252
  }
2918
3253
  });
@@ -2934,7 +3269,7 @@ mcpCommand.command("enable").description("Enable a disabled MCP server").argumen
2934
3269
  console.log();
2935
3270
  } catch (error) {
2936
3271
  spinner.fail("Failed to enable MCP server");
2937
- logger9.error(error instanceof Error ? error.message : String(error));
3272
+ logger10.error(error instanceof Error ? error.message : String(error));
2938
3273
  process.exit(1);
2939
3274
  }
2940
3275
  });
@@ -2956,7 +3291,7 @@ mcpCommand.command("disable").description("Disable an MCP server (without removi
2956
3291
  console.log();
2957
3292
  } catch (error) {
2958
3293
  spinner.fail("Failed to disable MCP server");
2959
- logger9.error(error instanceof Error ? error.message : String(error));
3294
+ logger10.error(error instanceof Error ? error.message : String(error));
2960
3295
  process.exit(1);
2961
3296
  }
2962
3297
  });
@@ -2964,7 +3299,7 @@ mcpCommand.command("status").description("Show MCP server status").option("--jso
2964
3299
  try {
2965
3300
  const loaded = await loadConfig7();
2966
3301
  if (!loaded) {
2967
- logger9.error("No rapid.json found. Run `rapid init` first.");
3302
+ logger10.error("No rapid.json found. Run `rapid init` first.");
2968
3303
  process.exit(1);
2969
3304
  }
2970
3305
  const { config } = loaded;
@@ -2974,11 +3309,11 @@ mcpCommand.command("status").description("Show MCP server status").option("--jso
2974
3309
  return;
2975
3310
  }
2976
3311
  console.log();
2977
- console.log(` ${logger9.brand("MCP Server Status")}`);
2978
- console.log(` ${logger9.dim("\u2500".repeat(40))}`);
3312
+ console.log(` ${logger10.brand("MCP Server Status")}`);
3313
+ console.log(` ${logger10.dim("\u2500".repeat(40))}`);
2979
3314
  console.log();
2980
3315
  if (servers.length === 0) {
2981
- console.log(` ${logger9.dim("No MCP servers configured")}`);
3316
+ console.log(` ${logger10.dim("No MCP servers configured")}`);
2982
3317
  console.log();
2983
3318
  return;
2984
3319
  }
@@ -2990,24 +3325,24 @@ mcpCommand.command("status").description("Show MCP server status").option("--jso
2990
3325
  } else {
2991
3326
  disabledCount++;
2992
3327
  }
2993
- const icon = server.status === "enabled" ? logger9.brand("\u2713") : server.status === "disabled" ? logger9.dim("\u25CB") : "\u2717";
2994
- const statusLabel = server.status === "enabled" ? "enabled" : server.status === "disabled" ? logger9.dim("disabled") : logger9.dim(`error: ${server.error}`);
3328
+ const icon = server.status === "enabled" ? logger10.brand("\u2713") : server.status === "disabled" ? logger10.dim("\u25CB") : "\u2717";
3329
+ const statusLabel = server.status === "enabled" ? "enabled" : server.status === "disabled" ? logger10.dim("disabled") : logger10.dim(`error: ${server.error}`);
2995
3330
  const typeLabel = server.type === "remote" ? "remote" : "stdio";
2996
3331
  console.log(` ${icon} ${server.name}`);
2997
- console.log(` ${logger9.dim("Type:")} ${typeLabel}`);
2998
- console.log(` ${logger9.dim("Status:")} ${statusLabel}`);
3332
+ console.log(` ${logger10.dim("Type:")} ${typeLabel}`);
3333
+ console.log(` ${logger10.dim("Status:")} ${statusLabel}`);
2999
3334
  if (server.url) {
3000
- console.log(` ${logger9.dim("URL:")} ${server.url}`);
3335
+ console.log(` ${logger10.dim("URL:")} ${server.url}`);
3001
3336
  }
3002
3337
  if (server.command) {
3003
- console.log(` ${logger9.dim("Cmd:")} ${server.command}`);
3338
+ console.log(` ${logger10.dim("Cmd:")} ${server.command}`);
3004
3339
  }
3005
3340
  console.log();
3006
3341
  }
3007
- console.log(` ${logger9.dim("Summary:")} ${enabledCount} enabled, ${disabledCount} disabled`);
3342
+ console.log(` ${logger10.dim("Summary:")} ${enabledCount} enabled, ${disabledCount} disabled`);
3008
3343
  console.log();
3009
3344
  } catch (error) {
3010
- logger9.error(error instanceof Error ? error.message : String(error));
3345
+ logger10.error(error instanceof Error ? error.message : String(error));
3011
3346
  process.exit(1);
3012
3347
  }
3013
3348
  });
@@ -3026,15 +3361,15 @@ mcpCommand.command("sync").description("Regenerate .mcp.json and opencode.json f
3026
3361
  const enabledCount = servers.filter((s) => s.enabled).length;
3027
3362
  spinner.succeed("MCP configuration synced");
3028
3363
  console.log();
3029
- console.log(` ${logger9.dim("Files updated:")}`);
3030
- console.log(` ${logger9.brand("\u2022")} .mcp.json`);
3031
- console.log(` ${logger9.brand("\u2022")} opencode.json`);
3364
+ console.log(` ${logger10.dim("Files updated:")}`);
3365
+ console.log(` ${logger10.brand("\u2022")} .mcp.json`);
3366
+ console.log(` ${logger10.brand("\u2022")} opencode.json`);
3032
3367
  console.log();
3033
- console.log(` ${logger9.dim("Servers:")} ${enabledCount} enabled`);
3368
+ console.log(` ${logger10.dim("Servers:")} ${enabledCount} enabled`);
3034
3369
  console.log();
3035
3370
  } catch (error) {
3036
3371
  spinner.fail("Failed to sync MCP configuration");
3037
- logger9.error(error instanceof Error ? error.message : String(error));
3372
+ logger10.error(error instanceof Error ? error.message : String(error));
3038
3373
  process.exit(1);
3039
3374
  }
3040
3375
  });
@@ -3046,25 +3381,143 @@ function collectHeaders(value, previous) {
3046
3381
  return previous;
3047
3382
  }
3048
3383
 
3049
- // src/commands/update.ts
3384
+ // src/commands/context.ts
3050
3385
  import { Command as Command10 } from "commander";
3386
+ import { loadConfig as loadConfig8, assembleContext as assembleContext2, logger as logger11 } from "@a3t/rapid-core";
3387
+ import ora9 from "ora";
3388
+ var contextCommand = new Command10("context").description("Show or inject project context from rapid.json").argument("[action]", "Action: show (default) or inject", "show").option("--json", "Output as JSON").action(async (action, options) => {
3389
+ try {
3390
+ const spinner = ora9("Loading configuration...").start();
3391
+ const loaded = await loadConfig8();
3392
+ if (!loaded) {
3393
+ spinner.fail("No rapid.json found. Run `rapid init` first.");
3394
+ process.exit(1);
3395
+ }
3396
+ const { config, rootDir } = loaded;
3397
+ spinner.stop();
3398
+ if (!config.context?.files?.length && !config.context?.dirs?.length) {
3399
+ if (action === "inject") {
3400
+ return;
3401
+ }
3402
+ logger11.info("No context files or directories configured.");
3403
+ logger11.blank();
3404
+ logger11.dim("Add files or directories to rapid.json:");
3405
+ logger11.dim(' "context": {');
3406
+ logger11.dim(' "files": ["README.md", "docs/architecture.md"],');
3407
+ logger11.dim(' "dirs": ["docs/"]');
3408
+ logger11.dim(" }");
3409
+ return;
3410
+ }
3411
+ const assembled = await assembleContext2(rootDir, config.context);
3412
+ if (action === "inject") {
3413
+ if (assembled.content) {
3414
+ console.log(assembled.content);
3415
+ }
3416
+ return;
3417
+ }
3418
+ if (options.json) {
3419
+ console.log(
3420
+ JSON.stringify(
3421
+ {
3422
+ files: assembled.files.map((f) => ({
3423
+ path: f.relativePath,
3424
+ size: f.size,
3425
+ truncated: f.truncated
3426
+ })),
3427
+ totalSize: assembled.totalSize,
3428
+ skippedFiles: assembled.skippedFiles.map((f) => ({
3429
+ path: f.path,
3430
+ reason: f.reason
3431
+ }))
3432
+ },
3433
+ null,
3434
+ 2
3435
+ )
3436
+ );
3437
+ return;
3438
+ }
3439
+ logger11.header("Context Configuration");
3440
+ logger11.blank();
3441
+ if (config.context.files?.length) {
3442
+ logger11.info("Configured files:");
3443
+ for (const file of config.context.files) {
3444
+ console.log(` ${logger11.dim("\u2022")} ${file}`);
3445
+ }
3446
+ logger11.blank();
3447
+ }
3448
+ if (config.context.dirs?.length) {
3449
+ logger11.info("Configured directories:");
3450
+ for (const dir of config.context.dirs) {
3451
+ console.log(` ${logger11.dim("\u2022")} ${dir}`);
3452
+ }
3453
+ logger11.blank();
3454
+ }
3455
+ if (config.context.exclude?.length) {
3456
+ logger11.info("Exclude patterns:");
3457
+ for (const pattern of config.context.exclude) {
3458
+ console.log(` ${logger11.dim("\u2022")} ${pattern}`);
3459
+ }
3460
+ logger11.blank();
3461
+ }
3462
+ logger11.info(`Assembled ${assembled.files.length} file(s):`);
3463
+ for (const file of assembled.files) {
3464
+ const sizeKb = (file.size / 1024).toFixed(1);
3465
+ console.log(` ${logger11.brand("\u2022")} ${file.relativePath} ${logger11.dim(`(${sizeKb}KB)`)}`);
3466
+ }
3467
+ const totalKb = (assembled.totalSize / 1024).toFixed(1);
3468
+ logger11.blank();
3469
+ logger11.dim(`Total size: ${totalKb}KB`);
3470
+ if (assembled.skippedFiles.length > 0) {
3471
+ logger11.blank();
3472
+ logger11.info(`Skipped ${assembled.skippedFiles.length} file(s):`);
3473
+ for (const skipped of assembled.skippedFiles) {
3474
+ const reasonText = getSkipReasonText(skipped.reason);
3475
+ console.log(` ${logger11.dim("\u2022")} ${skipped.path} ${logger11.dim(`(${reasonText})`)}`);
3476
+ }
3477
+ }
3478
+ } catch (error) {
3479
+ logger11.error(error instanceof Error ? error.message : String(error));
3480
+ process.exit(1);
3481
+ }
3482
+ });
3483
+ function getSkipReasonText(reason) {
3484
+ switch (reason) {
3485
+ case "missing":
3486
+ return "file not found";
3487
+ case "binary":
3488
+ return "binary file";
3489
+ case "too-large":
3490
+ return "exceeds size limit";
3491
+ case "excluded":
3492
+ return "excluded by pattern";
3493
+ case "directory":
3494
+ return "is a directory";
3495
+ case "error":
3496
+ return "read error";
3497
+ default:
3498
+ return reason;
3499
+ }
3500
+ }
3501
+
3502
+ // src/commands/update.ts
3503
+ import { Command as Command11 } from "commander";
3051
3504
 
3052
3505
  // src/utils/update-checker.ts
3053
3506
  import updateNotifier from "update-notifier";
3054
3507
  import semver from "semver";
3055
3508
  import { execa as execa3 } from "execa";
3056
- import { logger as logger10 } from "@a3t/rapid-core";
3509
+ import { logger as logger12 } from "@a3t/rapid-core";
3057
3510
  import chalk from "chalk";
3058
3511
  import { readFileSync, existsSync as existsSync2 } from "fs";
3059
3512
  import { fileURLToPath as fileURLToPath2 } from "url";
3060
- import { dirname as dirname3, join as join6 } from "path";
3513
+ import { dirname as dirname3, join as join7 } from "path";
3061
3514
  import prompts from "prompts";
3062
3515
  var __dirname = dirname3(fileURLToPath2(import.meta.url));
3063
3516
  function loadPackageJson() {
3064
3517
  const paths = [
3065
- join6(__dirname, "../package.json"),
3518
+ join7(__dirname, "../package.json"),
3066
3519
  // bundled: dist/ -> package root
3067
- join6(__dirname, "../../package.json")
3520
+ join7(__dirname, "../../package.json")
3068
3521
  // source: src/utils/ -> package root
3069
3522
  ];
3070
3523
  for (const p of paths) {
@@ -3120,9 +3573,9 @@ var UpdateChecker = class {
3120
3573
  if (!this.notifier.update) return;
3121
3574
  const { current, latest } = this.notifier.update;
3122
3575
  const updateType = this.getUpdateType(current, latest);
3123
- logger10.info(`Update available: ${logger10.dim(current)} \u2192 ${chalk.green(latest)}`);
3576
+ logger12.info(`Update available: ${logger12.dim(current)} \u2192 ${chalk.green(latest)}`);
3124
3577
  if (updateType === "major") {
3125
- logger10.warn("This is a major version update with breaking changes.");
3578
+ logger12.warn("This is a major version update with breaking changes.");
3126
3579
  }
3127
3580
  }
3128
3581
  /**
@@ -3130,20 +3583,20 @@ var UpdateChecker = class {
3130
3583
  */
3131
3584
  async verifySignatures() {
3132
3585
  try {
3133
- logger10.info("Verifying package signatures...");
3586
+ logger12.info("Verifying package signatures...");
3134
3587
  const result = await execa3("npm", ["audit", "signatures"], {
3135
3588
  reject: false
3136
3589
  });
3137
3590
  if (result.exitCode === 0) {
3138
- logger10.success("Package signatures verified successfully");
3591
+ logger12.success("Package signatures verified successfully");
3139
3592
  return true;
3140
3593
  } else {
3141
- logger10.warn("Package signature verification returned warnings");
3142
- logger10.debug(result.stdout || result.stderr);
3594
+ logger12.warn("Package signature verification returned warnings");
3595
+ logger12.debug(result.stdout || result.stderr);
3143
3596
  return true;
3144
3597
  }
3145
3598
  } catch {
3146
- logger10.debug("Signature verification not available (requires npm >= 9)");
3599
+ logger12.debug("Signature verification not available (requires npm >= 9)");
3147
3600
  return true;
3148
3601
  }
3149
3602
  }
@@ -3152,16 +3605,16 @@ var UpdateChecker = class {
3152
3605
  */
3153
3606
  async performUpdate() {
3154
3607
  try {
3155
- logger10.info("Updating RAPID CLI...");
3608
+ logger12.info("Updating RAPID CLI...");
3156
3609
  await execa3("npm", ["install", "-g", `${this.packageName}@latest`], {
3157
3610
  stdio: "inherit"
3158
3611
  });
3159
3612
  await this.verifySignatures();
3160
- logger10.success("RAPID CLI updated successfully!");
3161
- logger10.info("Package published with npm provenance - cryptographically verified");
3613
+ logger12.success("RAPID CLI updated successfully!");
3614
+ logger12.info("Package published with npm provenance - cryptographically verified");
3162
3615
  return true;
3163
3616
  } catch (error) {
3164
- logger10.error("Failed to update RAPID CLI:", error);
3617
+ logger12.error("Failed to update RAPID CLI:", error);
3165
3618
  return false;
3166
3619
  }
3167
3620
  }
@@ -3174,7 +3627,7 @@ var UpdateChecker = class {
3174
3627
  if (!updateInfo) return;
3175
3628
  this.showNotification();
3176
3629
  if (updateInfo.type === "major") {
3177
- logger10.warn(
3630
+ logger12.warn(
3178
3631
  `This is a major version update (${updateInfo.current} \u2192 ${updateInfo.latest}) that may contain breaking changes.`
3179
3632
  );
3180
3633
  try {
@@ -3185,20 +3638,20 @@ var UpdateChecker = class {
3185
3638
  initial: false
3186
3639
  });
3187
3640
  if (response.shouldUpdate) {
3188
- logger10.info(`Updating to ${updateInfo.latest} (major version)...`);
3641
+ logger12.info(`Updating to ${updateInfo.latest} (major version)...`);
3189
3642
  await this.performUpdate();
3190
3643
  } else {
3191
- logger10.info("Skipping major version update.");
3192
- logger10.info('You can update later with "rapid update --force"');
3644
+ logger12.info("Skipping major version update.");
3645
+ logger12.info('You can update later with "rapid update --force"');
3193
3646
  }
3194
3647
  } catch {
3195
- logger10.info(
3648
+ logger12.info(
3196
3649
  'Run "rapid update" to update manually, or use "rapid update --force" to update automatically.'
3197
3650
  );
3198
3651
  }
3199
3652
  return;
3200
3653
  }
3201
- logger10.info(`Auto-updating to ${updateInfo.latest} (${updateInfo.type} version)...`);
3654
+ logger12.info(`Auto-updating to ${updateInfo.latest} (${updateInfo.type} version)...`);
3202
3655
  await this.performUpdate();
3203
3656
  }
3204
3657
  /**
@@ -3206,7 +3659,7 @@ var UpdateChecker = class {
3206
3659
  */
3207
3660
  async forceUpdate() {
3208
3661
  if (!this.hasUpdate()) {
3209
- logger10.info("No updates available.");
3662
+ logger12.info("No updates available.");
3210
3663
  return;
3211
3664
  }
3212
3665
  const updateInfo = this.getUpdateInfo();
@@ -3219,68 +3672,68 @@ var UpdateChecker = class {
3219
3672
  var updateChecker = new UpdateChecker();
3220
3673
 
3221
3674
  // src/commands/update.ts
3222
- import { logger as logger11 } from "@a3t/rapid-core";
3223
- var updateCommand = new Command10("update").description("Check for and apply updates").option("--check", "Check for updates only").option("--force", "Force update even for major versions").action(async (options) => {
3675
+ import { logger as logger13 } from "@a3t/rapid-core";
3676
+ var updateCommand = new Command11("update").description("Check for and apply updates").option("--check", "Check for updates only").option("--force", "Force update even for major versions").action(async (options) => {
3224
3677
  try {
3225
3678
  if (options.check) {
3226
- logger11.header("Checking for updates...");
3679
+ logger13.header("Checking for updates...");
3227
3680
  if (!updateChecker.hasUpdate()) {
3228
- logger11.success("You are using the latest version!");
3681
+ logger13.success("You are using the latest version!");
3229
3682
  return;
3230
3683
  }
3231
3684
  const updateInfo2 = updateChecker.getUpdateInfo();
3232
3685
  if (updateInfo2) {
3233
3686
  updateChecker.showNotification();
3234
3687
  if (updateInfo2.type === "major") {
3235
- logger11.warn("This is a major version update with breaking changes.");
3236
- logger11.info('Use "rapid update --force" to update.');
3688
+ logger13.warn("This is a major version update with breaking changes.");
3689
+ logger13.info('Use "rapid update --force" to update.');
3237
3690
  } else {
3238
- logger11.info('Use "rapid update" to apply the update.');
3691
+ logger13.info('Use "rapid update" to apply the update.');
3239
3692
  }
3240
3693
  }
3241
3694
  return;
3242
3695
  }
3243
3696
  if (!updateChecker.hasUpdate()) {
3244
- logger11.success("You are already using the latest version!");
3697
+ logger13.success("You are already using the latest version!");
3245
3698
  return;
3246
3699
  }
3247
3700
  const updateInfo = updateChecker.getUpdateInfo();
3248
3701
  if (updateInfo && updateInfo.type === "major" && !options.force) {
3249
- logger11.warn("This is a major version update with breaking changes.");
3250
- logger11.info("Use --force to update anyway.");
3702
+ logger13.warn("This is a major version update with breaking changes.");
3703
+ logger13.info("Use --force to update anyway.");
3251
3704
  return;
3252
3705
  }
3253
3706
  await updateChecker.forceUpdate();
3254
3707
  } catch (error) {
3255
- logger11.error("Update failed:", error);
3708
+ logger13.error("Update failed:", error);
3256
3709
  process.exit(1);
3257
3710
  }
3258
3711
  });
3259
3712
 
3260
3713
  // src/commands/worktree.ts
3261
- import { Command as Command11 } from "commander";
3262
- import { logger as logger12 } from "@a3t/rapid-core";
3263
- import ora9 from "ora";
3714
+ import { Command as Command12 } from "commander";
3715
+ import { logger as logger14 } from "@a3t/rapid-core";
3716
+ import ora10 from "ora";
3264
3717
  function formatWorktree(wt, currentPath) {
3265
3718
  const isCurrent = wt.path === currentPath;
3266
- const marker = isCurrent ? logger12.brand("*") : " ";
3719
+ const marker = isCurrent ? logger14.brand("*") : " ";
3267
3720
  const status = [];
3268
3721
  if (wt.isMain) status.push("main");
3269
3722
  if (wt.locked) status.push("locked");
3270
3723
  if (wt.prunable) status.push("prunable");
3271
3724
  if (!wt.exists) status.push("missing");
3272
- const statusStr = status.length > 0 ? logger12.dim(` (${status.join(", ")})`) : "";
3273
- const branchStr = wt.branch ? logger12.brand(wt.branch) : logger12.dim("detached");
3725
+ const statusStr = status.length > 0 ? logger14.dim(` (${status.join(", ")})`) : "";
3726
+ const branchStr = wt.branch ? logger14.brand(wt.branch) : logger14.dim("detached");
3274
3727
  const headShort = wt.head?.substring(0, 7) ?? "";
3275
3728
  return `${marker} ${branchStr}${statusStr}
3276
- ${logger12.dim(wt.path)}
3277
- ${logger12.dim(`HEAD: ${headShort}`)}`;
3729
+ ${logger14.dim(wt.path)}
3730
+ ${logger14.dim(`HEAD: ${headShort}`)}`;
3278
3731
  }
3279
- var listCommand = new Command11("list").alias("ls").description("List all git worktrees").option("--json", "Output as JSON").action(async (options) => {
3732
+ var listCommand = new Command12("list").alias("ls").description("List all git worktrees").option("--json", "Output as JSON").action(async (options) => {
3280
3733
  try {
3281
3734
  const cwd = process.cwd();
3282
3735
  if (!await isGitRepo(cwd)) {
3283
- logger12.error("Not a git repository");
3736
+ logger14.error("Not a git repository");
3284
3737
  process.exit(1);
3285
3738
  }
3286
3739
  const gitRoot = await getGitRoot(cwd);
@@ -3290,10 +3743,10 @@ var listCommand = new Command11("list").alias("ls").description("List all git wo
3290
3743
  return;
3291
3744
  }
3292
3745
  if (worktrees.length === 0) {
3293
- logger12.info("No worktrees found");
3746
+ logger14.info("No worktrees found");
3294
3747
  return;
3295
3748
  }
3296
- logger12.header("Git Worktrees");
3749
+ logger14.header("Git Worktrees");
3297
3750
  console.log();
3298
3751
  for (const wt of worktrees) {
3299
3752
  console.log(formatWorktree(wt, gitRoot));
@@ -3301,15 +3754,15 @@ var listCommand = new Command11("list").alias("ls").description("List all git wo
3301
3754
  }
3302
3755
  const prunable = worktrees.filter((wt) => wt.prunable);
3303
3756
  if (prunable.length > 0) {
3304
- logger12.warn(`${prunable.length} worktree(s) can be pruned. Run: rapid worktree prune`);
3757
+ logger14.warn(`${prunable.length} worktree(s) can be pruned. Run: rapid worktree prune`);
3305
3758
  }
3306
3759
  } catch (error) {
3307
- logger12.error(error instanceof Error ? error.message : String(error));
3760
+ logger14.error(error instanceof Error ? error.message : String(error));
3308
3761
  process.exit(1);
3309
3762
  }
3310
3763
  });
3311
- var pruneCommand = new Command11("prune").description("Remove stale worktree references").option("--dry-run", "Show what would be pruned without removing").action(async (options) => {
3312
- const spinner = ora9("Checking worktrees...").start();
3764
+ var pruneCommand = new Command12("prune").description("Remove stale worktree references").option("--dry-run", "Show what would be pruned without removing").action(async (options) => {
3765
+ const spinner = ora10("Checking worktrees...").start();
3313
3766
  try {
3314
3767
  const cwd = process.cwd();
3315
3768
  if (!await isGitRepo(cwd)) {
@@ -3326,7 +3779,7 @@ var pruneCommand = new Command11("prune").description("Remove stale worktree ref
3326
3779
  if (options.dryRun) {
3327
3780
  spinner.info(`Would prune ${prunable.length} worktree(s):`);
3328
3781
  for (const wt of prunable) {
3329
- console.log(` ${logger12.dim("\u2022")} ${wt.path}`);
3782
+ console.log(` ${logger14.dim("\u2022")} ${wt.path}`);
3330
3783
  }
3331
3784
  return;
3332
3785
  }
@@ -3335,7 +3788,7 @@ var pruneCommand = new Command11("prune").description("Remove stale worktree ref
3335
3788
  if (result.success) {
3336
3789
  spinner.succeed(`Pruned ${result.pruned.length} worktree(s)`);
3337
3790
  for (const path of result.pruned) {
3338
- console.log(` ${logger12.dim("\u2022")} ${path}`);
3791
+ console.log(` ${logger14.dim("\u2022")} ${path}`);
3339
3792
  }
3340
3793
  } else {
3341
3794
  spinner.fail(`Failed to prune: ${result.error}`);
@@ -3346,8 +3799,8 @@ var pruneCommand = new Command11("prune").description("Remove stale worktree ref
3346
3799
  process.exit(1);
3347
3800
  }
3348
3801
  });
3349
- var removeCommand = new Command11("remove").alias("rm").description("Remove a worktree").argument("<path-or-branch>", "Worktree path or branch name").option("-f, --force", "Force removal even if worktree is dirty").action(async (pathOrBranch, options) => {
3350
- const spinner = ora9("Finding worktree...").start();
3802
+ var removeCommand = new Command12("remove").alias("rm").description("Remove a worktree").argument("<path-or-branch>", "Worktree path or branch name").option("-f, --force", "Force removal even if worktree is dirty").action(async (pathOrBranch, options) => {
3803
+ const spinner = ora10("Finding worktree...").start();
3351
3804
  try {
3352
3805
  const cwd = process.cwd();
3353
3806
  if (!await isGitRepo(cwd)) {
@@ -3361,7 +3814,7 @@ var removeCommand = new Command11("remove").alias("rm").description("Remove a wo
3361
3814
  );
3362
3815
  if (!worktree) {
3363
3816
  spinner.fail(`Worktree not found: ${pathOrBranch}`);
3364
- logger12.info("Available worktrees:");
3817
+ logger14.info("Available worktrees:");
3365
3818
  for (const wt of worktrees) {
3366
3819
  console.log(` ${wt.branch || wt.path}`);
3367
3820
  }
@@ -3388,8 +3841,8 @@ var removeCommand = new Command11("remove").alias("rm").description("Remove a wo
3388
3841
  process.exit(1);
3389
3842
  }
3390
3843
  });
3391
- var cleanupCommand = new Command11("cleanup").description("Remove worktrees for branches that have been merged").option("--dry-run", "Show what would be removed without removing").action(async (options) => {
3392
- const spinner = ora9("Analyzing worktrees...").start();
3844
+ var cleanupCommand = new Command12("cleanup").description("Remove worktrees for branches that have been merged").option("--dry-run", "Show what would be removed without removing").action(async (options) => {
3845
+ const spinner = ora10("Analyzing worktrees...").start();
3393
3846
  try {
3394
3847
  const cwd = process.cwd();
3395
3848
  if (!await isGitRepo(cwd)) {
@@ -3406,10 +3859,10 @@ var cleanupCommand = new Command11("cleanup").description("Remove worktrees for
3406
3859
  } else {
3407
3860
  console.log(" Feature branch worktrees:");
3408
3861
  for (const wt of nonMain) {
3409
- console.log(` ${logger12.dim("\u2022")} ${wt.branch} - ${wt.path}`);
3862
+ console.log(` ${logger14.dim("\u2022")} ${wt.branch} - ${wt.path}`);
3410
3863
  }
3411
3864
  console.log();
3412
- logger12.info("Run without --dry-run to remove worktrees for merged branches");
3865
+ logger14.info("Run without --dry-run to remove worktrees for merged branches");
3413
3866
  }
3414
3867
  return;
3415
3868
  }
@@ -3421,13 +3874,13 @@ var cleanupCommand = new Command11("cleanup").description("Remove worktrees for
3421
3874
  }
3422
3875
  spinner.succeed(`Cleaned up ${result.removed.length} worktree(s)`);
3423
3876
  for (const path of result.removed) {
3424
- console.log(` ${logger12.dim("\u2022")} ${path}`);
3877
+ console.log(` ${logger14.dim("\u2022")} ${path}`);
3425
3878
  }
3426
3879
  if (result.errors.length > 0) {
3427
3880
  console.log();
3428
- logger12.warn("Some worktrees could not be removed:");
3881
+ logger14.warn("Some worktrees could not be removed:");
3429
3882
  for (const err of result.errors) {
3430
- console.log(` ${logger12.dim("\u2022")} ${err}`);
3883
+ console.log(` ${logger14.dim("\u2022")} ${err}`);
3431
3884
  }
3432
3885
  }
3433
3886
  } catch (error) {
@@ -3435,32 +3888,32 @@ var cleanupCommand = new Command11("cleanup").description("Remove worktrees for
3435
3888
  process.exit(1);
3436
3889
  }
3437
3890
  });
3438
- var worktreeCommand = new Command11("worktree").alias("wt").description("Manage git worktrees for isolated development").addCommand(listCommand).addCommand(pruneCommand).addCommand(removeCommand).addCommand(cleanupCommand);
3891
+ var worktreeCommand = new Command12("worktree").alias("wt").description("Manage git worktrees for isolated development").addCommand(listCommand).addCommand(pruneCommand).addCommand(removeCommand).addCommand(cleanupCommand);
3439
3892
  worktreeCommand.action(async () => {
3440
3893
  await listCommand.parseAsync([], { from: "user" });
3441
3894
  });
3442
3895
 
3443
3896
  // src/commands/lima.ts
3444
- import { Command as Command12 } from "commander";
3445
- import { logger as logger13 } from "@a3t/rapid-core";
3446
- import ora10 from "ora";
3897
+ import { Command as Command13 } from "commander";
3898
+ import { logger as logger15 } from "@a3t/rapid-core";
3899
+ import ora11 from "ora";
3447
3900
  async function checkLimaAvailable() {
3448
3901
  if (!isMacOS()) {
3449
- logger13.error("Lima is only available on macOS");
3902
+ logger15.error("Lima is only available on macOS");
3450
3903
  return false;
3451
3904
  }
3452
3905
  if (!await hasLima()) {
3453
- logger13.error("Lima is not installed");
3454
- logger13.blank();
3455
- logger13.info("Install Lima with:");
3456
- console.log(` ${logger13.dim("$")} brew install lima`);
3457
- logger13.blank();
3458
- logger13.info("For more information: https://lima-vm.io");
3906
+ logger15.error("Lima is not installed");
3907
+ logger15.blank();
3908
+ logger15.info("Install Lima with:");
3909
+ console.log(` ${logger15.dim("$")} brew install lima`);
3910
+ logger15.blank();
3911
+ logger15.info("For more information: https://lima-vm.io");
3459
3912
  return false;
3460
3913
  }
3461
3914
  return true;
3462
3915
  }
3463
- var statusCommand2 = new Command12("status").description("Show Lima VM status").option("--json", "Output as JSON").action(async (options) => {
3916
+ var statusCommand2 = new Command13("status").description("Show Lima VM status").option("--json", "Output as JSON").action(async (options) => {
3464
3917
  if (!await checkLimaAvailable()) {
3465
3918
  process.exit(1);
3466
3919
  }
@@ -3470,43 +3923,43 @@ var statusCommand2 = new Command12("status").description("Show Lima VM status").
3470
3923
  return;
3471
3924
  }
3472
3925
  if (!instance) {
3473
- logger13.info(`Lima VM (${RAPID_LIMA_INSTANCE}) is not created`);
3474
- logger13.blank();
3475
- logger13.info("Start the VM with:");
3476
- console.log(` ${logger13.dim("$")} rapid lima start`);
3477
- logger13.blank();
3478
- logger13.info("Or use:");
3479
- console.log(` ${logger13.dim("$")} rapid dev --local`);
3926
+ logger15.info(`Lima VM (${RAPID_LIMA_INSTANCE}) is not created`);
3927
+ logger15.blank();
3928
+ logger15.info("Start the VM with:");
3929
+ console.log(` ${logger15.dim("$")} rapid lima start`);
3930
+ logger15.blank();
3931
+ logger15.info("Or use:");
3932
+ console.log(` ${logger15.dim("$")} rapid dev --local`);
3480
3933
  return;
3481
3934
  }
3482
- logger13.header("Lima VM Status");
3935
+ logger15.header("Lima VM Status");
3483
3936
  console.log();
3484
- console.log(` ${logger13.dim("Name:")} ${instance.name}`);
3937
+ console.log(` ${logger15.dim("Name:")} ${instance.name}`);
3485
3938
  console.log(
3486
- ` ${logger13.dim("Status:")} ${instance.status === "Running" ? logger13.brand(instance.status) : instance.status}`
3939
+ ` ${logger15.dim("Status:")} ${instance.status === "Running" ? logger15.brand(instance.status) : instance.status}`
3487
3940
  );
3488
- console.log(` ${logger13.dim("Arch:")} ${instance.arch}`);
3489
- console.log(` ${logger13.dim("CPUs:")} ${instance.cpus}`);
3490
- console.log(` ${logger13.dim("Memory:")} ${instance.memory}`);
3491
- console.log(` ${logger13.dim("Disk:")} ${instance.disk}`);
3941
+ console.log(` ${logger15.dim("Arch:")} ${instance.arch}`);
3942
+ console.log(` ${logger15.dim("CPUs:")} ${instance.cpus}`);
3943
+ console.log(` ${logger15.dim("Memory:")} ${instance.memory}`);
3944
+ console.log(` ${logger15.dim("Disk:")} ${instance.disk}`);
3492
3945
  if (instance.sshLocalPort) {
3493
- console.log(` ${logger13.dim("SSH Port:")} ${instance.sshLocalPort}`);
3946
+ console.log(` ${logger15.dim("SSH Port:")} ${instance.sshLocalPort}`);
3494
3947
  }
3495
3948
  console.log();
3496
3949
  if (instance.status === "Running") {
3497
- logger13.info("To open a shell:");
3498
- console.log(` ${logger13.dim("$")} rapid lima shell`);
3950
+ logger15.info("To open a shell:");
3951
+ console.log(` ${logger15.dim("$")} rapid lima shell`);
3499
3952
  } else {
3500
- logger13.info("To start the VM:");
3501
- console.log(` ${logger13.dim("$")} rapid lima start`);
3953
+ logger15.info("To start the VM:");
3954
+ console.log(` ${logger15.dim("$")} rapid lima start`);
3502
3955
  }
3503
3956
  console.log();
3504
3957
  });
3505
- var startCommand2 = new Command12("start").description("Start the Lima VM").option("--cpus <n>", "Number of CPUs", "4").option("--memory <size>", "Memory size", "8GiB").option("--disk <size>", "Disk size", "50GiB").action(async (options) => {
3958
+ var startCommand2 = new Command13("start").description("Start the Lima VM").option("--cpus <n>", "Number of CPUs", "4").option("--memory <size>", "Memory size", "8GiB").option("--disk <size>", "Disk size", "50GiB").action(async (options) => {
3506
3959
  if (!await checkLimaAvailable()) {
3507
3960
  process.exit(1);
3508
3961
  }
3509
- const spinner = ora10("Starting Lima VM...").start();
3962
+ const spinner = ora11("Starting Lima VM...").start();
3510
3963
  const projectDir = process.cwd();
3511
3964
  const result = await startInstance(projectDir, {
3512
3965
  cpus: parseInt(options.cpus, 10),
@@ -3516,56 +3969,56 @@ var startCommand2 = new Command12("start").description("Start the Lima VM").opti
3516
3969
  });
3517
3970
  if (!result.success) {
3518
3971
  spinner.fail("Failed to start Lima VM");
3519
- logger13.error(result.error ?? "Unknown error");
3972
+ logger15.error(result.error ?? "Unknown error");
3520
3973
  process.exit(1);
3521
3974
  }
3522
3975
  spinner.succeed("Lima VM started");
3523
- logger13.blank();
3524
- const sshSpinner = ora10("Checking SSH agent forwarding...").start();
3976
+ logger15.blank();
3977
+ const sshSpinner = ora11("Checking SSH agent forwarding...").start();
3525
3978
  const sshResult = await setupGitSsh();
3526
3979
  if (sshResult.success) {
3527
3980
  sshSpinner.succeed("SSH agent forwarding is working");
3528
3981
  } else {
3529
3982
  sshSpinner.warn("SSH agent forwarding may not be working");
3530
- logger13.dim(sshResult.error ?? "Make sure ssh-agent is running on the host");
3983
+ logger15.dim(sshResult.error ?? "Make sure ssh-agent is running on the host");
3531
3984
  }
3532
- logger13.blank();
3533
- logger13.info("To open a shell:");
3534
- console.log(` ${logger13.dim("$")} rapid lima shell`);
3985
+ logger15.blank();
3986
+ logger15.info("To open a shell:");
3987
+ console.log(` ${logger15.dim("$")} rapid lima shell`);
3535
3988
  console.log();
3536
3989
  });
3537
- var stopCommand2 = new Command12("stop").description("Stop the Lima VM").option("-f, --force", "Force stop").action(async (options) => {
3990
+ var stopCommand2 = new Command13("stop").description("Stop the Lima VM").option("-f, --force", "Force stop").action(async (options) => {
3538
3991
  if (!await checkLimaAvailable()) {
3539
3992
  process.exit(1);
3540
3993
  }
3541
3994
  const instance = await getInstance();
3542
3995
  if (!instance) {
3543
- logger13.info("Lima VM is not created");
3996
+ logger15.info("Lima VM is not created");
3544
3997
  return;
3545
3998
  }
3546
3999
  if (instance.status !== "Running") {
3547
- logger13.info("Lima VM is already stopped");
4000
+ logger15.info("Lima VM is already stopped");
3548
4001
  return;
3549
4002
  }
3550
- const spinner = ora10("Stopping Lima VM...").start();
4003
+ const spinner = ora11("Stopping Lima VM...").start();
3551
4004
  const result = await stopInstance(RAPID_LIMA_INSTANCE, {
3552
4005
  force: options.force
3553
4006
  });
3554
4007
  if (!result.success) {
3555
4008
  spinner.fail("Failed to stop Lima VM");
3556
- logger13.error(result.error ?? "Unknown error");
4009
+ logger15.error(result.error ?? "Unknown error");
3557
4010
  process.exit(1);
3558
4011
  }
3559
4012
  spinner.succeed("Lima VM stopped");
3560
4013
  });
3561
- var shellCommand = new Command12("shell").description("Open a shell in the Lima VM").option("-c, --command <cmd>", "Command to run instead of interactive shell").action(async (options) => {
4014
+ var shellCommand = new Command13("shell").description("Open a shell in the Lima VM").option("-c, --command <cmd>", "Command to run instead of interactive shell").action(async (options) => {
3562
4015
  if (!await checkLimaAvailable()) {
3563
4016
  process.exit(1);
3564
4017
  }
3565
4018
  const instance = await getInstance();
3566
4019
  if (!instance || instance.status !== "Running") {
3567
- logger13.error("Lima VM is not running");
3568
- logger13.info("Start with: rapid lima start");
4020
+ logger15.error("Lima VM is not running");
4021
+ logger15.info("Start with: rapid lima start");
3569
4022
  process.exit(1);
3570
4023
  }
3571
4024
  await shellInLima({
@@ -3573,30 +4026,30 @@ var shellCommand = new Command12("shell").description("Open a shell in the Lima
3573
4026
  command: options.command
3574
4027
  });
3575
4028
  });
3576
- var deleteCommand = new Command12("delete").description("Delete the Lima VM").option("-f, --force", "Force delete without confirmation").action(async (options) => {
4029
+ var deleteCommand = new Command13("delete").description("Delete the Lima VM").option("-f, --force", "Force delete without confirmation").action(async (options) => {
3577
4030
  if (!await checkLimaAvailable()) {
3578
4031
  process.exit(1);
3579
4032
  }
3580
4033
  const instance = await getInstance();
3581
4034
  if (!instance) {
3582
- logger13.info("Lima VM does not exist");
4035
+ logger15.info("Lima VM does not exist");
3583
4036
  return;
3584
4037
  }
3585
4038
  if (!options.force) {
3586
- logger13.warn("This will permanently delete the Lima VM and all its data.");
3587
- logger13.info(`Use ${logger13.brand("--force")} to confirm deletion.`);
4039
+ logger15.warn("This will permanently delete the Lima VM and all its data.");
4040
+ logger15.info(`Use ${logger15.brand("--force")} to confirm deletion.`);
3588
4041
  return;
3589
4042
  }
3590
- const spinner = ora10("Deleting Lima VM...").start();
4043
+ const spinner = ora11("Deleting Lima VM...").start();
3591
4044
  const result = await deleteInstance(RAPID_LIMA_INSTANCE, { force: true });
3592
4045
  if (!result.success) {
3593
4046
  spinner.fail("Failed to delete Lima VM");
3594
- logger13.error(result.error ?? "Unknown error");
4047
+ logger15.error(result.error ?? "Unknown error");
3595
4048
  process.exit(1);
3596
4049
  }
3597
4050
  spinner.succeed("Lima VM deleted");
3598
4051
  });
3599
- var listCommand2 = new Command12("list").alias("ls").description("List all Lima instances").option("--json", "Output as JSON").action(async (options) => {
4052
+ var listCommand2 = new Command13("list").alias("ls").description("List all Lima instances").option("--json", "Output as JSON").action(async (options) => {
3600
4053
  if (!await checkLimaAvailable()) {
3601
4054
  process.exit(1);
3602
4055
  }
@@ -3606,31 +4059,31 @@ var listCommand2 = new Command12("list").alias("ls").description("List all Lima
3606
4059
  return;
3607
4060
  }
3608
4061
  if (instances.length === 0) {
3609
- logger13.info("No Lima instances found");
4062
+ logger15.info("No Lima instances found");
3610
4063
  return;
3611
4064
  }
3612
- logger13.header("Lima Instances");
4065
+ logger15.header("Lima Instances");
3613
4066
  console.log();
3614
4067
  for (const inst of instances) {
3615
4068
  const isRapid = inst.name === RAPID_LIMA_INSTANCE;
3616
- const statusColor = inst.status === "Running" ? logger13.brand : logger13.dim;
4069
+ const statusColor = inst.status === "Running" ? logger15.brand : logger15.dim;
3617
4070
  console.log(
3618
- ` ${isRapid ? logger13.brand("*") : " "} ${inst.name} ${statusColor(`(${inst.status})`)}`
4071
+ ` ${isRapid ? logger15.brand("*") : " "} ${inst.name} ${statusColor(`(${inst.status})`)}`
3619
4072
  );
3620
- console.log(` ${logger13.dim(`${inst.cpus} CPUs, ${inst.memory}, ${inst.disk}`)}`);
4073
+ console.log(` ${logger15.dim(`${inst.cpus} CPUs, ${inst.memory}, ${inst.disk}`)}`);
3621
4074
  }
3622
4075
  console.log();
3623
4076
  });
3624
- var limaCommand = new Command12("lima").description("Manage Lima VM for local development (macOS)").addCommand(statusCommand2).addCommand(startCommand2).addCommand(stopCommand2).addCommand(shellCommand).addCommand(deleteCommand).addCommand(listCommand2);
4077
+ var limaCommand = new Command13("lima").description("Manage Lima VM for local development (macOS)").addCommand(statusCommand2).addCommand(startCommand2).addCommand(stopCommand2).addCommand(shellCommand).addCommand(deleteCommand).addCommand(listCommand2);
3625
4078
  limaCommand.action(async () => {
3626
4079
  await statusCommand2.parseAsync([], { from: "user" });
3627
4080
  });
3628
4081
 
3629
4082
  // src/index.ts
3630
4083
  var __dirname2 = dirname4(fileURLToPath3(import.meta.url));
3631
- var packageJson2 = JSON.parse(readFileSync2(join7(__dirname2, "../package.json"), "utf-8"));
4084
+ var packageJson2 = JSON.parse(readFileSync2(join8(__dirname2, "../package.json"), "utf-8"));
3632
4085
  var VERSION = packageJson2.version;
3633
- var program = new Command13();
4086
+ var program = new Command14();
3634
4087
  program.name("rapid").description("AI-assisted development with dev containers").version(VERSION, "-v, --version", "Show version").option("--verbose", "Verbose output").option("-q, --quiet", "Minimal output").option("--config <path>", "Path to rapid.json").hook("preAction", async (thisCommand) => {
3635
4088
  const opts = thisCommand.opts();
3636
4089
  if (opts.verbose) {
@@ -3644,7 +4097,7 @@ program.name("rapid").description("AI-assisted development with dev containers")
3644
4097
  try {
3645
4098
  await updateChecker.checkAndUpdate();
3646
4099
  } catch (error) {
3647
- logger14.debug("Update check failed:", error);
4100
+ logger16.debug("Update check failed:", error);
3648
4101
  }
3649
4102
  });
3650
4103
  program.addCommand(initCommand);
@@ -3656,13 +4109,14 @@ program.addCommand(agentCommand);
3656
4109
  program.addCommand(secretsCommand);
3657
4110
  program.addCommand(authCommand);
3658
4111
  program.addCommand(mcpCommand);
4112
+ program.addCommand(contextCommand);
3659
4113
  program.addCommand(updateCommand);
3660
4114
  program.addCommand(worktreeCommand);
3661
4115
  program.addCommand(limaCommand);
3662
4116
  program.action(() => {
3663
4117
  console.log();
3664
- console.log(` ${logger14.brand("RAPID")} ${logger14.dim(`v${VERSION}`)}`);
3665
- console.log(` ${logger14.dim("AI-assisted development with dev containers")}`);
4118
+ console.log(` ${logger16.brand("RAPID")} ${logger16.dim(`v${VERSION}`)}`);
4119
+ console.log(` ${logger16.dim("AI-assisted development with dev containers")}`);
3666
4120
  console.log();
3667
4121
  program.help();
3668
4122
  });
@@ -3670,4 +4124,4 @@ program.action(() => {
3670
4124
  export {
3671
4125
  program
3672
4126
  };
3673
- //# sourceMappingURL=chunk-52NWSTTE.js.map
4127
+ //# sourceMappingURL=chunk-COGUXZI3.js.map