@a3t/rapid-core 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,171 @@
1
+ # @a3t/rapid-core
2
+
3
+ Core library for RAPID - AI-assisted development with dev containers.
4
+
5
+ This package provides the foundational utilities for orchestrating AI coding assistants within containerized development environments.
6
+
7
+ ## Features
8
+
9
+ - 🐳 **Dev Container Management** - Control containerized environments via devcontainer CLI
10
+ - 🤖 **Agent Configuration** - Manage multiple AI coding assistants (Claude Code, OpenCode, Aider, etc.)
11
+ - 🔐 **Secret Management** - Integration with 1Password and Vault for credential handling
12
+ - 🔌 **MCP Server Support** - Model Context Protocol integration for external tools and APIs
13
+ - ⚙️ **Configuration Loading** - Smart configuration resolution with cosmiconfig
14
+ - 🔍 **External Auth Detection** - Detect credentials from external AI tools
15
+
16
+ ## Installation
17
+
18
+ ```bash
19
+ npm install @a3t/rapid-core
20
+ ```
21
+
22
+ ## Usage
23
+
24
+ ### Loading Configuration
25
+
26
+ ```typescript
27
+ import { loadConfig } from '@a3t/rapid-core';
28
+
29
+ const { config, rootDir } = await loadConfig();
30
+ console.log(config.agents.default); // 'claude'
31
+ ```
32
+
33
+ ### Managing Containers
34
+
35
+ ```typescript
36
+ import { getContainerStatus, startContainer, execInContainer } from '@a3t/rapid-core';
37
+
38
+ // Check if container is running
39
+ const status = await getContainerStatus(projectRoot, config);
40
+
41
+ // Start container
42
+ const result = await startContainer(projectRoot, config);
43
+
44
+ // Execute command in container
45
+ await execInContainer(projectRoot, ['claude'], config);
46
+ ```
47
+
48
+ ### Agent Detection
49
+
50
+ ```typescript
51
+ import { checkAllAgents, getAgent, launchAgent } from '@a3t/rapid-core';
52
+
53
+ // Check installed agents
54
+ const agents = await checkAllAgents(config);
55
+
56
+ // Get specific agent
57
+ const claude = getAgent(config, 'claude');
58
+
59
+ // Launch agent
60
+ await launchAgent(claude, { cwd: projectRoot });
61
+ ```
62
+
63
+ ### External Authentication
64
+
65
+ ```typescript
66
+ import { detectClaudeCodeAuth, detectAllCredentials, getAuthStatus } from '@a3t/rapid-core';
67
+
68
+ // Detect Claude Code credentials
69
+ const claudeAuth = await detectClaudeCodeAuth();
70
+
71
+ // Detect all credentials from external tools
72
+ const credentials = await detectAllCredentials();
73
+
74
+ // Get authentication status
75
+ const authStatus = await getAuthStatus();
76
+ ```
77
+
78
+ ## API Reference
79
+
80
+ ### Configuration
81
+
82
+ - `loadConfig(cwd?)` - Load RAPID configuration from cosmiconfig search
83
+ - `loadConfigFromFile(filepath)` - Load configuration from specific file
84
+ - `getDefaultConfig()` - Get default configuration
85
+ - `mergeWithDefaults(config)` - Merge user config with defaults
86
+
87
+ ### Container Management
88
+
89
+ - `hasDevcontainerCli()` - Check if devcontainer CLI is installed
90
+ - `hasDocker()` - Check if Docker is available
91
+ - `getContainerStatus(rootDir, config)` - Get current container status
92
+ - `startContainer(rootDir, config, options)` - Start dev container
93
+ - `stopContainer(rootDir, config, options)` - Stop dev container
94
+ - `execInContainer(rootDir, command, config, options)` - Execute command in container
95
+
96
+ ### Agent Management
97
+
98
+ - `checkAgentAvailable(agent)` - Check if agent CLI is installed
99
+ - `checkAllAgents(config)` - Check all configured agents
100
+ - `getDefaultAgent(config)` - Get default agent from config
101
+ - `getAgent(config, name)` - Get specific agent by name
102
+ - `launchAgent(agent, options)` - Launch agent CLI
103
+
104
+ ### Authentication
105
+
106
+ - `detectClaudeCodeAuth()` - Detect Claude Code credentials
107
+ - `detectCodexAuth()` - Detect OpenAI Codex credentials
108
+ - `detectGeminiAuth()` - Detect Google Gemini credentials
109
+ - `detectAiderAuth()` - Detect Aider API keys
110
+ - `detectEnvAuth()` - Detect API keys from environment
111
+ - `detectAllCredentials(config)` - Detect all available credentials
112
+ - `getAuthStatus(config)` - Get authentication status summary
113
+ - `getCredentialsForProvider(provider, config)` - Get credentials for specific provider
114
+ - `getAuthEnvironment(config)` - Get environment variables for detected credentials
115
+
116
+ ## Types
117
+
118
+ ```typescript
119
+ import type {
120
+ RapidConfig,
121
+ ContainerConfig,
122
+ AgentsConfig,
123
+ AgentDefinition,
124
+ SecretsConfig,
125
+ ContextConfig,
126
+ McpConfig,
127
+ DetectedCredential,
128
+ AuthStatus,
129
+ } from '@a3t/rapid-core';
130
+ ```
131
+
132
+ ## Configuration File Format
133
+
134
+ See [rapid.json Specification](https://github.com/a3tai/rapid/docs/reference/rapid.json-spec.md) for complete configuration reference.
135
+
136
+ ## Logger
137
+
138
+ ```typescript
139
+ import { logger, setLogLevel } from '@a3t/rapid-core';
140
+
141
+ // Set log level
142
+ setLogLevel('debug'); // 'debug' | 'info' | 'warn' | 'error'
143
+
144
+ // Log messages
145
+ logger.info('Information message');
146
+ logger.warn('Warning message');
147
+ logger.error('Error message');
148
+ logger.success('Success message');
149
+ logger.blank(); // Empty line
150
+ ```
151
+
152
+ ## Error Handling
153
+
154
+ Most async functions return success/error objects rather than throwing:
155
+
156
+ ```typescript
157
+ const result = await startContainer(rootDir, config);
158
+ if (!result.success) {
159
+ console.error(result.error);
160
+ }
161
+ ```
162
+
163
+ ## See Also
164
+
165
+ - [@a3t/rapid](https://www.npmjs.com/package/@a3t/rapid) - CLI tool
166
+ - [@a3t/rapid-schema](https://www.npmjs.com/package/@a3t/rapid-schema) - JSON schema
167
+ - [RAPID Documentation](https://getrapid.dev)
168
+
169
+ ## License
170
+
171
+ MIT © 2026 Rude Company LLC
package/dist/index.d.ts CHANGED
@@ -17,6 +17,18 @@ interface ContainerConfig {
17
17
  autoStart?: boolean;
18
18
  buildArgs?: Record<string, string>;
19
19
  }
20
+ /**
21
+ * External auth source types
22
+ */
23
+ type ExternalAuthSource = 'claude-code' | 'codex' | 'gemini-cli' | 'aider' | 'env';
24
+ /**
25
+ * External auth configuration
26
+ */
27
+ interface ExternalAuthConfig {
28
+ enabled?: boolean;
29
+ sources?: ExternalAuthSource[];
30
+ preferSource?: ExternalAuthSource;
31
+ }
20
32
  interface SecretsConfig {
21
33
  provider?: 'env' | '1password' | 'vault';
22
34
  vault?: string;
@@ -24,6 +36,7 @@ interface SecretsConfig {
24
36
  items?: Record<string, string>;
25
37
  envrc?: EnvrcConfig;
26
38
  dotenv?: DotenvConfig;
39
+ externalAuth?: ExternalAuthConfig;
27
40
  }
28
41
  interface EnvrcConfig {
29
42
  generate?: boolean;
@@ -81,6 +94,32 @@ interface EnvironmentStatus {
81
94
  secretsLoaded: boolean;
82
95
  containerRunning: boolean;
83
96
  }
97
+ /**
98
+ * Detected credential from an external tool
99
+ */
100
+ interface DetectedCredential {
101
+ source: ExternalAuthSource;
102
+ provider: 'anthropic' | 'openai' | 'google' | 'unknown';
103
+ authType: 'api-key' | 'oauth' | 'service-account';
104
+ envVar?: string;
105
+ value?: string;
106
+ expiresAt?: Date;
107
+ accountInfo?: {
108
+ email?: string;
109
+ organization?: string;
110
+ plan?: string;
111
+ };
112
+ configPath?: string;
113
+ }
114
+ /**
115
+ * Auth status summary
116
+ */
117
+ interface AuthStatus {
118
+ authenticated: boolean;
119
+ sources: DetectedCredential[];
120
+ preferredSource?: DetectedCredential;
121
+ warnings?: string[];
122
+ }
84
123
 
85
124
  /**
86
125
  * Configuration loading and validation
@@ -135,6 +174,8 @@ declare function launchAgent(agent: AgentDefinition, options?: {
135
174
  cwd?: string;
136
175
  env?: Record<string, string>;
137
176
  stdio?: 'inherit' | 'pipe';
177
+ useExternalAuth?: boolean;
178
+ externalAuthConfig?: ExternalAuthConfig;
138
179
  }): Promise<void>;
139
180
 
140
181
  /**
@@ -327,4 +368,56 @@ declare function getProviderInfo(provider: 'env' | '1password' | 'vault'): {
327
368
  installUrl: string | null;
328
369
  };
329
370
 
330
- export { type AgentDefinition, type AgentStatus, type AgentsConfig, type ContainerConfig, type ContainerStatus, type ContextConfig, type DevcontainerConfig, type DotenvConfig, type EnvironmentStatus, type EnvrcConfig, type LoadedConfig, type LogLevel, type McpConfig, type McpServerConfig, type OpAuthStatus, type RapidConfig, type SecretStatus, type SecretsConfig, type SecretsStatus, checkAgentAvailable, checkAllAgents, execInContainer, generateEnvrc, getAgent, getContainerName, getContainerStatus, getDefaultAgent, getDefaultConfig, getDevcontainerPath, getLogLevel, getOpAuthStatus, getProviderInfo, hasDevcontainerCli, hasDocker, hasEnvrc, hasOpCli, hasOpServiceAccountToken, hasVaultCli, isOpAuthenticated, isVaultAuthenticated, launchAgent, loadConfig, loadConfigFromFile, loadDevcontainerConfig, loadSecrets, logger, mergeWithDefaults, readEnvrc, readOpSecret, readVaultSecret, setLogLevel, startContainer, stopContainer, verifySecret, verifySecrets, writeEnvrc };
371
+ /**
372
+ * External Authentication Detection
373
+ *
374
+ * Detects and reuses credentials from AI coding tools like:
375
+ * - Claude Code (~/.claude.json)
376
+ * - OpenAI Codex (~/.codex/auth.json)
377
+ * - Gemini CLI (~/.gemini/)
378
+ * - Aider (.env files with API keys)
379
+ */
380
+
381
+ /**
382
+ * Detect Claude Code credentials from ~/.claude.json
383
+ */
384
+ declare function detectClaudeCodeAuth(): Promise<DetectedCredential | null>;
385
+ /**
386
+ * Detect OpenAI Codex credentials from ~/.codex/auth.json
387
+ */
388
+ declare function detectCodexAuth(): Promise<DetectedCredential | null>;
389
+ /**
390
+ * Detect Gemini CLI credentials from ~/.gemini/
391
+ */
392
+ declare function detectGeminiAuth(): Promise<DetectedCredential | null>;
393
+ /**
394
+ * Detect Aider credentials from environment variables
395
+ * Aider uses standard environment variables, no config file
396
+ */
397
+ declare function detectAiderAuth(): Promise<DetectedCredential[]>;
398
+ /**
399
+ * Detect credentials from standard environment variables
400
+ */
401
+ declare function detectEnvAuth(): Promise<DetectedCredential[]>;
402
+ /**
403
+ * Detect all available credentials from external sources
404
+ */
405
+ declare function detectAllCredentials(config?: ExternalAuthConfig): Promise<DetectedCredential[]>;
406
+ /**
407
+ * Get authentication status summary
408
+ */
409
+ declare function getAuthStatus(config?: ExternalAuthConfig): Promise<AuthStatus>;
410
+ /**
411
+ * Get credentials for a specific provider
412
+ */
413
+ declare function getCredentialsForProvider(provider: 'anthropic' | 'openai' | 'google', config?: ExternalAuthConfig): Promise<DetectedCredential | null>;
414
+ /**
415
+ * Get environment variables to inject based on detected credentials
416
+ */
417
+ declare function getAuthEnvironment(config?: ExternalAuthConfig): Promise<Record<string, string>>;
418
+ /**
419
+ * Format auth status for display
420
+ */
421
+ declare function formatAuthStatus(status: AuthStatus): string;
422
+
423
+ export { type AgentDefinition, type AgentStatus, type AgentsConfig, type AuthStatus, type ContainerConfig, type ContainerStatus, type ContextConfig, type DetectedCredential, type DevcontainerConfig, type DotenvConfig, type EnvironmentStatus, type EnvrcConfig, type ExternalAuthConfig, type ExternalAuthSource, type LoadedConfig, type LogLevel, type McpConfig, type McpServerConfig, type OpAuthStatus, type RapidConfig, type SecretStatus, type SecretsConfig, type SecretsStatus, checkAgentAvailable, checkAllAgents, detectAiderAuth, detectAllCredentials, detectClaudeCodeAuth, detectCodexAuth, detectEnvAuth, detectGeminiAuth, execInContainer, formatAuthStatus, generateEnvrc, getAgent, getAuthEnvironment, getAuthStatus, getContainerName, getContainerStatus, getCredentialsForProvider, getDefaultAgent, getDefaultConfig, getDevcontainerPath, getLogLevel, getOpAuthStatus, getProviderInfo, hasDevcontainerCli, hasDocker, hasEnvrc, hasOpCli, hasOpServiceAccountToken, hasVaultCli, isOpAuthenticated, isVaultAuthenticated, launchAgent, loadConfig, loadConfigFromFile, loadDevcontainerConfig, loadSecrets, logger, mergeWithDefaults, readEnvrc, readOpSecret, readVaultSecret, setLogLevel, startContainer, stopContainer, verifySecret, verifySecrets, writeEnvrc };
package/dist/index.js CHANGED
@@ -94,58 +94,11 @@ function mergeWithDefaults(config) {
94
94
  // src/agents.ts
95
95
  import { execa } from "execa";
96
96
  import which from "which";
97
- async function checkAgentAvailable(agent) {
98
- try {
99
- const cliPath = await which(agent.cli);
100
- let version;
101
- try {
102
- const result = await execa(agent.cli, ["--version"], { timeout: 5e3 });
103
- version = result.stdout.trim().split("\n")[0];
104
- } catch {
105
- }
106
- return {
107
- name: agent.cli,
108
- available: true,
109
- cliPath,
110
- ...version !== void 0 && { version }
111
- };
112
- } catch {
113
- return {
114
- name: agent.cli,
115
- available: false
116
- };
117
- }
118
- }
119
- async function checkAllAgents(config) {
120
- const results = [];
121
- for (const [name, agent] of Object.entries(config.agents.available)) {
122
- const status = await checkAgentAvailable(agent);
123
- results.push({
124
- ...status,
125
- name
126
- });
127
- }
128
- return results;
129
- }
130
- function getDefaultAgent(config) {
131
- const defaultName = config.agents.default;
132
- return config.agents.available[defaultName] || null;
133
- }
134
- function getAgent(config, name) {
135
- return config.agents.available[name] || null;
136
- }
137
- async function launchAgent(agent, options = {}) {
138
- const args = agent.args ?? [];
139
- const cwd = options.cwd ?? process.cwd();
140
- await execa(agent.cli, args, {
141
- cwd,
142
- env: {
143
- ...process.env,
144
- ...options.env
145
- },
146
- stdio: options.stdio ?? "inherit"
147
- });
148
- }
97
+
98
+ // src/external-auth.ts
99
+ import { readFile as readFile2, access } from "fs/promises";
100
+ import { homedir } from "os";
101
+ import { join } from "path";
149
102
 
150
103
  // src/logger.ts
151
104
  import chalk from "chalk";
@@ -213,11 +166,485 @@ var logger = {
213
166
  }
214
167
  };
215
168
 
169
+ // src/external-auth.ts
170
+ var DEFAULT_CONFIG = {
171
+ enabled: true,
172
+ sources: ["claude-code", "codex", "gemini-cli", "aider", "env"]
173
+ };
174
+ async function fileExists(path) {
175
+ try {
176
+ await access(path);
177
+ return true;
178
+ } catch {
179
+ return false;
180
+ }
181
+ }
182
+ async function readJsonFile(path) {
183
+ try {
184
+ const content = await readFile2(path, "utf-8");
185
+ return JSON.parse(content);
186
+ } catch {
187
+ return null;
188
+ }
189
+ }
190
+ async function detectClaudeCodeAuth() {
191
+ const home = homedir();
192
+ const configPath = join(home, ".claude.json");
193
+ if (!await fileExists(configPath)) {
194
+ return null;
195
+ }
196
+ const config = await readJsonFile(configPath);
197
+ if (!config) {
198
+ return null;
199
+ }
200
+ const oauth = config.oauthAccount || config.claudeAiOauth;
201
+ if (oauth?.accessToken) {
202
+ const expiresAt = oauth.expiresAt ? new Date(oauth.expiresAt) : void 0;
203
+ if (expiresAt && expiresAt < /* @__PURE__ */ new Date()) {
204
+ logger.debug("Claude Code OAuth token expired");
205
+ return null;
206
+ }
207
+ const cred = {
208
+ source: "claude-code",
209
+ provider: "anthropic",
210
+ authType: "oauth",
211
+ value: oauth.accessToken,
212
+ configPath
213
+ };
214
+ if (expiresAt) {
215
+ cred.expiresAt = expiresAt;
216
+ }
217
+ const accountInfo = {};
218
+ if (config.oauthAccount?.emailAddress) {
219
+ accountInfo.email = config.oauthAccount.emailAddress;
220
+ }
221
+ if (config.oauthAccount?.organizationName) {
222
+ accountInfo.organization = config.oauthAccount.organizationName;
223
+ }
224
+ if (config.oauthAccount?.planType) {
225
+ accountInfo.plan = config.oauthAccount.planType;
226
+ }
227
+ if (Object.keys(accountInfo).length > 0) {
228
+ cred.accountInfo = accountInfo;
229
+ }
230
+ return cred;
231
+ }
232
+ const apiKey = process.env.ANTHROPIC_API_KEY;
233
+ if (apiKey) {
234
+ return {
235
+ source: "claude-code",
236
+ provider: "anthropic",
237
+ authType: "api-key",
238
+ envVar: "ANTHROPIC_API_KEY",
239
+ value: apiKey,
240
+ configPath
241
+ };
242
+ }
243
+ return null;
244
+ }
245
+ async function detectCodexAuth() {
246
+ const home = homedir();
247
+ const configPath = join(home, ".codex", "auth.json");
248
+ if (!await fileExists(configPath)) {
249
+ return null;
250
+ }
251
+ const config = await readJsonFile(configPath);
252
+ if (!config) {
253
+ return null;
254
+ }
255
+ if (config.chatgpt?.accessToken) {
256
+ const expiresAt = config.chatgpt.expiresAt ? new Date(config.chatgpt.expiresAt) : void 0;
257
+ if (expiresAt && expiresAt < /* @__PURE__ */ new Date()) {
258
+ logger.debug("Codex ChatGPT OAuth token expired");
259
+ return null;
260
+ }
261
+ const cred = {
262
+ source: "codex",
263
+ provider: "openai",
264
+ authType: "oauth",
265
+ value: config.chatgpt.accessToken,
266
+ configPath
267
+ };
268
+ if (expiresAt) {
269
+ cred.expiresAt = expiresAt;
270
+ }
271
+ const accountInfo = {};
272
+ if (config.chatgpt.email) {
273
+ accountInfo.email = config.chatgpt.email;
274
+ }
275
+ if (config.chatgpt.workspaceId) {
276
+ accountInfo.organization = config.chatgpt.workspaceId;
277
+ }
278
+ if (Object.keys(accountInfo).length > 0) {
279
+ cred.accountInfo = accountInfo;
280
+ }
281
+ return cred;
282
+ }
283
+ if (config.api?.apiKey) {
284
+ return {
285
+ source: "codex",
286
+ provider: "openai",
287
+ authType: "api-key",
288
+ value: config.api.apiKey,
289
+ configPath
290
+ };
291
+ }
292
+ const apiKey = process.env.OPENAI_API_KEY;
293
+ if (apiKey) {
294
+ return {
295
+ source: "codex",
296
+ provider: "openai",
297
+ authType: "api-key",
298
+ envVar: "OPENAI_API_KEY",
299
+ value: apiKey
300
+ };
301
+ }
302
+ return null;
303
+ }
304
+ async function detectGeminiAuth() {
305
+ const home = homedir();
306
+ const settingsPath = join(home, ".gemini", "settings.json");
307
+ if (await fileExists(settingsPath)) {
308
+ const settings = await readJsonFile(settingsPath);
309
+ if (settings?.auth?.oauth?.accessToken) {
310
+ const oauth = settings.auth.oauth;
311
+ const expiresAt = oauth.expiresAt ? new Date(oauth.expiresAt) : void 0;
312
+ if (expiresAt && expiresAt < /* @__PURE__ */ new Date()) {
313
+ logger.debug("Gemini CLI OAuth token expired");
314
+ } else {
315
+ const cred = {
316
+ source: "gemini-cli",
317
+ provider: "google",
318
+ authType: "oauth",
319
+ value: oauth.accessToken,
320
+ configPath: settingsPath
321
+ };
322
+ if (expiresAt) {
323
+ cred.expiresAt = expiresAt;
324
+ }
325
+ const accountInfo = {};
326
+ if (oauth.email) {
327
+ accountInfo.email = oauth.email;
328
+ }
329
+ if (settings.googleCloudProject) {
330
+ accountInfo.organization = settings.googleCloudProject;
331
+ }
332
+ if (Object.keys(accountInfo).length > 0) {
333
+ cred.accountInfo = accountInfo;
334
+ }
335
+ return cred;
336
+ }
337
+ }
338
+ }
339
+ const geminiKey = process.env.GEMINI_API_KEY;
340
+ if (geminiKey) {
341
+ return {
342
+ source: "gemini-cli",
343
+ provider: "google",
344
+ authType: "api-key",
345
+ envVar: "GEMINI_API_KEY",
346
+ value: geminiKey
347
+ };
348
+ }
349
+ const googleKey = process.env.GOOGLE_API_KEY;
350
+ if (googleKey) {
351
+ return {
352
+ source: "gemini-cli",
353
+ provider: "google",
354
+ authType: "api-key",
355
+ envVar: "GOOGLE_API_KEY",
356
+ value: googleKey
357
+ };
358
+ }
359
+ return null;
360
+ }
361
+ async function detectAiderAuth() {
362
+ const credentials = [];
363
+ const anthropicKey = process.env.ANTHROPIC_API_KEY;
364
+ if (anthropicKey) {
365
+ credentials.push({
366
+ source: "aider",
367
+ provider: "anthropic",
368
+ authType: "api-key",
369
+ envVar: "ANTHROPIC_API_KEY",
370
+ value: anthropicKey
371
+ });
372
+ }
373
+ const openaiKey = process.env.OPENAI_API_KEY;
374
+ if (openaiKey) {
375
+ credentials.push({
376
+ source: "aider",
377
+ provider: "openai",
378
+ authType: "api-key",
379
+ envVar: "OPENAI_API_KEY",
380
+ value: openaiKey
381
+ });
382
+ }
383
+ const geminiKey = process.env.GEMINI_API_KEY;
384
+ if (geminiKey) {
385
+ credentials.push({
386
+ source: "aider",
387
+ provider: "google",
388
+ authType: "api-key",
389
+ envVar: "GEMINI_API_KEY",
390
+ value: geminiKey
391
+ });
392
+ }
393
+ return credentials;
394
+ }
395
+ async function detectEnvAuth() {
396
+ const credentials = [];
397
+ const envMappings = [
398
+ { envVar: "ANTHROPIC_API_KEY", provider: "anthropic" },
399
+ { envVar: "OPENAI_API_KEY", provider: "openai" },
400
+ { envVar: "GEMINI_API_KEY", provider: "google" },
401
+ { envVar: "GOOGLE_API_KEY", provider: "google" }
402
+ ];
403
+ for (const { envVar, provider } of envMappings) {
404
+ const value = process.env[envVar];
405
+ if (value) {
406
+ credentials.push({
407
+ source: "env",
408
+ provider,
409
+ authType: "api-key",
410
+ envVar,
411
+ value
412
+ });
413
+ }
414
+ }
415
+ return credentials;
416
+ }
417
+ async function detectAllCredentials(config = DEFAULT_CONFIG) {
418
+ if (!config.enabled) {
419
+ return [];
420
+ }
421
+ const sources = config.sources || DEFAULT_CONFIG.sources;
422
+ const credentials = [];
423
+ const seenValues = /* @__PURE__ */ new Set();
424
+ for (const source of sources) {
425
+ try {
426
+ let detected = null;
427
+ switch (source) {
428
+ case "claude-code":
429
+ detected = await detectClaudeCodeAuth();
430
+ break;
431
+ case "codex":
432
+ detected = await detectCodexAuth();
433
+ break;
434
+ case "gemini-cli":
435
+ detected = await detectGeminiAuth();
436
+ break;
437
+ case "aider":
438
+ detected = await detectAiderAuth();
439
+ break;
440
+ case "env":
441
+ detected = await detectEnvAuth();
442
+ break;
443
+ }
444
+ if (detected) {
445
+ const items = Array.isArray(detected) ? detected : [detected];
446
+ for (const item of items) {
447
+ const key = item.value || item.envVar || "";
448
+ if (key && !seenValues.has(key)) {
449
+ seenValues.add(key);
450
+ credentials.push(item);
451
+ }
452
+ }
453
+ }
454
+ } catch (error) {
455
+ logger.debug(`Error detecting ${source} credentials:`, error);
456
+ }
457
+ }
458
+ return credentials;
459
+ }
460
+ async function getAuthStatus(config = DEFAULT_CONFIG) {
461
+ const credentials = await detectAllCredentials(config);
462
+ const warnings = [];
463
+ for (const cred of credentials) {
464
+ if (cred.expiresAt && cred.expiresAt < /* @__PURE__ */ new Date()) {
465
+ warnings.push(`${cred.source} OAuth token has expired. Please re-authenticate.`);
466
+ }
467
+ }
468
+ let preferredSource;
469
+ if (config.preferSource) {
470
+ preferredSource = credentials.find((c) => c.source === config.preferSource);
471
+ }
472
+ if (!preferredSource && credentials.length > 0) {
473
+ preferredSource = credentials.find((c) => c.authType === "oauth") || credentials[0];
474
+ }
475
+ const result = {
476
+ authenticated: credentials.length > 0,
477
+ sources: credentials
478
+ };
479
+ if (preferredSource) {
480
+ result.preferredSource = preferredSource;
481
+ }
482
+ if (warnings.length > 0) {
483
+ result.warnings = warnings;
484
+ }
485
+ return result;
486
+ }
487
+ async function getCredentialsForProvider(provider, config = DEFAULT_CONFIG) {
488
+ const credentials = await detectAllCredentials(config);
489
+ const providerCreds = credentials.filter((c) => c.provider === provider);
490
+ if (providerCreds.length === 0) {
491
+ return null;
492
+ }
493
+ const found = providerCreds.find((c) => c.authType === "oauth");
494
+ return found || providerCreds[0] || null;
495
+ }
496
+ async function getAuthEnvironment(config = DEFAULT_CONFIG) {
497
+ const credentials = await detectAllCredentials(config);
498
+ const env = {};
499
+ const byProvider = /* @__PURE__ */ new Map();
500
+ for (const cred of credentials) {
501
+ const existing = byProvider.get(cred.provider);
502
+ if (!existing || cred.authType === "oauth" && existing.authType !== "oauth") {
503
+ byProvider.set(cred.provider, cred);
504
+ }
505
+ }
506
+ for (const [provider, cred] of byProvider) {
507
+ if (!cred.value) continue;
508
+ switch (provider) {
509
+ case "anthropic":
510
+ if (cred.authType === "oauth") {
511
+ env["ANTHROPIC_AUTH_TOKEN"] = cred.value;
512
+ } else {
513
+ env["ANTHROPIC_API_KEY"] = cred.value;
514
+ }
515
+ break;
516
+ case "openai":
517
+ if (cred.authType === "oauth") {
518
+ env["OPENAI_AUTH_TOKEN"] = cred.value;
519
+ } else {
520
+ env["OPENAI_API_KEY"] = cred.value;
521
+ }
522
+ break;
523
+ case "google":
524
+ if (cred.authType === "oauth") {
525
+ env["GOOGLE_AUTH_TOKEN"] = cred.value;
526
+ } else {
527
+ if (cred.envVar === "GOOGLE_API_KEY") {
528
+ env["GOOGLE_API_KEY"] = cred.value;
529
+ } else {
530
+ env["GEMINI_API_KEY"] = cred.value;
531
+ }
532
+ }
533
+ break;
534
+ }
535
+ }
536
+ return env;
537
+ }
538
+ function formatAuthStatus(status) {
539
+ const lines = [];
540
+ if (!status.authenticated) {
541
+ lines.push("No authentication detected");
542
+ lines.push("");
543
+ lines.push("To authenticate, either:");
544
+ lines.push(" - Log in with Claude Code: claude");
545
+ lines.push(" - Log in with Codex: codex");
546
+ lines.push(" - Log in with Gemini CLI: gemini");
547
+ lines.push(" - Set environment variables (ANTHROPIC_API_KEY, OPENAI_API_KEY, etc.)");
548
+ return lines.join("\n");
549
+ }
550
+ lines.push("Detected authentication sources:");
551
+ lines.push("");
552
+ for (const cred of status.sources) {
553
+ const isPrimary = cred === status.preferredSource;
554
+ const prefix = isPrimary ? "* " : " ";
555
+ const authType = cred.authType === "oauth" ? "OAuth" : "API Key";
556
+ let line = `${prefix}${cred.source} (${cred.provider}, ${authType})`;
557
+ if (cred.accountInfo?.email) {
558
+ line += ` - ${cred.accountInfo.email}`;
559
+ }
560
+ if (cred.accountInfo?.plan) {
561
+ line += ` [${cred.accountInfo.plan}]`;
562
+ }
563
+ if (cred.expiresAt) {
564
+ const expiresIn = Math.round((cred.expiresAt.getTime() - Date.now()) / 1e3 / 60);
565
+ if (expiresIn > 0) {
566
+ line += ` (expires in ${expiresIn}m)`;
567
+ } else {
568
+ line += " (EXPIRED)";
569
+ }
570
+ }
571
+ lines.push(line);
572
+ }
573
+ if (status.warnings && status.warnings.length > 0) {
574
+ lines.push("");
575
+ lines.push("Warnings:");
576
+ for (const warning of status.warnings) {
577
+ lines.push(` ! ${warning}`);
578
+ }
579
+ }
580
+ return lines.join("\n");
581
+ }
582
+
583
+ // src/agents.ts
584
+ async function checkAgentAvailable(agent) {
585
+ try {
586
+ const cliPath = await which(agent.cli);
587
+ let version;
588
+ try {
589
+ const result = await execa(agent.cli, ["--version"], { timeout: 5e3 });
590
+ version = result.stdout.trim().split("\n")[0];
591
+ } catch {
592
+ }
593
+ return {
594
+ name: agent.cli,
595
+ available: true,
596
+ cliPath,
597
+ ...version !== void 0 && { version }
598
+ };
599
+ } catch {
600
+ return {
601
+ name: agent.cli,
602
+ available: false
603
+ };
604
+ }
605
+ }
606
+ async function checkAllAgents(config) {
607
+ const results = [];
608
+ for (const [name, agent] of Object.entries(config.agents.available)) {
609
+ const status = await checkAgentAvailable(agent);
610
+ results.push({
611
+ ...status,
612
+ name
613
+ });
614
+ }
615
+ return results;
616
+ }
617
+ function getDefaultAgent(config) {
618
+ const defaultName = config.agents.default;
619
+ return config.agents.available[defaultName] || null;
620
+ }
621
+ function getAgent(config, name) {
622
+ return config.agents.available[name] || null;
623
+ }
624
+ async function launchAgent(agent, options = {}) {
625
+ const args = agent.args ?? [];
626
+ const cwd = options.cwd ?? process.cwd();
627
+ let authEnv = {};
628
+ if (options.useExternalAuth !== false) {
629
+ authEnv = await getAuthEnvironment(options.externalAuthConfig);
630
+ }
631
+ await execa(agent.cli, args, {
632
+ cwd,
633
+ env: {
634
+ ...process.env,
635
+ ...authEnv,
636
+ ...options.env
637
+ // User-provided env takes precedence
638
+ },
639
+ stdio: options.stdio ?? "inherit"
640
+ });
641
+ }
642
+
216
643
  // src/container.ts
217
644
  import { execa as execa2 } from "execa";
218
645
  import which2 from "which";
219
- import { readFile as readFile2 } from "fs/promises";
220
- import { join } from "path";
646
+ import { readFile as readFile3 } from "fs/promises";
647
+ import { join as join2 } from "path";
221
648
  async function hasDevcontainerCli() {
222
649
  try {
223
650
  await which2("devcontainer");
@@ -237,14 +664,14 @@ async function hasDocker() {
237
664
  function getDevcontainerPath(rootDir, config) {
238
665
  const customPath = config?.container?.devcontainer;
239
666
  if (customPath) {
240
- return join(rootDir, customPath);
667
+ return join2(rootDir, customPath);
241
668
  }
242
- return join(rootDir, ".devcontainer", "devcontainer.json");
669
+ return join2(rootDir, ".devcontainer", "devcontainer.json");
243
670
  }
244
671
  async function loadDevcontainerConfig(rootDir, config) {
245
672
  try {
246
673
  const configPath = getDevcontainerPath(rootDir, config);
247
- const content = await readFile2(configPath, "utf-8");
674
+ const content = await readFile3(configPath, "utf-8");
248
675
  return JSON.parse(content);
249
676
  } catch {
250
677
  return null;
@@ -370,8 +797,8 @@ async function execInContainer(rootDir, command, _config, options = {}) {
370
797
 
371
798
  // src/secrets.ts
372
799
  import { spawn } from "child_process";
373
- import { readFile as readFile3, writeFile, access } from "fs/promises";
374
- import { join as join2 } from "path";
800
+ import { readFile as readFile4, writeFile, access as access2 } from "fs/promises";
801
+ import { join as join3 } from "path";
375
802
  async function execCommand(command, args, options = {}) {
376
803
  return new Promise((resolve2) => {
377
804
  const proc = spawn(command, args, {
@@ -629,16 +1056,16 @@ function generateEnvrc(config) {
629
1056
  }
630
1057
  async function writeEnvrc(rootDir, config) {
631
1058
  const envrcPath = config.envrc?.path || ".envrc";
632
- const fullPath = join2(rootDir, envrcPath);
1059
+ const fullPath = join3(rootDir, envrcPath);
633
1060
  const content = generateEnvrc(config);
634
1061
  await writeFile(fullPath, content);
635
1062
  return fullPath;
636
1063
  }
637
1064
  async function hasEnvrc(rootDir, config) {
638
1065
  const envrcPath = config?.envrc?.path || ".envrc";
639
- const fullPath = join2(rootDir, envrcPath);
1066
+ const fullPath = join3(rootDir, envrcPath);
640
1067
  try {
641
- await access(fullPath);
1068
+ await access2(fullPath);
642
1069
  return true;
643
1070
  } catch {
644
1071
  return false;
@@ -646,9 +1073,9 @@ async function hasEnvrc(rootDir, config) {
646
1073
  }
647
1074
  async function readEnvrc(rootDir, config) {
648
1075
  const envrcPath = config?.envrc?.path || ".envrc";
649
- const fullPath = join2(rootDir, envrcPath);
1076
+ const fullPath = join3(rootDir, envrcPath);
650
1077
  try {
651
- const content = await readFile3(fullPath, "utf-8");
1078
+ const content = await readFile4(fullPath, "utf-8");
652
1079
  return content;
653
1080
  } catch {
654
1081
  return null;
@@ -682,11 +1109,21 @@ function getProviderInfo(provider) {
682
1109
  export {
683
1110
  checkAgentAvailable,
684
1111
  checkAllAgents,
1112
+ detectAiderAuth,
1113
+ detectAllCredentials,
1114
+ detectClaudeCodeAuth,
1115
+ detectCodexAuth,
1116
+ detectEnvAuth,
1117
+ detectGeminiAuth,
685
1118
  execInContainer,
1119
+ formatAuthStatus,
686
1120
  generateEnvrc,
687
1121
  getAgent,
1122
+ getAuthEnvironment,
1123
+ getAuthStatus,
688
1124
  getContainerName,
689
1125
  getContainerStatus,
1126
+ getCredentialsForProvider,
690
1127
  getDefaultAgent,
691
1128
  getDefaultConfig,
692
1129
  getDevcontainerPath,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/config.ts","../src/agents.ts","../src/logger.ts","../src/container.ts","../src/secrets.ts"],"sourcesContent":["/**\n * Configuration loading and validation\n */\n\nimport { cosmiconfig } from 'cosmiconfig';\nimport { readFile } from 'node:fs/promises';\nimport { dirname, resolve } from 'node:path';\nimport type { RapidConfig } from './types.js';\n\nconst CONFIG_NAME = 'rapid';\nconst CONFIG_FILES = ['rapid.json', 'rapid.config.json', '.rapidrc', '.rapidrc.json'];\n\nexport interface LoadedConfig {\n config: RapidConfig;\n filepath: string;\n rootDir: string;\n}\n\n/**\n * Load RAPID configuration from the current directory or ancestors\n */\nexport async function loadConfig(cwd?: string): Promise<LoadedConfig | null> {\n const explorer = cosmiconfig(CONFIG_NAME, {\n searchPlaces: CONFIG_FILES,\n loaders: {\n '.json': async (filepath) => {\n const content = await readFile(filepath, 'utf-8');\n return JSON.parse(content);\n },\n },\n });\n\n const result = await explorer.search(cwd);\n\n if (!result || result.isEmpty) {\n return null;\n }\n\n return {\n config: result.config as RapidConfig,\n filepath: result.filepath,\n rootDir: dirname(result.filepath),\n };\n}\n\n/**\n * Load configuration from a specific file\n */\nexport async function loadConfigFromFile(filepath: string): Promise<LoadedConfig> {\n const content = await readFile(filepath, 'utf-8');\n const config = JSON.parse(content) as RapidConfig;\n\n return {\n config,\n filepath: resolve(filepath),\n rootDir: dirname(resolve(filepath)),\n };\n}\n\n/**\n * Get default configuration\n */\nexport function getDefaultConfig(): RapidConfig {\n return {\n version: '1.0',\n agents: {\n default: 'claude',\n available: {\n claude: {\n cli: 'claude',\n instructionFile: 'CLAUDE.md',\n envVars: ['ANTHROPIC_API_KEY'],\n },\n opencode: {\n cli: 'opencode',\n instructionFile: 'AGENTS.md',\n envVars: ['ANTHROPIC_API_KEY'],\n },\n aider: {\n cli: 'aider',\n instructionFile: 'AGENTS.md',\n envVars: ['ANTHROPIC_API_KEY'],\n args: ['--model', 'claude-3-5-sonnet-20241022'],\n },\n },\n },\n secrets: {\n provider: 'env',\n },\n context: {\n files: ['README.md'],\n dirs: ['docs/'],\n generateAgentFiles: true,\n },\n };\n}\n\n/**\n * Merge user config with defaults\n */\nexport function mergeWithDefaults(config: Partial<RapidConfig>): RapidConfig {\n const defaults = getDefaultConfig();\n\n return {\n ...defaults,\n ...config,\n agents: {\n ...defaults.agents,\n ...config.agents,\n available: {\n ...defaults.agents.available,\n ...config.agents?.available,\n },\n },\n secrets: {\n ...defaults.secrets,\n ...config.secrets,\n },\n context: {\n ...defaults.context,\n ...config.context,\n },\n };\n}\n","/**\n * Agent detection and management\n */\n\nimport { execa } from 'execa';\nimport which from 'which';\nimport type { AgentDefinition, AgentStatus, RapidConfig } from './types.js';\n\n/**\n * Check if an agent CLI is available\n */\nexport async function checkAgentAvailable(agent: AgentDefinition): Promise<AgentStatus> {\n try {\n const cliPath = await which(agent.cli);\n\n // Try to get version\n let version: string | undefined;\n try {\n const result = await execa(agent.cli, ['--version'], { timeout: 5000 });\n version = result.stdout.trim().split('\\n')[0];\n } catch {\n // Version check failed, but CLI exists\n }\n\n return {\n name: agent.cli,\n available: true,\n cliPath,\n ...(version !== undefined && { version }),\n };\n } catch {\n return {\n name: agent.cli,\n available: false,\n };\n }\n}\n\n/**\n * Check all configured agents\n */\nexport async function checkAllAgents(config: RapidConfig): Promise<AgentStatus[]> {\n const results: AgentStatus[] = [];\n\n for (const [name, agent] of Object.entries(config.agents.available)) {\n const status = await checkAgentAvailable(agent);\n results.push({\n ...status,\n name,\n });\n }\n\n return results;\n}\n\n/**\n * Get the default agent from config\n */\nexport function getDefaultAgent(config: RapidConfig): AgentDefinition | null {\n const defaultName = config.agents.default;\n return config.agents.available[defaultName] || null;\n}\n\n/**\n * Get a specific agent by name\n */\nexport function getAgent(config: RapidConfig, name: string): AgentDefinition | null {\n return config.agents.available[name] || null;\n}\n\n/**\n * Launch an agent CLI\n */\nexport async function launchAgent(\n agent: AgentDefinition,\n options: {\n cwd?: string;\n env?: Record<string, string>;\n stdio?: 'inherit' | 'pipe';\n } = {}\n): Promise<void> {\n const args = agent.args ?? [];\n const cwd = options.cwd ?? process.cwd();\n\n await execa(agent.cli, args, {\n cwd,\n env: {\n ...process.env,\n ...options.env,\n },\n stdio: options.stdio ?? 'inherit',\n });\n}\n","/**\n * Logging utilities\n */\n\nimport chalk from 'chalk';\n\nexport type LogLevel = 'debug' | 'info' | 'warn' | 'error';\n\nconst LOG_LEVELS: Record<LogLevel, number> = {\n debug: 0,\n info: 1,\n warn: 2,\n error: 3,\n};\n\nlet currentLevel: LogLevel = 'info';\n\nexport function setLogLevel(level: LogLevel): void {\n currentLevel = level;\n}\n\nexport function getLogLevel(): LogLevel {\n return currentLevel;\n}\n\nfunction shouldLog(level: LogLevel): boolean {\n return LOG_LEVELS[level] >= LOG_LEVELS[currentLevel];\n}\n\nexport const logger = {\n debug(message: string, ...args: unknown[]): void {\n if (shouldLog('debug')) {\n console.log(chalk.gray(`[debug] ${message}`), ...args);\n }\n },\n\n info(message: string, ...args: unknown[]): void {\n if (shouldLog('info')) {\n console.log(chalk.blue('ℹ'), message, ...args);\n }\n },\n\n success(message: string, ...args: unknown[]): void {\n if (shouldLog('info')) {\n console.log(chalk.green('✓'), message, ...args);\n }\n },\n\n warn(message: string, ...args: unknown[]): void {\n if (shouldLog('warn')) {\n console.log(chalk.yellow('⚠'), message, ...args);\n }\n },\n\n error(message: string, ...args: unknown[]): void {\n if (shouldLog('error')) {\n console.error(chalk.red('✗'), message, ...args);\n }\n },\n\n // Styled output helpers\n brand(text: string): string {\n return chalk.hex('#818cf8')(text);\n },\n\n dim(text: string): string {\n return chalk.dim(text);\n },\n\n bold(text: string): string {\n return chalk.bold(text);\n },\n\n // Print a header\n header(text: string): void {\n console.log();\n console.log(chalk.bold(text));\n console.log(chalk.dim('─'.repeat(text.length)));\n },\n\n // Print a blank line\n blank(): void {\n console.log();\n },\n};\n","/**\n * Container management utilities\n * Uses devcontainer CLI for container lifecycle\n */\n\nimport { execa, type ExecaError } from 'execa';\nimport which from 'which';\nimport { readFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport type { RapidConfig } from './types.js';\n\nexport interface ContainerStatus {\n exists: boolean;\n running: boolean;\n containerId?: string;\n containerName?: string;\n}\n\nexport interface DevcontainerConfig {\n name?: string;\n image?: string;\n dockerFile?: string;\n build?: {\n dockerfile?: string;\n context?: string;\n };\n [key: string]: unknown;\n}\n\n/**\n * Check if devcontainer CLI is available\n */\nexport async function hasDevcontainerCli(): Promise<boolean> {\n try {\n await which('devcontainer');\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Check if Docker is available\n */\nexport async function hasDocker(): Promise<boolean> {\n try {\n await execa('docker', ['info'], { timeout: 5000 });\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Get the devcontainer.json path\n */\nexport function getDevcontainerPath(rootDir: string, config?: RapidConfig): string {\n const customPath = config?.container?.devcontainer;\n if (customPath) {\n return join(rootDir, customPath);\n }\n return join(rootDir, '.devcontainer', 'devcontainer.json');\n}\n\n/**\n * Load devcontainer.json\n */\nexport async function loadDevcontainerConfig(\n rootDir: string,\n config?: RapidConfig\n): Promise<DevcontainerConfig | null> {\n try {\n const configPath = getDevcontainerPath(rootDir, config);\n const content = await readFile(configPath, 'utf-8');\n return JSON.parse(content);\n } catch {\n return null;\n }\n}\n\n/**\n * Get container name for a project\n */\nexport function getContainerName(rootDir: string, devcontainerConfig?: DevcontainerConfig): string {\n // Use devcontainer name if available, otherwise derive from directory\n const dirName = rootDir.split('/').pop() || 'rapid';\n const name = devcontainerConfig?.name || dirName;\n // Sanitize for Docker container name\n return `rapid-${name}`.toLowerCase().replace(/[^a-z0-9-]/g, '-');\n}\n\n/**\n * Check container status using devcontainer labels\n */\nexport async function getContainerStatus(\n rootDir: string,\n _config?: RapidConfig\n): Promise<ContainerStatus> {\n try {\n // Use devcontainer label to find the container (this is how devcontainer CLI tracks containers)\n const result = await execa('docker', [\n 'ps',\n '-a',\n '--filter',\n `label=devcontainer.local_folder=${rootDir}`,\n '--format',\n '{{.ID}}\\t{{.State}}\\t{{.Names}}',\n ]);\n\n const lines = result.stdout.trim().split('\\n').filter(Boolean);\n if (lines.length === 0) {\n return { exists: false, running: false };\n }\n\n const parts = lines[0]?.split('\\t');\n const containerId = parts?.[0];\n const state = parts?.[1];\n const containerName = parts?.[2];\n\n if (!containerId || !containerName) {\n return { exists: false, running: false };\n }\n\n return {\n exists: true,\n running: state === 'running',\n containerId,\n containerName,\n };\n } catch {\n return { exists: false, running: false };\n }\n}\n\n/**\n * Start the dev container using devcontainer CLI\n */\nexport async function startContainer(\n rootDir: string,\n _config?: RapidConfig,\n options: { rebuild?: boolean; quiet?: boolean } = {}\n): Promise<{ success: boolean; containerId?: string; error?: string }> {\n const hasDevCli = await hasDevcontainerCli();\n\n if (!hasDevCli) {\n return {\n success: false,\n error: 'devcontainer CLI not found. Install with: npm install -g @devcontainers/cli',\n };\n }\n\n const hasDockerRunning = await hasDocker();\n if (!hasDockerRunning) {\n return {\n success: false,\n error: 'Docker is not running. Please start Docker Desktop.',\n };\n }\n\n try {\n const args = ['up', '--workspace-folder', rootDir];\n\n if (options.rebuild) {\n args.push('--remove-existing-container');\n }\n\n const result = await execa('devcontainer', args, {\n stdio: options.quiet ? 'pipe' : 'inherit',\n cwd: rootDir,\n });\n\n // Parse the container ID from output\n // devcontainer up outputs JSON with containerId\n if (options.quiet && result.stdout) {\n try {\n const output = JSON.parse(result.stdout);\n return { success: true, containerId: output.containerId };\n } catch {\n return { success: true };\n }\n }\n\n return { success: true };\n } catch (error) {\n const execError = error as ExecaError;\n const stderr = typeof execError.stderr === 'string' ? execError.stderr : undefined;\n return {\n success: false,\n error: stderr || execError.message,\n };\n }\n}\n\n/**\n * Stop the dev container\n */\nexport async function stopContainer(\n rootDir: string,\n config?: RapidConfig,\n options: { remove?: boolean } = {}\n): Promise<{ success: boolean; error?: string }> {\n const status = await getContainerStatus(rootDir, config);\n\n if (!status.exists) {\n return { success: true }; // Nothing to stop\n }\n\n try {\n if (status.running) {\n await execa('docker', ['stop', status.containerId!]);\n }\n\n if (options.remove) {\n await execa('docker', ['rm', status.containerId!]);\n }\n\n return { success: true };\n } catch (error) {\n const execError = error as ExecaError;\n const stderr = typeof execError.stderr === 'string' ? execError.stderr : undefined;\n return {\n success: false,\n error: stderr || execError.message,\n };\n }\n}\n\n/**\n * Execute a command inside the dev container\n */\nexport async function execInContainer(\n rootDir: string,\n command: string[],\n _config?: RapidConfig,\n options: { interactive?: boolean; tty?: boolean; env?: Record<string, string> } = {}\n): Promise<void> {\n const hasDevCli = await hasDevcontainerCli();\n\n if (!hasDevCli) {\n throw new Error('devcontainer CLI not found. Install with: npm install -g @devcontainers/cli');\n }\n\n const args = ['exec', '--workspace-folder', rootDir];\n\n // Add environment variables\n if (options.env) {\n for (const [key, value] of Object.entries(options.env)) {\n args.push('--remote-env', `${key}=${value}`);\n }\n }\n\n // Add the command\n args.push(...command);\n\n await execa('devcontainer', args, {\n stdio: 'inherit',\n cwd: rootDir,\n });\n}\n","/**\n * Secrets management for RAPID\n * Supports 1Password, HashiCorp Vault, and environment variables\n */\n\nimport { spawn } from 'node:child_process';\nimport { readFile, writeFile, access } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport type { SecretsConfig } from './types.js';\nimport { logger } from './logger.js';\n\nexport interface SecretStatus {\n name: string;\n reference: string;\n provider: 'env' | '1password' | 'vault';\n available: boolean;\n error?: string;\n}\n\nexport interface SecretsStatus {\n provider: 'env' | '1password' | 'vault';\n authenticated: boolean;\n authMethod?: 'service-account' | 'user' | 'token';\n secrets: SecretStatus[];\n allAvailable: boolean;\n}\n\nexport interface OpAuthStatus {\n authenticated: boolean;\n method: 'service-account' | 'user' | 'none';\n accountInfo?: string;\n}\n\n/**\n * Execute a command and return stdout\n */\nasync function execCommand(\n command: string,\n args: string[],\n options: { timeout?: number } = {}\n): Promise<{ stdout: string; stderr: string; exitCode: number }> {\n return new Promise((resolve) => {\n const proc = spawn(command, args, {\n stdio: ['pipe', 'pipe', 'pipe'],\n timeout: options.timeout ?? 30000,\n });\n\n let stdout = '';\n let stderr = '';\n\n proc.stdout?.on('data', (data) => {\n stdout += data.toString();\n });\n\n proc.stderr?.on('data', (data) => {\n stderr += data.toString();\n });\n\n proc.on('close', (code) => {\n resolve({ stdout: stdout.trim(), stderr: stderr.trim(), exitCode: code ?? 1 });\n });\n\n proc.on('error', (err) => {\n resolve({ stdout: '', stderr: err.message, exitCode: 1 });\n });\n });\n}\n\n/**\n * Check if 1Password CLI is installed\n */\nexport async function hasOpCli(): Promise<boolean> {\n const result = await execCommand('op', ['--version']);\n return result.exitCode === 0;\n}\n\n/**\n * Check if OP_SERVICE_ACCOUNT_TOKEN is set\n */\nexport function hasOpServiceAccountToken(): boolean {\n return !!process.env.OP_SERVICE_ACCOUNT_TOKEN;\n}\n\n/**\n * Check if 1Password CLI is authenticated (via service account or user)\n */\nexport async function isOpAuthenticated(): Promise<boolean> {\n // Service account token takes precedence\n if (hasOpServiceAccountToken()) {\n // Verify the token works by trying to list vaults\n const result = await execCommand('op', ['vault', 'list', '--format=json']);\n return result.exitCode === 0;\n }\n\n // Fall back to user authentication\n const result = await execCommand('op', ['account', 'list']);\n return result.exitCode === 0 && result.stdout.length > 0;\n}\n\n/**\n * Get detailed 1Password authentication status\n */\nexport async function getOpAuthStatus(): Promise<OpAuthStatus> {\n // Check for service account token first\n if (hasOpServiceAccountToken()) {\n const result = await execCommand('op', ['vault', 'list', '--format=json']);\n if (result.exitCode === 0) {\n return {\n authenticated: true,\n method: 'service-account',\n accountInfo: 'Service Account',\n };\n }\n return {\n authenticated: false,\n method: 'none',\n accountInfo: 'Invalid service account token',\n };\n }\n\n // Check for user authentication\n const result = await execCommand('op', ['account', 'list', '--format=json']);\n if (result.exitCode === 0 && result.stdout.length > 0) {\n try {\n const accounts = JSON.parse(result.stdout);\n if (accounts.length > 0) {\n return {\n authenticated: true,\n method: 'user',\n accountInfo: accounts[0].email || accounts[0].url,\n };\n }\n } catch {\n // Parse error, but command succeeded\n return {\n authenticated: true,\n method: 'user',\n };\n }\n }\n\n return {\n authenticated: false,\n method: 'none',\n };\n}\n\n/**\n * Check if HashiCorp Vault CLI is installed\n */\nexport async function hasVaultCli(): Promise<boolean> {\n const result = await execCommand('vault', ['--version']);\n return result.exitCode === 0;\n}\n\n/**\n * Check if HashiCorp Vault is authenticated\n */\nexport async function isVaultAuthenticated(): Promise<boolean> {\n const result = await execCommand('vault', ['token', 'lookup']);\n return result.exitCode === 0;\n}\n\n/**\n * Read a secret from 1Password\n * @param reference - 1Password reference (e.g., \"op://vault/item/field\")\n */\nexport async function readOpSecret(reference: string): Promise<string | null> {\n const result = await execCommand('op', ['read', reference]);\n if (result.exitCode !== 0) {\n return null;\n }\n return result.stdout;\n}\n\n/**\n * Read a secret from HashiCorp Vault\n * @param path - Vault path (e.g., \"secret/data/myproject\")\n * @param field - Field name within the secret\n */\nexport async function readVaultSecret(path: string, field: string): Promise<string | null> {\n const result = await execCommand('vault', ['kv', 'get', '-field', field, path]);\n if (result.exitCode !== 0) {\n return null;\n }\n return result.stdout;\n}\n\n/**\n * Verify a single secret is accessible\n */\nexport async function verifySecret(\n name: string,\n reference: string,\n provider: 'env' | '1password' | 'vault',\n config?: SecretsConfig\n): Promise<SecretStatus> {\n const status: SecretStatus = {\n name,\n reference,\n provider,\n available: false,\n };\n\n try {\n switch (provider) {\n case 'env': {\n const value = process.env[name];\n status.available = !!value && value.length > 0;\n if (!status.available) {\n status.error = 'Environment variable not set';\n }\n break;\n }\n\n case '1password': {\n // Reference should be in format op://vault/item/field\n const value = await readOpSecret(reference);\n status.available = value !== null;\n if (!status.available) {\n status.error = 'Secret not found in 1Password';\n }\n break;\n }\n\n case 'vault': {\n // Parse path and field from reference\n const field = reference.split('/').pop() || 'value';\n const vaultPath = reference.includes('/')\n ? reference.substring(0, reference.lastIndexOf('/'))\n : config?.vault || 'secret/data/default';\n\n const value = await readVaultSecret(vaultPath, field);\n status.available = value !== null;\n if (!status.available) {\n status.error = 'Secret not found in Vault';\n }\n break;\n }\n }\n } catch (error) {\n status.error = error instanceof Error ? error.message : String(error);\n status.available = false;\n }\n\n return status;\n}\n\n/**\n * Verify all secrets in configuration\n */\nexport async function verifySecrets(config: SecretsConfig): Promise<SecretsStatus> {\n const provider = config.provider || 'env';\n let authenticated = true;\n\n // Check authentication status for provider\n switch (provider) {\n case '1password':\n authenticated = await isOpAuthenticated();\n break;\n case 'vault':\n authenticated = await isVaultAuthenticated();\n break;\n case 'env':\n authenticated = true;\n break;\n }\n\n const secrets: SecretStatus[] = [];\n\n if (config.items) {\n for (const [name, reference] of Object.entries(config.items)) {\n const status = await verifySecret(name, reference, provider, config);\n secrets.push(status);\n }\n }\n\n const allAvailable = secrets.length === 0 || secrets.every((s) => s.available);\n\n return {\n provider,\n authenticated,\n secrets,\n allAvailable,\n };\n}\n\n/**\n * Load all secrets into environment\n */\nexport async function loadSecrets(config: SecretsConfig): Promise<Record<string, string>> {\n const provider = config.provider || 'env';\n const secrets: Record<string, string> = {};\n\n if (!config.items) {\n return secrets;\n }\n\n for (const [name, reference] of Object.entries(config.items)) {\n try {\n let value: string | null = null;\n\n switch (provider) {\n case 'env':\n value = process.env[name] || null;\n break;\n\n case '1password':\n value = await readOpSecret(reference);\n break;\n\n case 'vault': {\n const field = reference.split('/').pop() || 'value';\n const path = reference.substring(0, reference.lastIndexOf('/')) || config.vault || '';\n value = await readVaultSecret(path, field);\n break;\n }\n }\n\n if (value) {\n secrets[name] = value;\n }\n } catch (error) {\n logger.debug(`Failed to load secret ${name}: ${error}`);\n }\n }\n\n return secrets;\n}\n\n/**\n * Generate .envrc file from secrets configuration\n */\nexport function generateEnvrc(config: SecretsConfig): string {\n const provider = config.provider || 'env';\n const lines: string[] = [\n '# .envrc - RAPID project secrets',\n '# This file is safe to commit - it contains NO secrets, only references',\n '#',\n `# Provider: ${provider}`,\n `# Generated by: rapid secrets generate`,\n '',\n ];\n\n if (!config.items || Object.keys(config.items).length === 0) {\n lines.push('# No secrets configured in rapid.json');\n return lines.join('\\n');\n }\n\n switch (provider) {\n case '1password':\n lines.push('# Secrets loaded from 1Password');\n lines.push('# Requires: 1Password CLI (op) installed and authenticated');\n lines.push('');\n for (const [name, reference] of Object.entries(config.items)) {\n lines.push(`export ${name}=$(op read \"${reference}\")`);\n }\n break;\n\n case 'vault':\n lines.push('# Secrets loaded from HashiCorp Vault');\n lines.push('# Requires: Vault CLI installed and authenticated');\n lines.push('');\n if (config.address) {\n lines.push(`export VAULT_ADDR=\"${config.address}\"`);\n lines.push('');\n }\n for (const [name, reference] of Object.entries(config.items)) {\n const path = config.vault || 'secret/data/default';\n lines.push(`export ${name}=$(vault kv get -field=${reference} ${path})`);\n }\n break;\n\n case 'env':\n lines.push('# WARNING: env provider expects secrets to be set manually');\n lines.push('# Consider using 1password or vault for better security');\n lines.push('');\n lines.push('# Uncomment and set values (DO NOT commit actual values!)');\n for (const name of Object.keys(config.items)) {\n lines.push(`# export ${name}=\"your-value-here\"`);\n }\n break;\n }\n\n // Add .env.local loading if configured\n if (config.envrc?.includeLocal !== false) {\n lines.push('');\n lines.push('# Load local overrides if present');\n lines.push('[[ -f .env.local ]] && source_env .env.local');\n }\n\n lines.push('');\n return lines.join('\\n');\n}\n\n/**\n * Write .envrc file to project directory\n */\nexport async function writeEnvrc(rootDir: string, config: SecretsConfig): Promise<string> {\n const envrcPath = config.envrc?.path || '.envrc';\n const fullPath = join(rootDir, envrcPath);\n const content = generateEnvrc(config);\n\n await writeFile(fullPath, content);\n return fullPath;\n}\n\n/**\n * Check if .envrc exists in project\n */\nexport async function hasEnvrc(rootDir: string, config?: SecretsConfig): Promise<boolean> {\n const envrcPath = config?.envrc?.path || '.envrc';\n const fullPath = join(rootDir, envrcPath);\n\n try {\n await access(fullPath);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Read existing .envrc content\n */\nexport async function readEnvrc(rootDir: string, config?: SecretsConfig): Promise<string | null> {\n const envrcPath = config?.envrc?.path || '.envrc';\n const fullPath = join(rootDir, envrcPath);\n\n try {\n const content = await readFile(fullPath, 'utf-8');\n return content;\n } catch {\n return null;\n }\n}\n\n/**\n * Get a summary of provider requirements\n */\nexport function getProviderInfo(provider: 'env' | '1password' | 'vault'): {\n name: string;\n cliRequired: string | null;\n authCommand: string | null;\n installUrl: string | null;\n} {\n switch (provider) {\n case '1password':\n return {\n name: '1Password',\n cliRequired: 'op',\n authCommand: 'eval $(op signin)',\n installUrl: 'https://developer.1password.com/docs/cli/get-started/',\n };\n case 'vault':\n return {\n name: 'HashiCorp Vault',\n cliRequired: 'vault',\n authCommand: 'vault login',\n installUrl: 'https://developer.hashicorp.com/vault/docs/install',\n };\n case 'env':\n return {\n name: 'Environment Variables',\n cliRequired: null,\n authCommand: null,\n installUrl: null,\n };\n }\n}\n"],"mappings":"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","names":["execa","which","readFile","readFile","join","resolve","result","join","readFile"]}
1
+ {"version":3,"sources":["../src/config.ts","../src/agents.ts","../src/external-auth.ts","../src/logger.ts","../src/container.ts","../src/secrets.ts"],"sourcesContent":["/**\n * Configuration loading and validation\n */\n\nimport { cosmiconfig } from 'cosmiconfig';\nimport { readFile } from 'node:fs/promises';\nimport { dirname, resolve } from 'node:path';\nimport type { RapidConfig } from './types.js';\n\nconst CONFIG_NAME = 'rapid';\nconst CONFIG_FILES = ['rapid.json', 'rapid.config.json', '.rapidrc', '.rapidrc.json'];\n\nexport interface LoadedConfig {\n config: RapidConfig;\n filepath: string;\n rootDir: string;\n}\n\n/**\n * Load RAPID configuration from the current directory or ancestors\n */\nexport async function loadConfig(cwd?: string): Promise<LoadedConfig | null> {\n const explorer = cosmiconfig(CONFIG_NAME, {\n searchPlaces: CONFIG_FILES,\n loaders: {\n '.json': async (filepath) => {\n const content = await readFile(filepath, 'utf-8');\n return JSON.parse(content);\n },\n },\n });\n\n const result = await explorer.search(cwd);\n\n if (!result || result.isEmpty) {\n return null;\n }\n\n return {\n config: result.config as RapidConfig,\n filepath: result.filepath,\n rootDir: dirname(result.filepath),\n };\n}\n\n/**\n * Load configuration from a specific file\n */\nexport async function loadConfigFromFile(filepath: string): Promise<LoadedConfig> {\n const content = await readFile(filepath, 'utf-8');\n const config = JSON.parse(content) as RapidConfig;\n\n return {\n config,\n filepath: resolve(filepath),\n rootDir: dirname(resolve(filepath)),\n };\n}\n\n/**\n * Get default configuration\n */\nexport function getDefaultConfig(): RapidConfig {\n return {\n version: '1.0',\n agents: {\n default: 'claude',\n available: {\n claude: {\n cli: 'claude',\n instructionFile: 'CLAUDE.md',\n envVars: ['ANTHROPIC_API_KEY'],\n },\n opencode: {\n cli: 'opencode',\n instructionFile: 'AGENTS.md',\n envVars: ['ANTHROPIC_API_KEY'],\n },\n aider: {\n cli: 'aider',\n instructionFile: 'AGENTS.md',\n envVars: ['ANTHROPIC_API_KEY'],\n args: ['--model', 'claude-3-5-sonnet-20241022'],\n },\n },\n },\n secrets: {\n provider: 'env',\n },\n context: {\n files: ['README.md'],\n dirs: ['docs/'],\n generateAgentFiles: true,\n },\n };\n}\n\n/**\n * Merge user config with defaults\n */\nexport function mergeWithDefaults(config: Partial<RapidConfig>): RapidConfig {\n const defaults = getDefaultConfig();\n\n return {\n ...defaults,\n ...config,\n agents: {\n ...defaults.agents,\n ...config.agents,\n available: {\n ...defaults.agents.available,\n ...config.agents?.available,\n },\n },\n secrets: {\n ...defaults.secrets,\n ...config.secrets,\n },\n context: {\n ...defaults.context,\n ...config.context,\n },\n };\n}\n","/**\n * Agent detection and management\n */\n\nimport { execa } from 'execa';\nimport which from 'which';\nimport type { AgentDefinition, AgentStatus, RapidConfig, ExternalAuthConfig } from './types.js';\nimport { getAuthEnvironment } from './external-auth.js';\n\n/**\n * Check if an agent CLI is available\n */\nexport async function checkAgentAvailable(agent: AgentDefinition): Promise<AgentStatus> {\n try {\n const cliPath = await which(agent.cli);\n\n // Try to get version\n let version: string | undefined;\n try {\n const result = await execa(agent.cli, ['--version'], { timeout: 5000 });\n version = result.stdout.trim().split('\\n')[0];\n } catch {\n // Version check failed, but CLI exists\n }\n\n return {\n name: agent.cli,\n available: true,\n cliPath,\n ...(version !== undefined && { version }),\n };\n } catch {\n return {\n name: agent.cli,\n available: false,\n };\n }\n}\n\n/**\n * Check all configured agents\n */\nexport async function checkAllAgents(config: RapidConfig): Promise<AgentStatus[]> {\n const results: AgentStatus[] = [];\n\n for (const [name, agent] of Object.entries(config.agents.available)) {\n const status = await checkAgentAvailable(agent);\n results.push({\n ...status,\n name,\n });\n }\n\n return results;\n}\n\n/**\n * Get the default agent from config\n */\nexport function getDefaultAgent(config: RapidConfig): AgentDefinition | null {\n const defaultName = config.agents.default;\n return config.agents.available[defaultName] || null;\n}\n\n/**\n * Get a specific agent by name\n */\nexport function getAgent(config: RapidConfig, name: string): AgentDefinition | null {\n return config.agents.available[name] || null;\n}\n\n/**\n * Launch an agent CLI\n */\nexport async function launchAgent(\n agent: AgentDefinition,\n options: {\n cwd?: string;\n env?: Record<string, string>;\n stdio?: 'inherit' | 'pipe';\n useExternalAuth?: boolean;\n externalAuthConfig?: ExternalAuthConfig;\n } = {}\n): Promise<void> {\n const args = agent.args ?? [];\n const cwd = options.cwd ?? process.cwd();\n\n // Get external auth environment if enabled\n let authEnv: Record<string, string> = {};\n if (options.useExternalAuth !== false) {\n authEnv = await getAuthEnvironment(options.externalAuthConfig);\n }\n\n await execa(agent.cli, args, {\n cwd,\n env: {\n ...process.env,\n ...authEnv,\n ...options.env, // User-provided env takes precedence\n },\n stdio: options.stdio ?? 'inherit',\n });\n}\n","/**\n * External Authentication Detection\n *\n * Detects and reuses credentials from AI coding tools like:\n * - Claude Code (~/.claude.json)\n * - OpenAI Codex (~/.codex/auth.json)\n * - Gemini CLI (~/.gemini/)\n * - Aider (.env files with API keys)\n */\n\nimport { readFile, access } from 'node:fs/promises';\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\nimport type { DetectedCredential, ExternalAuthConfig, AuthStatus } from './types.js';\nimport { logger } from './logger.js';\n\n/**\n * Default configuration for external auth detection\n */\nconst DEFAULT_CONFIG: ExternalAuthConfig = {\n enabled: true,\n sources: ['claude-code', 'codex', 'gemini-cli', 'aider', 'env'],\n};\n\n/**\n * Check if a file exists\n */\nasync function fileExists(path: string): Promise<boolean> {\n try {\n await access(path);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Safely read and parse JSON file\n */\nasync function readJsonFile<T>(path: string): Promise<T | null> {\n try {\n const content = await readFile(path, 'utf-8');\n return JSON.parse(content) as T;\n } catch {\n return null;\n }\n}\n\n// =============================================================================\n// Claude Code Detection\n// =============================================================================\n\ninterface ClaudeCodeConfig {\n oauthAccount?: {\n accessToken?: string;\n refreshToken?: string;\n expiresAt?: string;\n accountUuid?: string;\n emailAddress?: string;\n organizationName?: string;\n planType?: string;\n };\n claudeAiOauth?: {\n accessToken?: string;\n refreshToken?: string;\n expiresAt?: string;\n };\n lastAccountUuid?: string;\n}\n\n/**\n * Detect Claude Code credentials from ~/.claude.json\n */\nexport async function detectClaudeCodeAuth(): Promise<DetectedCredential | null> {\n const home = homedir();\n const configPath = join(home, '.claude.json');\n\n if (!(await fileExists(configPath))) {\n return null;\n }\n\n const config = await readJsonFile<ClaudeCodeConfig>(configPath);\n if (!config) {\n return null;\n }\n\n // Check for OAuth session (Claude Pro/Max login)\n const oauth = config.oauthAccount || config.claudeAiOauth;\n if (oauth?.accessToken) {\n const expiresAt = oauth.expiresAt ? new Date(oauth.expiresAt) : undefined;\n\n // Check if token is expired\n if (expiresAt && expiresAt < new Date()) {\n logger.debug('Claude Code OAuth token expired');\n return null;\n }\n\n const cred: DetectedCredential = {\n source: 'claude-code',\n provider: 'anthropic',\n authType: 'oauth',\n value: oauth.accessToken,\n configPath,\n };\n\n if (expiresAt) {\n cred.expiresAt = expiresAt;\n }\n\n const accountInfo: {\n email?: string;\n organization?: string;\n plan?: string;\n } = {};\n\n if (config.oauthAccount?.emailAddress) {\n accountInfo.email = config.oauthAccount.emailAddress;\n }\n if (config.oauthAccount?.organizationName) {\n accountInfo.organization = config.oauthAccount.organizationName;\n }\n if (config.oauthAccount?.planType) {\n accountInfo.plan = config.oauthAccount.planType;\n }\n\n if (Object.keys(accountInfo).length > 0) {\n cred.accountInfo = accountInfo;\n }\n\n return cred;\n }\n\n // Check for API key in environment (Claude Code also respects ANTHROPIC_API_KEY)\n const apiKey = process.env.ANTHROPIC_API_KEY;\n if (apiKey) {\n return {\n source: 'claude-code',\n provider: 'anthropic',\n authType: 'api-key',\n envVar: 'ANTHROPIC_API_KEY',\n value: apiKey,\n configPath,\n };\n }\n\n return null;\n}\n\n// =============================================================================\n// OpenAI Codex Detection\n// =============================================================================\n\ninterface CodexAuthConfig {\n chatgpt?: {\n accessToken?: string;\n refreshToken?: string;\n expiresAt?: string;\n email?: string;\n workspaceId?: string;\n };\n api?: {\n apiKey?: string;\n };\n}\n\n/**\n * Detect OpenAI Codex credentials from ~/.codex/auth.json\n */\nexport async function detectCodexAuth(): Promise<DetectedCredential | null> {\n const home = homedir();\n const configPath = join(home, '.codex', 'auth.json');\n\n if (!(await fileExists(configPath))) {\n return null;\n }\n\n const config = await readJsonFile<CodexAuthConfig>(configPath);\n if (!config) {\n return null;\n }\n\n // Check for ChatGPT OAuth session\n if (config.chatgpt?.accessToken) {\n const expiresAt = config.chatgpt.expiresAt ? new Date(config.chatgpt.expiresAt) : undefined;\n\n // Check if token is expired\n if (expiresAt && expiresAt < new Date()) {\n logger.debug('Codex ChatGPT OAuth token expired');\n return null;\n }\n\n const cred: DetectedCredential = {\n source: 'codex',\n provider: 'openai',\n authType: 'oauth',\n value: config.chatgpt.accessToken,\n configPath,\n };\n\n if (expiresAt) {\n cred.expiresAt = expiresAt;\n }\n\n const accountInfo: {\n email?: string;\n organization?: string;\n plan?: string;\n } = {};\n\n if (config.chatgpt.email) {\n accountInfo.email = config.chatgpt.email;\n }\n if (config.chatgpt.workspaceId) {\n accountInfo.organization = config.chatgpt.workspaceId;\n }\n\n if (Object.keys(accountInfo).length > 0) {\n cred.accountInfo = accountInfo;\n }\n\n return cred;\n }\n\n // Check for API key\n if (config.api?.apiKey) {\n return {\n source: 'codex',\n provider: 'openai',\n authType: 'api-key',\n value: config.api.apiKey,\n configPath,\n };\n }\n\n // Check environment variable\n const apiKey = process.env.OPENAI_API_KEY;\n if (apiKey) {\n return {\n source: 'codex',\n provider: 'openai',\n authType: 'api-key',\n envVar: 'OPENAI_API_KEY',\n value: apiKey,\n };\n }\n\n return null;\n}\n\n// =============================================================================\n// Gemini CLI Detection\n// =============================================================================\n\ninterface GeminiSettings {\n auth?: {\n oauth?: {\n accessToken?: string;\n refreshToken?: string;\n expiresAt?: string;\n email?: string;\n };\n };\n googleCloudProject?: string;\n}\n\n/**\n * Detect Gemini CLI credentials from ~/.gemini/\n */\nexport async function detectGeminiAuth(): Promise<DetectedCredential | null> {\n const home = homedir();\n const settingsPath = join(home, '.gemini', 'settings.json');\n\n // Check for settings.json with OAuth\n if (await fileExists(settingsPath)) {\n const settings = await readJsonFile<GeminiSettings>(settingsPath);\n if (settings?.auth?.oauth?.accessToken) {\n const oauth = settings.auth.oauth;\n const expiresAt = oauth.expiresAt ? new Date(oauth.expiresAt) : undefined;\n\n if (expiresAt && expiresAt < new Date()) {\n logger.debug('Gemini CLI OAuth token expired');\n } else {\n const cred: DetectedCredential = {\n source: 'gemini-cli',\n provider: 'google',\n authType: 'oauth',\n value: oauth.accessToken!,\n configPath: settingsPath,\n };\n\n if (expiresAt) {\n cred.expiresAt = expiresAt;\n }\n\n const accountInfo: {\n email?: string;\n organization?: string;\n plan?: string;\n } = {};\n\n if (oauth.email) {\n accountInfo.email = oauth.email;\n }\n if (settings.googleCloudProject) {\n accountInfo.organization = settings.googleCloudProject;\n }\n\n if (Object.keys(accountInfo).length > 0) {\n cred.accountInfo = accountInfo;\n }\n\n return cred;\n }\n }\n }\n\n // Check for GEMINI_API_KEY environment variable\n const geminiKey = process.env.GEMINI_API_KEY;\n if (geminiKey) {\n return {\n source: 'gemini-cli',\n provider: 'google',\n authType: 'api-key',\n envVar: 'GEMINI_API_KEY',\n value: geminiKey,\n };\n }\n\n // Check for GOOGLE_API_KEY environment variable\n const googleKey = process.env.GOOGLE_API_KEY;\n if (googleKey) {\n return {\n source: 'gemini-cli',\n provider: 'google',\n authType: 'api-key',\n envVar: 'GOOGLE_API_KEY',\n value: googleKey,\n };\n }\n\n return null;\n}\n\n// =============================================================================\n// Aider Detection\n// =============================================================================\n\n/**\n * Detect Aider credentials from environment variables\n * Aider uses standard environment variables, no config file\n */\nexport async function detectAiderAuth(): Promise<DetectedCredential[]> {\n const credentials: DetectedCredential[] = [];\n\n // Anthropic API Key (Aider's preferred for Claude models)\n const anthropicKey = process.env.ANTHROPIC_API_KEY;\n if (anthropicKey) {\n credentials.push({\n source: 'aider',\n provider: 'anthropic',\n authType: 'api-key',\n envVar: 'ANTHROPIC_API_KEY',\n value: anthropicKey,\n });\n }\n\n // OpenAI API Key\n const openaiKey = process.env.OPENAI_API_KEY;\n if (openaiKey) {\n credentials.push({\n source: 'aider',\n provider: 'openai',\n authType: 'api-key',\n envVar: 'OPENAI_API_KEY',\n value: openaiKey,\n });\n }\n\n // Gemini API Key (Aider also supports Gemini)\n const geminiKey = process.env.GEMINI_API_KEY;\n if (geminiKey) {\n credentials.push({\n source: 'aider',\n provider: 'google',\n authType: 'api-key',\n envVar: 'GEMINI_API_KEY',\n value: geminiKey,\n });\n }\n\n return credentials;\n}\n\n// =============================================================================\n// Environment Variable Detection\n// =============================================================================\n\n/**\n * Detect credentials from standard environment variables\n */\nexport async function detectEnvAuth(): Promise<DetectedCredential[]> {\n const credentials: DetectedCredential[] = [];\n\n const envMappings: Array<{\n envVar: string;\n provider: 'anthropic' | 'openai' | 'google';\n }> = [\n { envVar: 'ANTHROPIC_API_KEY', provider: 'anthropic' },\n { envVar: 'OPENAI_API_KEY', provider: 'openai' },\n { envVar: 'GEMINI_API_KEY', provider: 'google' },\n { envVar: 'GOOGLE_API_KEY', provider: 'google' },\n ];\n\n for (const { envVar, provider } of envMappings) {\n const value = process.env[envVar];\n if (value) {\n credentials.push({\n source: 'env',\n provider,\n authType: 'api-key',\n envVar,\n value,\n });\n }\n }\n\n return credentials;\n}\n\n// =============================================================================\n// Main Detection Functions\n// =============================================================================\n\n/**\n * Detect all available credentials from external sources\n */\nexport async function detectAllCredentials(\n config: ExternalAuthConfig = DEFAULT_CONFIG\n): Promise<DetectedCredential[]> {\n if (!config.enabled) {\n return [];\n }\n\n const sources = config.sources || DEFAULT_CONFIG.sources!;\n const credentials: DetectedCredential[] = [];\n const seenValues = new Set<string>();\n\n for (const source of sources) {\n try {\n let detected: DetectedCredential | DetectedCredential[] | null = null;\n\n switch (source) {\n case 'claude-code':\n detected = await detectClaudeCodeAuth();\n break;\n case 'codex':\n detected = await detectCodexAuth();\n break;\n case 'gemini-cli':\n detected = await detectGeminiAuth();\n break;\n case 'aider':\n detected = await detectAiderAuth();\n break;\n case 'env':\n detected = await detectEnvAuth();\n break;\n }\n\n if (detected) {\n const items = Array.isArray(detected) ? detected : [detected];\n for (const item of items) {\n // Deduplicate by value to avoid listing the same API key multiple times\n const key = item.value || item.envVar || '';\n if (key && !seenValues.has(key)) {\n seenValues.add(key);\n credentials.push(item);\n }\n }\n }\n } catch (error) {\n logger.debug(`Error detecting ${source} credentials:`, error);\n }\n }\n\n return credentials;\n}\n\n/**\n * Get authentication status summary\n */\nexport async function getAuthStatus(\n config: ExternalAuthConfig = DEFAULT_CONFIG\n): Promise<AuthStatus> {\n const credentials = await detectAllCredentials(config);\n const warnings: string[] = [];\n\n // Check for expired tokens\n for (const cred of credentials) {\n if (cred.expiresAt && cred.expiresAt < new Date()) {\n warnings.push(`${cred.source} OAuth token has expired. Please re-authenticate.`);\n }\n }\n\n // Find preferred source\n let preferredSource: DetectedCredential | undefined;\n if (config.preferSource) {\n preferredSource = credentials.find((c) => c.source === config.preferSource);\n }\n\n // If no preferred source specified, prioritize OAuth over API keys\n if (!preferredSource && credentials.length > 0) {\n preferredSource = credentials.find((c) => c.authType === 'oauth') || credentials[0];\n }\n\n const result: AuthStatus = {\n authenticated: credentials.length > 0,\n sources: credentials,\n };\n\n if (preferredSource) {\n result.preferredSource = preferredSource;\n }\n\n if (warnings.length > 0) {\n result.warnings = warnings;\n }\n\n return result;\n}\n\n/**\n * Get credentials for a specific provider\n */\nexport async function getCredentialsForProvider(\n provider: 'anthropic' | 'openai' | 'google',\n config: ExternalAuthConfig = DEFAULT_CONFIG\n): Promise<DetectedCredential | null> {\n const credentials = await detectAllCredentials(config);\n const providerCreds = credentials.filter((c) => c.provider === provider);\n\n if (providerCreds.length === 0) {\n return null;\n }\n\n // Prefer OAuth over API keys\n const found = providerCreds.find((c) => c.authType === 'oauth');\n return found || providerCreds[0] || null;\n}\n\n/**\n * Get environment variables to inject based on detected credentials\n */\nexport async function getAuthEnvironment(\n config: ExternalAuthConfig = DEFAULT_CONFIG\n): Promise<Record<string, string>> {\n const credentials = await detectAllCredentials(config);\n const env: Record<string, string> = {};\n\n // Group by provider and prefer OAuth tokens\n const byProvider = new Map<string, DetectedCredential>();\n\n for (const cred of credentials) {\n const existing = byProvider.get(cred.provider);\n // Prefer OAuth over API keys\n if (!existing || (cred.authType === 'oauth' && existing.authType !== 'oauth')) {\n byProvider.set(cred.provider, cred);\n }\n }\n\n // Map to environment variables\n for (const [provider, cred] of byProvider) {\n if (!cred.value) continue;\n\n switch (provider) {\n case 'anthropic':\n // For OAuth tokens, we use ANTHROPIC_AUTH_TOKEN\n // For API keys, we use ANTHROPIC_API_KEY\n if (cred.authType === 'oauth') {\n env['ANTHROPIC_AUTH_TOKEN'] = cred.value;\n } else {\n env['ANTHROPIC_API_KEY'] = cred.value;\n }\n break;\n\n case 'openai':\n if (cred.authType === 'oauth') {\n // OpenAI Codex uses a different auth header for OAuth\n env['OPENAI_AUTH_TOKEN'] = cred.value;\n } else {\n env['OPENAI_API_KEY'] = cred.value;\n }\n break;\n\n case 'google':\n if (cred.authType === 'oauth') {\n env['GOOGLE_AUTH_TOKEN'] = cred.value;\n } else {\n // Prefer GEMINI_API_KEY, fallback to GOOGLE_API_KEY\n if (cred.envVar === 'GOOGLE_API_KEY') {\n env['GOOGLE_API_KEY'] = cred.value;\n } else {\n env['GEMINI_API_KEY'] = cred.value;\n }\n }\n break;\n }\n }\n\n return env;\n}\n\n/**\n * Format auth status for display\n */\nexport function formatAuthStatus(status: AuthStatus): string {\n const lines: string[] = [];\n\n if (!status.authenticated) {\n lines.push('No authentication detected');\n lines.push('');\n lines.push('To authenticate, either:');\n lines.push(' - Log in with Claude Code: claude');\n lines.push(' - Log in with Codex: codex');\n lines.push(' - Log in with Gemini CLI: gemini');\n lines.push(' - Set environment variables (ANTHROPIC_API_KEY, OPENAI_API_KEY, etc.)');\n return lines.join('\\n');\n }\n\n lines.push('Detected authentication sources:');\n lines.push('');\n\n for (const cred of status.sources) {\n const isPrimary = cred === status.preferredSource;\n const prefix = isPrimary ? '* ' : ' ';\n const authType = cred.authType === 'oauth' ? 'OAuth' : 'API Key';\n\n let line = `${prefix}${cred.source} (${cred.provider}, ${authType})`;\n\n if (cred.accountInfo?.email) {\n line += ` - ${cred.accountInfo.email}`;\n }\n if (cred.accountInfo?.plan) {\n line += ` [${cred.accountInfo.plan}]`;\n }\n if (cred.expiresAt) {\n const expiresIn = Math.round((cred.expiresAt.getTime() - Date.now()) / 1000 / 60);\n if (expiresIn > 0) {\n line += ` (expires in ${expiresIn}m)`;\n } else {\n line += ' (EXPIRED)';\n }\n }\n\n lines.push(line);\n }\n\n if (status.warnings && status.warnings.length > 0) {\n lines.push('');\n lines.push('Warnings:');\n for (const warning of status.warnings) {\n lines.push(` ! ${warning}`);\n }\n }\n\n return lines.join('\\n');\n}\n","/**\n * Logging utilities\n */\n\nimport chalk from 'chalk';\n\nexport type LogLevel = 'debug' | 'info' | 'warn' | 'error';\n\nconst LOG_LEVELS: Record<LogLevel, number> = {\n debug: 0,\n info: 1,\n warn: 2,\n error: 3,\n};\n\nlet currentLevel: LogLevel = 'info';\n\nexport function setLogLevel(level: LogLevel): void {\n currentLevel = level;\n}\n\nexport function getLogLevel(): LogLevel {\n return currentLevel;\n}\n\nfunction shouldLog(level: LogLevel): boolean {\n return LOG_LEVELS[level] >= LOG_LEVELS[currentLevel];\n}\n\nexport const logger = {\n debug(message: string, ...args: unknown[]): void {\n if (shouldLog('debug')) {\n console.log(chalk.gray(`[debug] ${message}`), ...args);\n }\n },\n\n info(message: string, ...args: unknown[]): void {\n if (shouldLog('info')) {\n console.log(chalk.blue('ℹ'), message, ...args);\n }\n },\n\n success(message: string, ...args: unknown[]): void {\n if (shouldLog('info')) {\n console.log(chalk.green('✓'), message, ...args);\n }\n },\n\n warn(message: string, ...args: unknown[]): void {\n if (shouldLog('warn')) {\n console.log(chalk.yellow('⚠'), message, ...args);\n }\n },\n\n error(message: string, ...args: unknown[]): void {\n if (shouldLog('error')) {\n console.error(chalk.red('✗'), message, ...args);\n }\n },\n\n // Styled output helpers\n brand(text: string): string {\n return chalk.hex('#818cf8')(text);\n },\n\n dim(text: string): string {\n return chalk.dim(text);\n },\n\n bold(text: string): string {\n return chalk.bold(text);\n },\n\n // Print a header\n header(text: string): void {\n console.log();\n console.log(chalk.bold(text));\n console.log(chalk.dim('─'.repeat(text.length)));\n },\n\n // Print a blank line\n blank(): void {\n console.log();\n },\n};\n","/**\n * Container management utilities\n * Uses devcontainer CLI for container lifecycle\n */\n\nimport { execa, type ExecaError } from 'execa';\nimport which from 'which';\nimport { readFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport type { RapidConfig } from './types.js';\n\nexport interface ContainerStatus {\n exists: boolean;\n running: boolean;\n containerId?: string;\n containerName?: string;\n}\n\nexport interface DevcontainerConfig {\n name?: string;\n image?: string;\n dockerFile?: string;\n build?: {\n dockerfile?: string;\n context?: string;\n };\n [key: string]: unknown;\n}\n\n/**\n * Check if devcontainer CLI is available\n */\nexport async function hasDevcontainerCli(): Promise<boolean> {\n try {\n await which('devcontainer');\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Check if Docker is available\n */\nexport async function hasDocker(): Promise<boolean> {\n try {\n await execa('docker', ['info'], { timeout: 5000 });\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Get the devcontainer.json path\n */\nexport function getDevcontainerPath(rootDir: string, config?: RapidConfig): string {\n const customPath = config?.container?.devcontainer;\n if (customPath) {\n return join(rootDir, customPath);\n }\n return join(rootDir, '.devcontainer', 'devcontainer.json');\n}\n\n/**\n * Load devcontainer.json\n */\nexport async function loadDevcontainerConfig(\n rootDir: string,\n config?: RapidConfig\n): Promise<DevcontainerConfig | null> {\n try {\n const configPath = getDevcontainerPath(rootDir, config);\n const content = await readFile(configPath, 'utf-8');\n return JSON.parse(content);\n } catch {\n return null;\n }\n}\n\n/**\n * Get container name for a project\n */\nexport function getContainerName(rootDir: string, devcontainerConfig?: DevcontainerConfig): string {\n // Use devcontainer name if available, otherwise derive from directory\n const dirName = rootDir.split('/').pop() || 'rapid';\n const name = devcontainerConfig?.name || dirName;\n // Sanitize for Docker container name\n return `rapid-${name}`.toLowerCase().replace(/[^a-z0-9-]/g, '-');\n}\n\n/**\n * Check container status using devcontainer labels\n */\nexport async function getContainerStatus(\n rootDir: string,\n _config?: RapidConfig\n): Promise<ContainerStatus> {\n try {\n // Use devcontainer label to find the container (this is how devcontainer CLI tracks containers)\n const result = await execa('docker', [\n 'ps',\n '-a',\n '--filter',\n `label=devcontainer.local_folder=${rootDir}`,\n '--format',\n '{{.ID}}\\t{{.State}}\\t{{.Names}}',\n ]);\n\n const lines = result.stdout.trim().split('\\n').filter(Boolean);\n if (lines.length === 0) {\n return { exists: false, running: false };\n }\n\n const parts = lines[0]?.split('\\t');\n const containerId = parts?.[0];\n const state = parts?.[1];\n const containerName = parts?.[2];\n\n if (!containerId || !containerName) {\n return { exists: false, running: false };\n }\n\n return {\n exists: true,\n running: state === 'running',\n containerId,\n containerName,\n };\n } catch {\n return { exists: false, running: false };\n }\n}\n\n/**\n * Start the dev container using devcontainer CLI\n */\nexport async function startContainer(\n rootDir: string,\n _config?: RapidConfig,\n options: { rebuild?: boolean; quiet?: boolean } = {}\n): Promise<{ success: boolean; containerId?: string; error?: string }> {\n const hasDevCli = await hasDevcontainerCli();\n\n if (!hasDevCli) {\n return {\n success: false,\n error: 'devcontainer CLI not found. Install with: npm install -g @devcontainers/cli',\n };\n }\n\n const hasDockerRunning = await hasDocker();\n if (!hasDockerRunning) {\n return {\n success: false,\n error: 'Docker is not running. Please start Docker Desktop.',\n };\n }\n\n try {\n const args = ['up', '--workspace-folder', rootDir];\n\n if (options.rebuild) {\n args.push('--remove-existing-container');\n }\n\n const result = await execa('devcontainer', args, {\n stdio: options.quiet ? 'pipe' : 'inherit',\n cwd: rootDir,\n });\n\n // Parse the container ID from output\n // devcontainer up outputs JSON with containerId\n if (options.quiet && result.stdout) {\n try {\n const output = JSON.parse(result.stdout);\n return { success: true, containerId: output.containerId };\n } catch {\n return { success: true };\n }\n }\n\n return { success: true };\n } catch (error) {\n const execError = error as ExecaError;\n const stderr = typeof execError.stderr === 'string' ? execError.stderr : undefined;\n return {\n success: false,\n error: stderr || execError.message,\n };\n }\n}\n\n/**\n * Stop the dev container\n */\nexport async function stopContainer(\n rootDir: string,\n config?: RapidConfig,\n options: { remove?: boolean } = {}\n): Promise<{ success: boolean; error?: string }> {\n const status = await getContainerStatus(rootDir, config);\n\n if (!status.exists) {\n return { success: true }; // Nothing to stop\n }\n\n try {\n if (status.running) {\n await execa('docker', ['stop', status.containerId!]);\n }\n\n if (options.remove) {\n await execa('docker', ['rm', status.containerId!]);\n }\n\n return { success: true };\n } catch (error) {\n const execError = error as ExecaError;\n const stderr = typeof execError.stderr === 'string' ? execError.stderr : undefined;\n return {\n success: false,\n error: stderr || execError.message,\n };\n }\n}\n\n/**\n * Execute a command inside the dev container\n */\nexport async function execInContainer(\n rootDir: string,\n command: string[],\n _config?: RapidConfig,\n options: { interactive?: boolean; tty?: boolean; env?: Record<string, string> } = {}\n): Promise<void> {\n const hasDevCli = await hasDevcontainerCli();\n\n if (!hasDevCli) {\n throw new Error('devcontainer CLI not found. Install with: npm install -g @devcontainers/cli');\n }\n\n const args = ['exec', '--workspace-folder', rootDir];\n\n // Add environment variables\n if (options.env) {\n for (const [key, value] of Object.entries(options.env)) {\n args.push('--remote-env', `${key}=${value}`);\n }\n }\n\n // Add the command\n args.push(...command);\n\n await execa('devcontainer', args, {\n stdio: 'inherit',\n cwd: rootDir,\n });\n}\n","/**\n * Secrets management for RAPID\n * Supports 1Password, HashiCorp Vault, and environment variables\n */\n\nimport { spawn } from 'node:child_process';\nimport { readFile, writeFile, access } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport type { SecretsConfig } from './types.js';\nimport { logger } from './logger.js';\n\nexport interface SecretStatus {\n name: string;\n reference: string;\n provider: 'env' | '1password' | 'vault';\n available: boolean;\n error?: string;\n}\n\nexport interface SecretsStatus {\n provider: 'env' | '1password' | 'vault';\n authenticated: boolean;\n authMethod?: 'service-account' | 'user' | 'token';\n secrets: SecretStatus[];\n allAvailable: boolean;\n}\n\nexport interface OpAuthStatus {\n authenticated: boolean;\n method: 'service-account' | 'user' | 'none';\n accountInfo?: string;\n}\n\n/**\n * Execute a command and return stdout\n */\nasync function execCommand(\n command: string,\n args: string[],\n options: { timeout?: number } = {}\n): Promise<{ stdout: string; stderr: string; exitCode: number }> {\n return new Promise((resolve) => {\n const proc = spawn(command, args, {\n stdio: ['pipe', 'pipe', 'pipe'],\n timeout: options.timeout ?? 30000,\n });\n\n let stdout = '';\n let stderr = '';\n\n proc.stdout?.on('data', (data) => {\n stdout += data.toString();\n });\n\n proc.stderr?.on('data', (data) => {\n stderr += data.toString();\n });\n\n proc.on('close', (code) => {\n resolve({ stdout: stdout.trim(), stderr: stderr.trim(), exitCode: code ?? 1 });\n });\n\n proc.on('error', (err) => {\n resolve({ stdout: '', stderr: err.message, exitCode: 1 });\n });\n });\n}\n\n/**\n * Check if 1Password CLI is installed\n */\nexport async function hasOpCli(): Promise<boolean> {\n const result = await execCommand('op', ['--version']);\n return result.exitCode === 0;\n}\n\n/**\n * Check if OP_SERVICE_ACCOUNT_TOKEN is set\n */\nexport function hasOpServiceAccountToken(): boolean {\n return !!process.env.OP_SERVICE_ACCOUNT_TOKEN;\n}\n\n/**\n * Check if 1Password CLI is authenticated (via service account or user)\n */\nexport async function isOpAuthenticated(): Promise<boolean> {\n // Service account token takes precedence\n if (hasOpServiceAccountToken()) {\n // Verify the token works by trying to list vaults\n const result = await execCommand('op', ['vault', 'list', '--format=json']);\n return result.exitCode === 0;\n }\n\n // Fall back to user authentication\n const result = await execCommand('op', ['account', 'list']);\n return result.exitCode === 0 && result.stdout.length > 0;\n}\n\n/**\n * Get detailed 1Password authentication status\n */\nexport async function getOpAuthStatus(): Promise<OpAuthStatus> {\n // Check for service account token first\n if (hasOpServiceAccountToken()) {\n const result = await execCommand('op', ['vault', 'list', '--format=json']);\n if (result.exitCode === 0) {\n return {\n authenticated: true,\n method: 'service-account',\n accountInfo: 'Service Account',\n };\n }\n return {\n authenticated: false,\n method: 'none',\n accountInfo: 'Invalid service account token',\n };\n }\n\n // Check for user authentication\n const result = await execCommand('op', ['account', 'list', '--format=json']);\n if (result.exitCode === 0 && result.stdout.length > 0) {\n try {\n const accounts = JSON.parse(result.stdout);\n if (accounts.length > 0) {\n return {\n authenticated: true,\n method: 'user',\n accountInfo: accounts[0].email || accounts[0].url,\n };\n }\n } catch {\n // Parse error, but command succeeded\n return {\n authenticated: true,\n method: 'user',\n };\n }\n }\n\n return {\n authenticated: false,\n method: 'none',\n };\n}\n\n/**\n * Check if HashiCorp Vault CLI is installed\n */\nexport async function hasVaultCli(): Promise<boolean> {\n const result = await execCommand('vault', ['--version']);\n return result.exitCode === 0;\n}\n\n/**\n * Check if HashiCorp Vault is authenticated\n */\nexport async function isVaultAuthenticated(): Promise<boolean> {\n const result = await execCommand('vault', ['token', 'lookup']);\n return result.exitCode === 0;\n}\n\n/**\n * Read a secret from 1Password\n * @param reference - 1Password reference (e.g., \"op://vault/item/field\")\n */\nexport async function readOpSecret(reference: string): Promise<string | null> {\n const result = await execCommand('op', ['read', reference]);\n if (result.exitCode !== 0) {\n return null;\n }\n return result.stdout;\n}\n\n/**\n * Read a secret from HashiCorp Vault\n * @param path - Vault path (e.g., \"secret/data/myproject\")\n * @param field - Field name within the secret\n */\nexport async function readVaultSecret(path: string, field: string): Promise<string | null> {\n const result = await execCommand('vault', ['kv', 'get', '-field', field, path]);\n if (result.exitCode !== 0) {\n return null;\n }\n return result.stdout;\n}\n\n/**\n * Verify a single secret is accessible\n */\nexport async function verifySecret(\n name: string,\n reference: string,\n provider: 'env' | '1password' | 'vault',\n config?: SecretsConfig\n): Promise<SecretStatus> {\n const status: SecretStatus = {\n name,\n reference,\n provider,\n available: false,\n };\n\n try {\n switch (provider) {\n case 'env': {\n const value = process.env[name];\n status.available = !!value && value.length > 0;\n if (!status.available) {\n status.error = 'Environment variable not set';\n }\n break;\n }\n\n case '1password': {\n // Reference should be in format op://vault/item/field\n const value = await readOpSecret(reference);\n status.available = value !== null;\n if (!status.available) {\n status.error = 'Secret not found in 1Password';\n }\n break;\n }\n\n case 'vault': {\n // Parse path and field from reference\n const field = reference.split('/').pop() || 'value';\n const vaultPath = reference.includes('/')\n ? reference.substring(0, reference.lastIndexOf('/'))\n : config?.vault || 'secret/data/default';\n\n const value = await readVaultSecret(vaultPath, field);\n status.available = value !== null;\n if (!status.available) {\n status.error = 'Secret not found in Vault';\n }\n break;\n }\n }\n } catch (error) {\n status.error = error instanceof Error ? error.message : String(error);\n status.available = false;\n }\n\n return status;\n}\n\n/**\n * Verify all secrets in configuration\n */\nexport async function verifySecrets(config: SecretsConfig): Promise<SecretsStatus> {\n const provider = config.provider || 'env';\n let authenticated = true;\n\n // Check authentication status for provider\n switch (provider) {\n case '1password':\n authenticated = await isOpAuthenticated();\n break;\n case 'vault':\n authenticated = await isVaultAuthenticated();\n break;\n case 'env':\n authenticated = true;\n break;\n }\n\n const secrets: SecretStatus[] = [];\n\n if (config.items) {\n for (const [name, reference] of Object.entries(config.items)) {\n const status = await verifySecret(name, reference, provider, config);\n secrets.push(status);\n }\n }\n\n const allAvailable = secrets.length === 0 || secrets.every((s) => s.available);\n\n return {\n provider,\n authenticated,\n secrets,\n allAvailable,\n };\n}\n\n/**\n * Load all secrets into environment\n */\nexport async function loadSecrets(config: SecretsConfig): Promise<Record<string, string>> {\n const provider = config.provider || 'env';\n const secrets: Record<string, string> = {};\n\n if (!config.items) {\n return secrets;\n }\n\n for (const [name, reference] of Object.entries(config.items)) {\n try {\n let value: string | null = null;\n\n switch (provider) {\n case 'env':\n value = process.env[name] || null;\n break;\n\n case '1password':\n value = await readOpSecret(reference);\n break;\n\n case 'vault': {\n const field = reference.split('/').pop() || 'value';\n const path = reference.substring(0, reference.lastIndexOf('/')) || config.vault || '';\n value = await readVaultSecret(path, field);\n break;\n }\n }\n\n if (value) {\n secrets[name] = value;\n }\n } catch (error) {\n logger.debug(`Failed to load secret ${name}: ${error}`);\n }\n }\n\n return secrets;\n}\n\n/**\n * Generate .envrc file from secrets configuration\n */\nexport function generateEnvrc(config: SecretsConfig): string {\n const provider = config.provider || 'env';\n const lines: string[] = [\n '# .envrc - RAPID project secrets',\n '# This file is safe to commit - it contains NO secrets, only references',\n '#',\n `# Provider: ${provider}`,\n `# Generated by: rapid secrets generate`,\n '',\n ];\n\n if (!config.items || Object.keys(config.items).length === 0) {\n lines.push('# No secrets configured in rapid.json');\n return lines.join('\\n');\n }\n\n switch (provider) {\n case '1password':\n lines.push('# Secrets loaded from 1Password');\n lines.push('# Requires: 1Password CLI (op) installed and authenticated');\n lines.push('');\n for (const [name, reference] of Object.entries(config.items)) {\n lines.push(`export ${name}=$(op read \"${reference}\")`);\n }\n break;\n\n case 'vault':\n lines.push('# Secrets loaded from HashiCorp Vault');\n lines.push('# Requires: Vault CLI installed and authenticated');\n lines.push('');\n if (config.address) {\n lines.push(`export VAULT_ADDR=\"${config.address}\"`);\n lines.push('');\n }\n for (const [name, reference] of Object.entries(config.items)) {\n const path = config.vault || 'secret/data/default';\n lines.push(`export ${name}=$(vault kv get -field=${reference} ${path})`);\n }\n break;\n\n case 'env':\n lines.push('# WARNING: env provider expects secrets to be set manually');\n lines.push('# Consider using 1password or vault for better security');\n lines.push('');\n lines.push('# Uncomment and set values (DO NOT commit actual values!)');\n for (const name of Object.keys(config.items)) {\n lines.push(`# export ${name}=\"your-value-here\"`);\n }\n break;\n }\n\n // Add .env.local loading if configured\n if (config.envrc?.includeLocal !== false) {\n lines.push('');\n lines.push('# Load local overrides if present');\n lines.push('[[ -f .env.local ]] && source_env .env.local');\n }\n\n lines.push('');\n return lines.join('\\n');\n}\n\n/**\n * Write .envrc file to project directory\n */\nexport async function writeEnvrc(rootDir: string, config: SecretsConfig): Promise<string> {\n const envrcPath = config.envrc?.path || '.envrc';\n const fullPath = join(rootDir, envrcPath);\n const content = generateEnvrc(config);\n\n await writeFile(fullPath, content);\n return fullPath;\n}\n\n/**\n * Check if .envrc exists in project\n */\nexport async function hasEnvrc(rootDir: string, config?: SecretsConfig): Promise<boolean> {\n const envrcPath = config?.envrc?.path || '.envrc';\n const fullPath = join(rootDir, envrcPath);\n\n try {\n await access(fullPath);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Read existing .envrc content\n */\nexport async function readEnvrc(rootDir: string, config?: SecretsConfig): Promise<string | null> {\n const envrcPath = config?.envrc?.path || '.envrc';\n const fullPath = join(rootDir, envrcPath);\n\n try {\n const content = await readFile(fullPath, 'utf-8');\n return content;\n } catch {\n return null;\n }\n}\n\n/**\n * Get a summary of provider requirements\n */\nexport function getProviderInfo(provider: 'env' | '1password' | 'vault'): {\n name: string;\n cliRequired: string | null;\n authCommand: string | null;\n installUrl: string | null;\n} {\n switch (provider) {\n case '1password':\n return {\n name: '1Password',\n cliRequired: 'op',\n authCommand: 'eval $(op signin)',\n installUrl: 'https://developer.1password.com/docs/cli/get-started/',\n };\n case 'vault':\n return {\n name: 'HashiCorp Vault',\n cliRequired: 'vault',\n authCommand: 'vault login',\n installUrl: 'https://developer.hashicorp.com/vault/docs/install',\n };\n case 'env':\n return {\n name: 'Environment Variables',\n cliRequired: null,\n authCommand: null,\n installUrl: null,\n };\n }\n}\n"],"mappings":"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","names":["readFile","readFile","execa","which","readFile","join","readFile","access","join","resolve","result","join","access","readFile"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@a3t/rapid-core",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "Core library for RAPID - AI-assisted development with dev containers",
5
5
  "license": "MIT",
6
6
  "author": "Steve Rude <steve@rude.la>",
@@ -44,7 +44,7 @@
44
44
  "vitest": "^3.0.5"
45
45
  },
46
46
  "peerDependencies": {
47
- "@a3t/rapid-schema": "0.1.0"
47
+ "@a3t/rapid-schema": "0.1.2"
48
48
  },
49
49
  "scripts": {
50
50
  "build": "tsup",