@sashabogi/foundation 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +341 -0
  3. package/dist/cli.d.ts +12 -0
  4. package/dist/cli.d.ts.map +1 -0
  5. package/dist/cli.js +308 -0
  6. package/dist/cli.js.map +1 -0
  7. package/dist/index.d.ts +32 -0
  8. package/dist/index.d.ts.map +1 -0
  9. package/dist/index.js +78 -0
  10. package/dist/index.js.map +1 -0
  11. package/dist/services/config.service.d.ts +92 -0
  12. package/dist/services/config.service.d.ts.map +1 -0
  13. package/dist/services/config.service.js +284 -0
  14. package/dist/services/config.service.js.map +1 -0
  15. package/dist/services/git.service.d.ts +175 -0
  16. package/dist/services/git.service.d.ts.map +1 -0
  17. package/dist/services/git.service.js +395 -0
  18. package/dist/services/git.service.js.map +1 -0
  19. package/dist/services/provider.service.d.ts +74 -0
  20. package/dist/services/provider.service.d.ts.map +1 -0
  21. package/dist/services/provider.service.js +182 -0
  22. package/dist/services/provider.service.js.map +1 -0
  23. package/dist/services/storage.service.d.ts +84 -0
  24. package/dist/services/storage.service.d.ts.map +1 -0
  25. package/dist/services/storage.service.js +320 -0
  26. package/dist/services/storage.service.js.map +1 -0
  27. package/dist/tools/demerzel/index.d.ts +21 -0
  28. package/dist/tools/demerzel/index.d.ts.map +1 -0
  29. package/dist/tools/demerzel/index.js +166 -0
  30. package/dist/tools/demerzel/index.js.map +1 -0
  31. package/dist/tools/gaia/index.d.ts +27 -0
  32. package/dist/tools/gaia/index.d.ts.map +1 -0
  33. package/dist/tools/gaia/index.js +466 -0
  34. package/dist/tools/gaia/index.js.map +1 -0
  35. package/dist/tools/seldon/index.d.ts +43 -0
  36. package/dist/tools/seldon/index.d.ts.map +1 -0
  37. package/dist/tools/seldon/index.js +886 -0
  38. package/dist/tools/seldon/index.js.map +1 -0
  39. package/dist/types/index.d.ts +392 -0
  40. package/dist/types/index.d.ts.map +1 -0
  41. package/dist/types/index.js +10 -0
  42. package/dist/types/index.js.map +1 -0
  43. package/package.json +85 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Sasha Bogojevic
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,341 @@
1
+ # 🏛️ Foundation
2
+
3
+ **The unified MCP server for AI-assisted development.**
4
+
5
+ Three pillars from Asimov's Foundation universe, working together:
6
+
7
+ | Module | Character | Purpose | Tools |
8
+ |--------|-----------|---------|-------|
9
+ | **Demerzel** | R. Daneel Olivaw | Codebase intelligence - 20,000 years of perfect memory | 9 |
10
+ | **Seldon** | Hari Seldon | Multi-agent orchestration - the Plan guides the future | 19 |
11
+ | **Gaia** | The Collective | Workflow patterns - "We are all one, and one is all" | 13 |
12
+
13
+ **One install. One config. 41 tools.**
14
+
15
+ ---
16
+
17
+ ## Quick Start
18
+
19
+ ```bash
20
+ # Install
21
+ npm install -g @sashabogi/foundation
22
+
23
+ # Setup wizard (configure providers)
24
+ foundation init
25
+
26
+ # Add to Claude Code
27
+ foundation mcp install
28
+ ```
29
+
30
+ Restart Claude Code. Foundation is now available.
31
+
32
+ ---
33
+
34
+ ## Modules
35
+
36
+ ### 🤖 Demerzel: Codebase Intelligence
37
+
38
+ *"I have been watching for 20,000 years."*
39
+
40
+ Named after R. Daneel Olivaw/Demerzel - the robot who guided humanity across millennia with perfect memory and silent observation.
41
+
42
+ ```bash
43
+ # Create a snapshot of your codebase
44
+ demerzel_snapshot path="." enhanced=true
45
+
46
+ # Search (zero AI cost)
47
+ demerzel_search path=".foundation/snapshot.txt" pattern="TODO"
48
+
49
+ # Find where a symbol is defined (zero AI cost)
50
+ demerzel_find_symbol path=".foundation/snapshot.txt" symbol="AuthProvider"
51
+
52
+ # Deep AI analysis (~500 tokens)
53
+ demerzel_analyze path=".foundation/snapshot.txt" query="How does authentication work?"
54
+ ```
55
+
56
+ **Tools**: `demerzel_snapshot`, `demerzel_search`, `demerzel_find_files`, `demerzel_find_symbol`, `demerzel_find_importers`, `demerzel_get_deps`, `demerzel_get_context`, `demerzel_analyze`, `demerzel_semantic_search`
57
+
58
+ ---
59
+
60
+ ### 📊 Seldon: Multi-Agent Orchestration
61
+
62
+ *"The future is not set, but it can be guided."*
63
+
64
+ Named after Hari Seldon - the mathematician who created psychohistory to predict and guide humanity's future through the Seldon Plan.
65
+
66
+ #### Agent Invocation
67
+ ```bash
68
+ # Invoke a specific agent role
69
+ seldon_invoke role="critic" task="Review this architectural decision..."
70
+
71
+ # Compare multiple agents on the same task
72
+ seldon_compare roles=["critic", "reviewer"] task="Evaluate this approach..."
73
+
74
+ # Get code review
75
+ seldon_review code="function auth() { ... }" focus=["security", "performance"]
76
+ ```
77
+
78
+ #### Planning
79
+ ```bash
80
+ # Generate a detailed implementation plan
81
+ seldon_plan intent="Add OAuth2 authentication" context="Express backend"
82
+
83
+ # Break work into phases
84
+ seldon_phase_create intent="Build user dashboard with real-time updates"
85
+
86
+ # View phase status
87
+ seldon_phase_list
88
+ ```
89
+
90
+ #### Verification Loop (The Key Innovation)
91
+ ```
92
+ Plan → Execute → Verify → Fix → Re-verify → ✓ Next Phase
93
+ ↑_____________|
94
+ (automatic, with severity thresholds)
95
+ ```
96
+
97
+ ```bash
98
+ # Verify implementation against a plan
99
+ seldon_verify planId="plan_abc123" runTests=true
100
+
101
+ # Generate fixes for issues
102
+ seldon_fix verificationId="ver_xyz789" severityThreshold="major" autoApply=true
103
+
104
+ # YOLO Mode: Execute with automatic verify/fix loop
105
+ seldon_execute_verified \
106
+ phaseId="phase_abc123" \
107
+ maxAttempts=3 \
108
+ severityThreshold="major" \
109
+ autoFix=true
110
+
111
+ # Execute multiple phases in parallel (each in its own worktree)
112
+ seldon_execute_parallel \
113
+ phaseIds=["phase_1", "phase_2", "phase_3"] \
114
+ worktreePerPhase=true \
115
+ mergeStrategy="sequential"
116
+ ```
117
+
118
+ #### Pipelines
119
+ ```bash
120
+ # Create and execute pipelines
121
+ seldon_pipeline_create name="feature-dev" steps=[...]
122
+ seldon_pipeline_execute pipelineId="pipe_abc123"
123
+ ```
124
+
125
+ **Agent Roles**: `orchestrator`, `coder`, `critic`, `reviewer`, `designer`, `researcher`, `verifier`
126
+
127
+ **Providers**: Anthropic, OpenAI, Google Gemini, DeepSeek, Groq, Together, Fireworks, OpenRouter, Z.AI, Kimi, Ollama, Perplexity
128
+
129
+ **Tools**:
130
+ - *Invocation*: `seldon_invoke`, `seldon_compare`, `seldon_critique`, `seldon_review`, `seldon_design`
131
+ - *Planning*: `seldon_plan`, `seldon_phase_create`, `seldon_phase_list`
132
+ - *Verification*: `seldon_verify`, `seldon_fix`, `seldon_execute_verified`, `seldon_execute_parallel`
133
+ - *Pipelines*: `seldon_pipeline_create`, `seldon_pipeline_execute`, `seldon_pipeline_status`
134
+ - *Tasks*: `seldon_task_execute`, `seldon_task_claim`
135
+ - *Providers*: `seldon_providers_list`, `seldon_providers_test`
136
+
137
+ ---
138
+
139
+ ### 🌍 Gaia: Workflow Patterns
140
+
141
+ *"We are all one, and one is all."*
142
+
143
+ Named after Gaia - the planet-wide collective consciousness where every individual shares memory and learns as one.
144
+
145
+ #### Parallel Worktrees
146
+ *"The single biggest productivity unlock"*
147
+
148
+ ```bash
149
+ # Create worktrees for parallel Claude sessions
150
+ gaia_worktree_create branch="feature/auth" alias="a" purpose="OAuth implementation"
151
+ gaia_worktree_create branch="bugfix/login" alias="b" purpose="Fix login crash"
152
+
153
+ # Quick switch (generates shell aliases)
154
+ # alias za='cd /path/to/project-a && claude'
155
+ # alias zb='cd /path/to/project-b && claude'
156
+ ```
157
+
158
+ #### Collective Learning
159
+ *"Every correction benefits all future sessions"*
160
+
161
+ ```bash
162
+ # Capture a correction
163
+ gaia_learn \
164
+ mistake="Used any type instead of proper typing" \
165
+ correction="Always use explicit types, never any" \
166
+ category="code_style"
167
+
168
+ # Apply to CLAUDE.md
169
+ gaia_apply
170
+ ```
171
+
172
+ #### Session Memory
173
+
174
+ ```bash
175
+ # Register a session
176
+ gaia_session_register purpose="Implementing OAuth2" taskType="feature"
177
+
178
+ # Create handoff document for another session
179
+ gaia_session_handoff sessionId="sess_abc123" includeGitStatus=true
180
+
181
+ # Remember context for later
182
+ gaia_remember name="pre-refactor" notes="Before auth rewrite"
183
+
184
+ # Recall a memory
185
+ gaia_recall name="pre-refactor"
186
+ ```
187
+
188
+ **Tools**: `gaia_worktree_create`, `gaia_worktree_list`, `gaia_worktree_switch`, `gaia_worktree_cleanup`, `gaia_session_register`, `gaia_session_status`, `gaia_session_handoff`, `gaia_session_complete`, `gaia_learn`, `gaia_apply`, `gaia_review`, `gaia_remember`, `gaia_recall`
189
+
190
+ ---
191
+
192
+ ## Configuration
193
+
194
+ Foundation uses a single YAML config file:
195
+
196
+ **Location**: `~/.foundation/config.yaml`
197
+
198
+ ```yaml
199
+ version: "1.0"
200
+
201
+ # Global defaults
202
+ defaults:
203
+ temperature: 0.7
204
+ max_tokens: 4096
205
+ timeout_ms: 60000
206
+
207
+ # Provider API keys (use environment variables)
208
+ providers:
209
+ anthropic:
210
+ api_key: ${ANTHROPIC_API_KEY}
211
+ access_mode: session # Use current Claude session when possible
212
+ openai:
213
+ api_key: ${OPENAI_API_KEY}
214
+ default_model: gpt-4o
215
+ deepseek:
216
+ api_key: ${DEEPSEEK_API_KEY}
217
+ default_model: deepseek-reasoner
218
+ ollama:
219
+ base_url: http://localhost:11434
220
+ default_model: llama3.3:70b
221
+
222
+ # Role assignments with fallback chains
223
+ roles:
224
+ orchestrator:
225
+ provider: anthropic
226
+ model: claude-sonnet-4-20250514
227
+ coder:
228
+ provider: deepseek
229
+ model: deepseek-reasoner
230
+ needs_worktree: true
231
+ fallback_chain:
232
+ - provider: openai
233
+ model: gpt-4o
234
+ critic:
235
+ provider: deepseek
236
+ model: deepseek-reasoner
237
+ temperature: 0.3
238
+ reviewer:
239
+ provider: openai
240
+ model: gpt-4o
241
+
242
+ # Demerzel settings (codebase intelligence)
243
+ demerzel:
244
+ provider: ollama
245
+ model: qwen2.5-coder:7b
246
+ snapshot_max_age_hours: 24
247
+
248
+ # Gaia settings (workflow patterns)
249
+ worktrees:
250
+ base_dir: .foundation/worktrees
251
+ max_count: 10
252
+ auto_cleanup: true
253
+
254
+ learning:
255
+ auto_apply: false
256
+ ```
257
+
258
+ ---
259
+
260
+ ## The Foundation Trilogy
261
+
262
+ Just as in Asimov's universe, the three work together:
263
+
264
+ ```
265
+ ┌─────────────────────────────────────────────────────────────┐
266
+ │ FOUNDATION │
267
+ │ │
268
+ │ DEMERZEL SELDON GAIA │
269
+ │ (The Observer) (The Planner) (The Memory) │
270
+ │ │
271
+ │ Knows the Orchestrates Preserves context │
272
+ │ codebase the agents across sessions │
273
+ │ perfectly and plans and learns │
274
+ │ │
275
+ │ "I have been "The future is "We are all one, │
276
+ │ watching for not set, but it and one is all" │
277
+ │ 20,000 years" can be guided" │
278
+ └─────────────────────────────────────────────────────────────┘
279
+ ```
280
+
281
+ ---
282
+
283
+ ## Data Storage
284
+
285
+ ```
286
+ ~/.foundation/
287
+ ├── config.yaml # Main configuration
288
+ ├── state/
289
+ │ ├── worktrees.json # Active worktrees
290
+ │ ├── sessions.json # Session tracking
291
+ │ ├── learnings.json # Global learnings
292
+ │ ├── pipelines.json # Pipeline state
293
+ │ ├── tasks.json # Task queue
294
+ │ ├── snapshots.json # Context memories
295
+ │ └── provider-health.json # Provider health tracking
296
+ └── cache/
297
+ └── ...
298
+
299
+ .foundation/ # Project-level (in repo root)
300
+ ├── config.yaml # Project overrides
301
+ ├── snapshot.txt # Codebase snapshot (Demerzel)
302
+ ├── learnings.json # Project-specific learnings (Gaia)
303
+ └── sessions.json # Project sessions (Gaia)
304
+ ```
305
+
306
+ ---
307
+
308
+ ## Development
309
+
310
+ ```bash
311
+ # Clone and install
312
+ git clone https://github.com/sashabogi/foundation.git
313
+ cd foundation
314
+ npm install
315
+
316
+ # Build
317
+ npm run build
318
+
319
+ # Development with watch
320
+ npm run dev
321
+
322
+ # Run directly
323
+ npm start
324
+ ```
325
+
326
+ ---
327
+
328
+ ## Credits
329
+
330
+ Foundation consolidates work from:
331
+ - [Argus](https://github.com/sashabogi/argus) → **Demerzel**
332
+ - [Hari Seldon](https://github.com/sashabogi/hari-seldon) → **Seldon**
333
+ - Claude Workflow Orchestrator → **Gaia**
334
+
335
+ Inspired by Isaac Asimov's Foundation series.
336
+
337
+ ---
338
+
339
+ ## License
340
+
341
+ MIT
package/dist/cli.d.ts ADDED
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Foundation CLI
4
+ *
5
+ * Commands:
6
+ * - foundation init Setup wizard for configuration
7
+ * - foundation start Start the MCP server
8
+ * - foundation mcp MCP installation helpers
9
+ * - foundation status Check Foundation status
10
+ */
11
+ export {};
12
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA;;;;;;;;GAQG"}
package/dist/cli.js ADDED
@@ -0,0 +1,308 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Foundation CLI
4
+ *
5
+ * Commands:
6
+ * - foundation init Setup wizard for configuration
7
+ * - foundation start Start the MCP server
8
+ * - foundation mcp MCP installation helpers
9
+ * - foundation status Check Foundation status
10
+ */
11
+ import { Command } from 'commander';
12
+ import chalk from 'chalk';
13
+ import ora from 'ora';
14
+ import { existsSync, mkdirSync, writeFileSync, readFileSync } from 'fs';
15
+ import { homedir } from 'os';
16
+ import { join } from 'path';
17
+ import { ConfigService } from './services/config.service.js';
18
+ const VERSION = '0.1.0';
19
+ const CONFIG_DIR = join(homedir(), '.foundation');
20
+ const CONFIG_FILE = join(CONFIG_DIR, 'config.yaml');
21
+ const program = new Command();
22
+ program
23
+ .name('foundation')
24
+ .description('Unified MCP server for AI-assisted development')
25
+ .version(VERSION);
26
+ // ============================================================================
27
+ // foundation init
28
+ // ============================================================================
29
+ program
30
+ .command('init')
31
+ .description('Initialize Foundation configuration')
32
+ .option('-f, --force', 'Overwrite existing configuration')
33
+ .action(async (options) => {
34
+ const spinner = ora('Initializing Foundation...').start();
35
+ try {
36
+ // Create config directory
37
+ if (!existsSync(CONFIG_DIR)) {
38
+ mkdirSync(CONFIG_DIR, { recursive: true });
39
+ spinner.text = 'Created ~/.foundation directory';
40
+ }
41
+ // Check for existing config
42
+ if (existsSync(CONFIG_FILE) && !options.force) {
43
+ spinner.warn('Configuration already exists. Use --force to overwrite.');
44
+ console.log(chalk.gray(` Config: ${CONFIG_FILE}`));
45
+ return;
46
+ }
47
+ // Create default config
48
+ const defaultConfig = `# Foundation Configuration
49
+ # https://github.com/sashabogi/foundation
50
+
51
+ version: "1.0"
52
+
53
+ # Global defaults
54
+ defaults:
55
+ temperature: 0.7
56
+ max_tokens: 4096
57
+ timeout_ms: 60000
58
+
59
+ # Provider API keys (use environment variables for security)
60
+ providers:
61
+ anthropic:
62
+ api_key: \${ANTHROPIC_API_KEY}
63
+ access_mode: session # 'api', 'session', or 'auto'
64
+
65
+ openai:
66
+ api_key: \${OPENAI_API_KEY}
67
+ default_model: gpt-4o
68
+
69
+ # deepseek:
70
+ # api_key: \${DEEPSEEK_API_KEY}
71
+ # default_model: deepseek-reasoner
72
+
73
+ # ollama:
74
+ # base_url: http://localhost:11434
75
+ # default_model: llama3.3:70b
76
+
77
+ # Role assignments
78
+ roles:
79
+ orchestrator:
80
+ provider: anthropic
81
+ model: claude-sonnet-4-20250514
82
+
83
+ coder:
84
+ provider: anthropic
85
+ model: claude-sonnet-4-20250514
86
+ needs_worktree: true
87
+
88
+ critic:
89
+ provider: anthropic
90
+ model: claude-sonnet-4-20250514
91
+ temperature: 0.3
92
+
93
+ reviewer:
94
+ provider: anthropic
95
+ model: claude-sonnet-4-20250514
96
+
97
+ designer:
98
+ provider: anthropic
99
+ model: claude-sonnet-4-20250514
100
+
101
+ researcher:
102
+ provider: anthropic
103
+ model: claude-sonnet-4-20250514
104
+
105
+ verifier:
106
+ provider: anthropic
107
+ model: claude-sonnet-4-20250514
108
+ temperature: 0.2
109
+
110
+ # Demerzel settings (codebase intelligence)
111
+ demerzel:
112
+ provider: anthropic
113
+ model: claude-sonnet-4-20250514
114
+ snapshot_max_age_hours: 24
115
+ auto_refresh: false
116
+
117
+ # Gaia settings (workflow patterns)
118
+ worktrees:
119
+ base_dir: .foundation/worktrees
120
+ max_count: 10
121
+ auto_cleanup: true
122
+ stale_after_hours: 48
123
+
124
+ learning:
125
+ auto_apply: false
126
+ categories:
127
+ - code_style
128
+ - architecture
129
+ - testing
130
+ - performance
131
+ - security
132
+ - documentation
133
+ `;
134
+ writeFileSync(CONFIG_FILE, defaultConfig);
135
+ spinner.succeed('Foundation initialized!');
136
+ console.log();
137
+ console.log(chalk.green('✓') + ' Configuration created at ' + chalk.cyan(CONFIG_FILE));
138
+ console.log();
139
+ console.log(chalk.bold('Next steps:'));
140
+ console.log(' 1. Edit ' + chalk.cyan('~/.foundation/config.yaml') + ' to add your API keys');
141
+ console.log(' 2. Run ' + chalk.cyan('foundation mcp install') + ' to add to Claude Code');
142
+ console.log(' 3. Restart Claude Code');
143
+ console.log();
144
+ }
145
+ catch (error) {
146
+ spinner.fail('Failed to initialize Foundation');
147
+ console.error(chalk.red(error instanceof Error ? error.message : String(error)));
148
+ process.exit(1);
149
+ }
150
+ });
151
+ // ============================================================================
152
+ // foundation start
153
+ // ============================================================================
154
+ program
155
+ .command('start')
156
+ .description('Start the Foundation MCP server')
157
+ .option('-v, --verbose', 'Enable verbose logging')
158
+ .action(async (options) => {
159
+ console.log(chalk.bold('Foundation MCP Server'));
160
+ console.log(chalk.gray('Press Ctrl+C to stop'));
161
+ console.log();
162
+ // Import and start the server
163
+ const { startServer } = await import('./index.js');
164
+ await startServer();
165
+ });
166
+ // ============================================================================
167
+ // foundation mcp
168
+ // ============================================================================
169
+ const mcpCommand = program
170
+ .command('mcp')
171
+ .description('MCP installation helpers');
172
+ mcpCommand
173
+ .command('install')
174
+ .description('Add Foundation to Claude Code MCP configuration')
175
+ .action(async () => {
176
+ const spinner = ora('Adding Foundation to Claude Code...').start();
177
+ try {
178
+ // Find Claude Code config location
179
+ const possiblePaths = [
180
+ join(homedir(), '.config', 'claude-code', 'mcp.json'),
181
+ join(homedir(), 'Library', 'Application Support', 'Claude', 'claude_desktop_config.json'),
182
+ join(homedir(), '.claude', 'mcp.json'),
183
+ ];
184
+ let configPath = null;
185
+ for (const path of possiblePaths) {
186
+ if (existsSync(path)) {
187
+ configPath = path;
188
+ break;
189
+ }
190
+ }
191
+ // Determine the Foundation executable path
192
+ const foundationPath = process.argv[1]; // Current CLI path
193
+ const serverPath = foundationPath.replace('cli.js', 'index.js');
194
+ const mcpEntry = {
195
+ foundation: {
196
+ command: 'node',
197
+ args: [serverPath],
198
+ env: {
199
+ ANTHROPIC_API_KEY: '${ANTHROPIC_API_KEY}',
200
+ OPENAI_API_KEY: '${OPENAI_API_KEY}',
201
+ },
202
+ },
203
+ };
204
+ if (configPath) {
205
+ // Update existing config
206
+ const existing = JSON.parse(readFileSync(configPath, 'utf-8'));
207
+ existing.mcpServers = existing.mcpServers || {};
208
+ existing.mcpServers.foundation = mcpEntry.foundation;
209
+ writeFileSync(configPath, JSON.stringify(existing, null, 2));
210
+ spinner.succeed('Updated Claude Code configuration');
211
+ console.log(chalk.gray(` Config: ${configPath}`));
212
+ }
213
+ else {
214
+ // Create new config (Claude Desktop format)
215
+ const claudeDesktopPath = join(homedir(), 'Library', 'Application Support', 'Claude', 'claude_desktop_config.json');
216
+ const claudeDir = join(homedir(), 'Library', 'Application Support', 'Claude');
217
+ if (!existsSync(claudeDir)) {
218
+ mkdirSync(claudeDir, { recursive: true });
219
+ }
220
+ const newConfig = { mcpServers: mcpEntry };
221
+ writeFileSync(claudeDesktopPath, JSON.stringify(newConfig, null, 2));
222
+ spinner.succeed('Created Claude Desktop configuration');
223
+ console.log(chalk.gray(` Config: ${claudeDesktopPath}`));
224
+ }
225
+ console.log();
226
+ console.log(chalk.bold('Restart Claude Code/Desktop to activate Foundation.'));
227
+ console.log();
228
+ console.log('Available tools:');
229
+ console.log(chalk.cyan(' Demerzel (9)') + ' - Codebase intelligence');
230
+ console.log(chalk.cyan(' Seldon (19)') + ' - Multi-agent orchestration');
231
+ console.log(chalk.cyan(' Gaia (13)') + ' - Workflow patterns');
232
+ console.log();
233
+ }
234
+ catch (error) {
235
+ spinner.fail('Failed to install MCP configuration');
236
+ console.error(chalk.red(error instanceof Error ? error.message : String(error)));
237
+ process.exit(1);
238
+ }
239
+ });
240
+ mcpCommand
241
+ .command('config')
242
+ .description('Print MCP configuration JSON for manual installation')
243
+ .action(() => {
244
+ const serverPath = process.argv[1].replace('cli.js', 'index.js');
245
+ const config = {
246
+ mcpServers: {
247
+ foundation: {
248
+ command: 'node',
249
+ args: [serverPath],
250
+ env: {
251
+ ANTHROPIC_API_KEY: '${ANTHROPIC_API_KEY}',
252
+ OPENAI_API_KEY: '${OPENAI_API_KEY}',
253
+ },
254
+ },
255
+ },
256
+ };
257
+ console.log(JSON.stringify(config, null, 2));
258
+ });
259
+ // ============================================================================
260
+ // foundation status
261
+ // ============================================================================
262
+ program
263
+ .command('status')
264
+ .description('Check Foundation status and configuration')
265
+ .action(async () => {
266
+ console.log(chalk.bold('Foundation Status'));
267
+ console.log();
268
+ // Check config
269
+ const configExists = existsSync(CONFIG_FILE);
270
+ console.log((configExists ? chalk.green('✓') : chalk.red('✗')) +
271
+ ' Configuration: ' +
272
+ (configExists ? chalk.cyan(CONFIG_FILE) : chalk.gray('Not found')));
273
+ if (configExists) {
274
+ try {
275
+ const config = ConfigService.getInstance();
276
+ const providers = config.getProviders();
277
+ console.log();
278
+ console.log(chalk.bold('Configured Providers:'));
279
+ for (const [name, providerConfig] of Object.entries(providers)) {
280
+ if (providerConfig) {
281
+ const hasKey = providerConfig.api_key && !providerConfig.api_key.includes('${');
282
+ console.log(' ' +
283
+ (hasKey ? chalk.green('✓') : chalk.yellow('○')) +
284
+ ' ' + name +
285
+ (hasKey ? '' : chalk.gray(' (needs API key)')));
286
+ }
287
+ }
288
+ }
289
+ catch (error) {
290
+ console.log(chalk.yellow(' Could not parse configuration'));
291
+ }
292
+ }
293
+ // Check state directory
294
+ const stateDir = join(CONFIG_DIR, 'state');
295
+ const stateExists = existsSync(stateDir);
296
+ console.log();
297
+ console.log((stateExists ? chalk.green('✓') : chalk.gray('○')) +
298
+ ' State directory: ' +
299
+ (stateExists ? chalk.cyan(stateDir) : chalk.gray('Not created yet')));
300
+ console.log();
301
+ console.log(chalk.gray('Run `foundation init` to create configuration'));
302
+ console.log(chalk.gray('Run `foundation mcp install` to add to Claude Code'));
303
+ });
304
+ // ============================================================================
305
+ // Parse and run
306
+ // ============================================================================
307
+ program.parse();
308
+ //# sourceMappingURL=cli.js.map