@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.
- package/LICENSE +21 -0
- package/README.md +341 -0
- package/dist/cli.d.ts +12 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +308 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.d.ts +32 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +78 -0
- package/dist/index.js.map +1 -0
- package/dist/services/config.service.d.ts +92 -0
- package/dist/services/config.service.d.ts.map +1 -0
- package/dist/services/config.service.js +284 -0
- package/dist/services/config.service.js.map +1 -0
- package/dist/services/git.service.d.ts +175 -0
- package/dist/services/git.service.d.ts.map +1 -0
- package/dist/services/git.service.js +395 -0
- package/dist/services/git.service.js.map +1 -0
- package/dist/services/provider.service.d.ts +74 -0
- package/dist/services/provider.service.d.ts.map +1 -0
- package/dist/services/provider.service.js +182 -0
- package/dist/services/provider.service.js.map +1 -0
- package/dist/services/storage.service.d.ts +84 -0
- package/dist/services/storage.service.d.ts.map +1 -0
- package/dist/services/storage.service.js +320 -0
- package/dist/services/storage.service.js.map +1 -0
- package/dist/tools/demerzel/index.d.ts +21 -0
- package/dist/tools/demerzel/index.d.ts.map +1 -0
- package/dist/tools/demerzel/index.js +166 -0
- package/dist/tools/demerzel/index.js.map +1 -0
- package/dist/tools/gaia/index.d.ts +27 -0
- package/dist/tools/gaia/index.d.ts.map +1 -0
- package/dist/tools/gaia/index.js +466 -0
- package/dist/tools/gaia/index.js.map +1 -0
- package/dist/tools/seldon/index.d.ts +43 -0
- package/dist/tools/seldon/index.d.ts.map +1 -0
- package/dist/tools/seldon/index.js +886 -0
- package/dist/tools/seldon/index.js.map +1 -0
- package/dist/types/index.d.ts +392 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +10 -0
- package/dist/types/index.js.map +1 -0
- 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
|