codebase-cli 2.0.0-pre.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 +266 -0
- package/bin/codebase +2 -0
- package/dist/agent/agent.js +198 -0
- package/dist/agent/agent.js.map +1 -0
- package/dist/agent/config.js +117 -0
- package/dist/agent/config.js.map +1 -0
- package/dist/agent/events.js +153 -0
- package/dist/agent/events.js.map +1 -0
- package/dist/agent/router.js +35 -0
- package/dist/agent/router.js.map +1 -0
- package/dist/agent/system-prompt.js +21 -0
- package/dist/agent/system-prompt.js.map +1 -0
- package/dist/auth/cli.js +138 -0
- package/dist/auth/cli.js.map +1 -0
- package/dist/auth/credentials.js +105 -0
- package/dist/auth/credentials.js.map +1 -0
- package/dist/auth/flow.js +222 -0
- package/dist/auth/flow.js.map +1 -0
- package/dist/auth/pkce.js +46 -0
- package/dist/auth/pkce.js.map +1 -0
- package/dist/cli.js +69 -0
- package/dist/cli.js.map +1 -0
- package/dist/clipboard/copy.js +106 -0
- package/dist/clipboard/copy.js.map +1 -0
- package/dist/commands/builtins.js +203 -0
- package/dist/commands/builtins.js.map +1 -0
- package/dist/commands/registry.js +65 -0
- package/dist/commands/registry.js.map +1 -0
- package/dist/commands/types.js +2 -0
- package/dist/commands/types.js.map +1 -0
- package/dist/compaction/engine.js +209 -0
- package/dist/compaction/engine.js.map +1 -0
- package/dist/compaction/tokens.js +79 -0
- package/dist/compaction/tokens.js.map +1 -0
- package/dist/compaction/types.js +2 -0
- package/dist/compaction/types.js.map +1 -0
- package/dist/diagnostics/checkers.js +211 -0
- package/dist/diagnostics/checkers.js.map +1 -0
- package/dist/diagnostics/engine.js +71 -0
- package/dist/diagnostics/engine.js.map +1 -0
- package/dist/diagnostics/types.js +2 -0
- package/dist/diagnostics/types.js.map +1 -0
- package/dist/dotenv/loader.js +115 -0
- package/dist/dotenv/loader.js.map +1 -0
- package/dist/glue/client.js +47 -0
- package/dist/glue/client.js.map +1 -0
- package/dist/glue/intent.js +78 -0
- package/dist/glue/intent.js.map +1 -0
- package/dist/glue/narration.js +55 -0
- package/dist/glue/narration.js.map +1 -0
- package/dist/headless/run.js +89 -0
- package/dist/headless/run.js.map +1 -0
- package/dist/hooks/manager.js +158 -0
- package/dist/hooks/manager.js.map +1 -0
- package/dist/hooks/runner.js +70 -0
- package/dist/hooks/runner.js.map +1 -0
- package/dist/hooks/types.js +2 -0
- package/dist/hooks/types.js.map +1 -0
- package/dist/memory/inject.js +12 -0
- package/dist/memory/inject.js.map +1 -0
- package/dist/memory/store.js +178 -0
- package/dist/memory/store.js.map +1 -0
- package/dist/memory/types.js +10 -0
- package/dist/memory/types.js.map +1 -0
- package/dist/permissions/store.js +172 -0
- package/dist/permissions/store.js.map +1 -0
- package/dist/plan/flow.js +214 -0
- package/dist/plan/flow.js.map +1 -0
- package/dist/plan/prompts.js +69 -0
- package/dist/plan/prompts.js.map +1 -0
- package/dist/plan/store.js +37 -0
- package/dist/plan/store.js.map +1 -0
- package/dist/plan/types.js +3 -0
- package/dist/plan/types.js.map +1 -0
- package/dist/sessions/store.js +105 -0
- package/dist/sessions/store.js.map +1 -0
- package/dist/skills/loader.js +41 -0
- package/dist/skills/loader.js.map +1 -0
- package/dist/skills/platform-loader.js +63 -0
- package/dist/skills/platform-loader.js.map +1 -0
- package/dist/skills/types.js +21 -0
- package/dist/skills/types.js.map +1 -0
- package/dist/tools/ask-user.js +61 -0
- package/dist/tools/ask-user.js.map +1 -0
- package/dist/tools/dispatch-agent.js +178 -0
- package/dist/tools/dispatch-agent.js.map +1 -0
- package/dist/tools/edit-file.js +80 -0
- package/dist/tools/edit-file.js.map +1 -0
- package/dist/tools/errors.js +89 -0
- package/dist/tools/errors.js.map +1 -0
- package/dist/tools/file-ops.js +136 -0
- package/dist/tools/file-ops.js.map +1 -0
- package/dist/tools/file-state-cache.js +92 -0
- package/dist/tools/file-state-cache.js.map +1 -0
- package/dist/tools/git/branch.js +84 -0
- package/dist/tools/git/branch.js.map +1 -0
- package/dist/tools/git/commit.js +83 -0
- package/dist/tools/git/commit.js.map +1 -0
- package/dist/tools/git/diff.js +72 -0
- package/dist/tools/git/diff.js.map +1 -0
- package/dist/tools/git/git-helpers.js +58 -0
- package/dist/tools/git/git-helpers.js.map +1 -0
- package/dist/tools/git/log.js +70 -0
- package/dist/tools/git/log.js.map +1 -0
- package/dist/tools/git/status.js +97 -0
- package/dist/tools/git/status.js.map +1 -0
- package/dist/tools/git/worktree.js +132 -0
- package/dist/tools/git/worktree.js.map +1 -0
- package/dist/tools/glob.js +128 -0
- package/dist/tools/glob.js.map +1 -0
- package/dist/tools/grep.js +199 -0
- package/dist/tools/grep.js.map +1 -0
- package/dist/tools/list-files.js +120 -0
- package/dist/tools/list-files.js.map +1 -0
- package/dist/tools/memory-tools.js +127 -0
- package/dist/tools/memory-tools.js.map +1 -0
- package/dist/tools/multi-edit.js +87 -0
- package/dist/tools/multi-edit.js.map +1 -0
- package/dist/tools/notebook-edit.js +147 -0
- package/dist/tools/notebook-edit.js.map +1 -0
- package/dist/tools/permission.js +168 -0
- package/dist/tools/permission.js.map +1 -0
- package/dist/tools/plan-mode.js +76 -0
- package/dist/tools/plan-mode.js.map +1 -0
- package/dist/tools/read-file.js +135 -0
- package/dist/tools/read-file.js.map +1 -0
- package/dist/tools/registry.js +52 -0
- package/dist/tools/registry.js.map +1 -0
- package/dist/tools/shell.js +216 -0
- package/dist/tools/shell.js.map +1 -0
- package/dist/tools/task-store.js +70 -0
- package/dist/tools/task-store.js.map +1 -0
- package/dist/tools/tasks.js +131 -0
- package/dist/tools/tasks.js.map +1 -0
- package/dist/tools/types.js +2 -0
- package/dist/tools/types.js.map +1 -0
- package/dist/tools/web-fetch.js +152 -0
- package/dist/tools/web-fetch.js.map +1 -0
- package/dist/tools/web-search.js +169 -0
- package/dist/tools/web-search.js.map +1 -0
- package/dist/tools/write-file.js +70 -0
- package/dist/tools/write-file.js.map +1 -0
- package/dist/types.js +9 -0
- package/dist/types.js.map +1 -0
- package/dist/ui/App.js +216 -0
- package/dist/ui/App.js.map +1 -0
- package/dist/ui/Input.js +90 -0
- package/dist/ui/Input.js.map +1 -0
- package/dist/ui/Message.js +89 -0
- package/dist/ui/Message.js.map +1 -0
- package/dist/ui/MessageList.js +35 -0
- package/dist/ui/MessageList.js.map +1 -0
- package/dist/ui/Permission.js +39 -0
- package/dist/ui/Permission.js.map +1 -0
- package/dist/ui/Status.js +34 -0
- package/dist/ui/Status.js.map +1 -0
- package/dist/ui/TaskPanel.js +43 -0
- package/dist/ui/TaskPanel.js.map +1 -0
- package/dist/ui/Throbber.js +20 -0
- package/dist/ui/Throbber.js.map +1 -0
- package/dist/ui/ToolPanel.js +83 -0
- package/dist/ui/ToolPanel.js.map +1 -0
- package/dist/ui/UserQuery.js +38 -0
- package/dist/ui/UserQuery.js.map +1 -0
- package/dist/ui/input-state.js +210 -0
- package/dist/ui/input-state.js.map +1 -0
- package/dist/ui/wrap.js +30 -0
- package/dist/ui/wrap.js.map +1 -0
- package/dist/user-queries/store.js +60 -0
- package/dist/user-queries/store.js.map +1 -0
- package/package.json +76 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Codebase Foundation
|
|
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,266 @@
|
|
|
1
|
+
# Codebase CLI
|
|
2
|
+
|
|
3
|
+
AI coding agent in your terminal. Reads your project, writes code, runs commands, searches the web. Works with any LLM provider — or sign in with codebase.foundation and we proxy inference for you.
|
|
4
|
+
|
|
5
|
+
> **v2 (TypeScript)** — codebase-cli has been rewritten on top of the
|
|
6
|
+
> [pi-mono](https://github.com/earendil-works/pi-mono) runtime. Existing
|
|
7
|
+
> v1 (Go) users: the installer below auto-detects the old binary and
|
|
8
|
+
> migrates your data. See [`docs/MIGRATION_v1_to_v2.md`](docs/MIGRATION_v1_to_v2.md).
|
|
9
|
+
|
|
10
|
+
## Install
|
|
11
|
+
|
|
12
|
+
Requires **Node.js ≥ 20**. The one-liner installer prints a hint with Volta/fnm/nvm if Node is missing or too old.
|
|
13
|
+
|
|
14
|
+
**macOS / Linux (one-liner — recommended):**
|
|
15
|
+
|
|
16
|
+
```sh
|
|
17
|
+
curl -fsSL https://codebase.design/install.sh | sh
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
This detects an existing v1 binary, asks before removing it, then installs v2 via npm.
|
|
21
|
+
|
|
22
|
+
**Windows (PowerShell):**
|
|
23
|
+
|
|
24
|
+
```powershell
|
|
25
|
+
irm https://codebase.design/install.ps1 | iex
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
**With npm (any platform, requires Node.js ≥ 20):**
|
|
29
|
+
|
|
30
|
+
```sh
|
|
31
|
+
npm install -g codebase-cli
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
**With Homebrew:**
|
|
35
|
+
|
|
36
|
+
```sh
|
|
37
|
+
brew install codebase-foundation/codebase/codebase
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
**From source:**
|
|
41
|
+
|
|
42
|
+
```sh
|
|
43
|
+
git clone https://github.com/codebase-foundation/codebase-cli.git
|
|
44
|
+
cd codebase-cli
|
|
45
|
+
npm install
|
|
46
|
+
npm run build
|
|
47
|
+
npm link # symlinks `codebase` into your npm prefix
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
After install, run `codebase` from any project directory.
|
|
51
|
+
|
|
52
|
+
## Quick Start
|
|
53
|
+
|
|
54
|
+
**Option 1: Login with Codebase (easiest)**
|
|
55
|
+
|
|
56
|
+
```sh
|
|
57
|
+
codebase auth login
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Opens your browser, logs you into codebase.foundation, and you're ready. Uses our inference providers (Claude, MiniMax, Qwen, etc.) with your account credits. No API keys needed.
|
|
61
|
+
|
|
62
|
+
**Option 2: Bring your own API key**
|
|
63
|
+
|
|
64
|
+
```sh
|
|
65
|
+
export ANTHROPIC_API_KEY=sk-ant-...
|
|
66
|
+
codebase
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Works with any provider:
|
|
70
|
+
|
|
71
|
+
```sh
|
|
72
|
+
# OpenAI
|
|
73
|
+
export OPENAI_API_KEY=sk-...
|
|
74
|
+
|
|
75
|
+
# Groq
|
|
76
|
+
export OPENAI_BASE_URL=https://api.groq.com/openai/v1
|
|
77
|
+
export OPENAI_API_KEY=gsk-...
|
|
78
|
+
export OPENAI_MODEL=llama-3.3-70b-versatile
|
|
79
|
+
|
|
80
|
+
# Ollama (local, free)
|
|
81
|
+
export OPENAI_BASE_URL=http://localhost:11434/v1
|
|
82
|
+
export OPENAI_API_KEY=ollama
|
|
83
|
+
export OPENAI_MODEL=qwen2.5-coder:32b
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
**Option 3: First-run setup wizard**
|
|
87
|
+
|
|
88
|
+
Just run `codebase` with no config. The setup wizard walks you through picking a provider, entering your key, and selecting a model. "Login with Codebase" is the first option.
|
|
89
|
+
|
|
90
|
+
## What It Does
|
|
91
|
+
|
|
92
|
+
You describe what you want. The agent reads your code, makes changes, runs commands, and explains what it did.
|
|
93
|
+
|
|
94
|
+
```
|
|
95
|
+
> add a /health endpoint that returns uptime and version
|
|
96
|
+
|
|
97
|
+
read_file server.go ✓
|
|
98
|
+
read_file go.mod ✓
|
|
99
|
+
edit_file server.go ✓
|
|
100
|
+
shell go build ./... ✓
|
|
101
|
+
|
|
102
|
+
Added GET /health endpoint at server.go:47 returning JSON with
|
|
103
|
+
uptime, version, and go runtime. Build passes.
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## Tools (30)
|
|
107
|
+
|
|
108
|
+
| Category | Tools |
|
|
109
|
+
|----------|-------|
|
|
110
|
+
| **File read** | `read_file`, `list_files`, `glob`, `grep`, `search_files` |
|
|
111
|
+
| **File write** | `write_file`, `edit_file`, `multi_edit`, `notebook_edit` |
|
|
112
|
+
| **Shell** | `shell` (input-aware parallelism — read-only commands run concurrently) |
|
|
113
|
+
| **Git** | `git_status`, `git_diff`, `git_log`, `git_commit`, `git_branch`, `enter_worktree`, `exit_worktree` |
|
|
114
|
+
| **Web** | `web_search`, `web_fetch` |
|
|
115
|
+
| **Agent** | `dispatch_agent` (explore, plan, or general-purpose subagents with optional worktree isolation) |
|
|
116
|
+
| **Tasks** | `create_task`, `update_task`, `list_tasks`, `get_task` |
|
|
117
|
+
| **Planning** | `enter_plan_mode`, `exit_plan_mode` |
|
|
118
|
+
| **Memory** | `save_memory`, `read_memory` (persist context across sessions) |
|
|
119
|
+
| **Other** | `config`, `ask_user` |
|
|
120
|
+
|
|
121
|
+
Plus any tools from connected MCP servers.
|
|
122
|
+
|
|
123
|
+
## Commands (22)
|
|
124
|
+
|
|
125
|
+
| Command | What it does |
|
|
126
|
+
|---------|-------------|
|
|
127
|
+
| `/help` | List all commands |
|
|
128
|
+
| `/status` | Model, tokens, turns, cost |
|
|
129
|
+
| `/cost` | Token usage and estimated cost |
|
|
130
|
+
| `/context` | Visual context window usage bar |
|
|
131
|
+
| `/model [name]` | Show or switch model |
|
|
132
|
+
| `/commit` | Generate commit from current diff |
|
|
133
|
+
| `/review` | Code review of uncommitted changes |
|
|
134
|
+
| `/plan` | Enter planning mode |
|
|
135
|
+
| `/diff` | Open diff in VS Code/Cursor |
|
|
136
|
+
| `/compact` | Manually compact conversation |
|
|
137
|
+
| `/clear` | Clear display |
|
|
138
|
+
| `/memory` | View saved project memories |
|
|
139
|
+
| `/undo [file]` | Revert file from session history or git |
|
|
140
|
+
| `/export [file]` | Export conversation to markdown |
|
|
141
|
+
| `/tasks` | Show task checklist |
|
|
142
|
+
| `/theme` | Switch color theme |
|
|
143
|
+
| `/trust` | Set permission level |
|
|
144
|
+
| `/diagnostics` | Toggle language checkers |
|
|
145
|
+
| `/copy` | Copy last response to clipboard |
|
|
146
|
+
| `/session` | Full session info |
|
|
147
|
+
| `/setup` | Re-run setup wizard |
|
|
148
|
+
| `/quit` | Exit (or ctrl+c twice) |
|
|
149
|
+
|
|
150
|
+
## Features
|
|
151
|
+
|
|
152
|
+
- **30 tools** with schema validation and input-dependent parallel execution
|
|
153
|
+
- **Streaming tool execution** — tools start running before the model finishes responding
|
|
154
|
+
- **3 agent types** — explore (read-only), plan (architecture), general-purpose (full access)
|
|
155
|
+
- **Worktree isolation** — subagents can work in isolated git branches
|
|
156
|
+
- **Cross-session memory** — remembers your preferences and project context
|
|
157
|
+
- **Error recovery** — auto-retries on context overflow, output limits, rate limits
|
|
158
|
+
- **Structured compaction** — 9-section summaries when context gets long
|
|
159
|
+
- **Hooks system** — automate lint/test/format after edits
|
|
160
|
+
- **7 language checkers** — Go, TypeScript, ESLint, Python (pyright/mypy), Rust
|
|
161
|
+
- **MCP support** — connect external tool servers for extensibility
|
|
162
|
+
- **IDE detection** — discovers VS Code/Cursor/JetBrains via lockfiles
|
|
163
|
+
- **File history** — undo any edit within the session, even without git
|
|
164
|
+
- **Glue models** — route cheap tasks to a fast model, save money
|
|
165
|
+
- **Permission explainer** — risk-rated permission prompts (LOW/MEDIUM/HIGH)
|
|
166
|
+
- **Multi-provider** — OpenAI, Anthropic, MiniMax, Groq, Ollama, any compatible endpoint
|
|
167
|
+
- **OAuth-aware platform** — sign-in unlocks proxied inference and account-curated skills/templates/prompts
|
|
168
|
+
|
|
169
|
+
## Authentication
|
|
170
|
+
|
|
171
|
+
```sh
|
|
172
|
+
codebase auth login # browser OAuth — log in with Google, GitHub, or wallet
|
|
173
|
+
codebase auth <cbk_xxx> # save an API key from the dashboard (SSH / headless)
|
|
174
|
+
codebase auth status # show current sign-in
|
|
175
|
+
codebase auth refresh # force-refresh the access token
|
|
176
|
+
codebase auth logout # revoke session
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
Credentials are stored at `~/.codebase/credentials.json` (mode 0600).
|
|
180
|
+
|
|
181
|
+
When logged in, the CLI routes through `codebase.foundation` — you get access to all providers (Claude, MiniMax, Qwen, etc.) using your account credits. No API keys to manage. Skill, template, and prompt definitions you author in the web app become available automatically (Phase 7+).
|
|
182
|
+
|
|
183
|
+
## MCP (External Tool Servers)
|
|
184
|
+
|
|
185
|
+
Connect to any MCP-compatible server. Add to `~/.codebase/config.json`:
|
|
186
|
+
|
|
187
|
+
```json
|
|
188
|
+
{
|
|
189
|
+
"mcp_servers": {
|
|
190
|
+
"github": {
|
|
191
|
+
"command": "mcp-server-github",
|
|
192
|
+
"args": ["--token", "$GITHUB_TOKEN"],
|
|
193
|
+
"transport": "stdio"
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
MCP tools appear alongside built-in tools automatically.
|
|
200
|
+
|
|
201
|
+
## Hooks
|
|
202
|
+
|
|
203
|
+
Automate actions on events. Add to `~/.codebase/hooks.json`:
|
|
204
|
+
|
|
205
|
+
```json
|
|
206
|
+
[
|
|
207
|
+
{
|
|
208
|
+
"event": "PostEdit",
|
|
209
|
+
"matcher": "write_file|edit_file",
|
|
210
|
+
"command": "go vet ./...",
|
|
211
|
+
"timeout": 15
|
|
212
|
+
}
|
|
213
|
+
]
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
Events: `PreToolUse`, `PostToolUse`, `PostEdit`, `UserPromptSubmit`, `SessionStart`, `Stop`.
|
|
217
|
+
|
|
218
|
+
## Project Instructions
|
|
219
|
+
|
|
220
|
+
The CLI reads these files from your project root for context:
|
|
221
|
+
|
|
222
|
+
- `CLAUDE.md` — project instructions (Claude Code convention)
|
|
223
|
+
- `AGENTS.md` — agent instructions (OpenAI Codex convention)
|
|
224
|
+
- `CODEX.md` — project instructions (Codex convention)
|
|
225
|
+
- `.cursorrules` — project instructions (Cursor convention)
|
|
226
|
+
|
|
227
|
+
## Flags
|
|
228
|
+
|
|
229
|
+
```
|
|
230
|
+
codebase # run in current directory
|
|
231
|
+
codebase --dir /path/to/proj # run in specific directory
|
|
232
|
+
codebase --model claude-sonnet-4-5 # override model
|
|
233
|
+
codebase --resume # resume previous session
|
|
234
|
+
codebase --version # print version
|
|
235
|
+
codebase auth login # authenticate with codebase.foundation
|
|
236
|
+
codebase auth logout # revoke authentication
|
|
237
|
+
codebase --headless "fix the build" # one-shot, no TUI
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
## Environment Variables
|
|
241
|
+
|
|
242
|
+
```sh
|
|
243
|
+
# LLM Provider (pick one)
|
|
244
|
+
OPENAI_API_KEY=... # OpenAI or compatible
|
|
245
|
+
ANTHROPIC_API_KEY=... # Anthropic (auto-detected)
|
|
246
|
+
OPENAI_BASE_URL=... # Custom endpoint
|
|
247
|
+
OPENAI_MODEL=... # Override model
|
|
248
|
+
|
|
249
|
+
# Glue (optional — cheap model for routing/narration)
|
|
250
|
+
GLUE_API_KEY=...
|
|
251
|
+
GLUE_BASE_URL=...
|
|
252
|
+
GLUE_FAST_MODEL=...
|
|
253
|
+
GLUE_SMART_MODEL=...
|
|
254
|
+
|
|
255
|
+
# Web Search (optional — DuckDuckGo works without keys)
|
|
256
|
+
TAVILY_API_KEY=...
|
|
257
|
+
BRAVE_API_KEY=...
|
|
258
|
+
|
|
259
|
+
# Behavior
|
|
260
|
+
CODEBASE_NOBOOT=1 # skip boot animation
|
|
261
|
+
CODEBASE_NOSOUND=1 # skip boot audio
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
## License
|
|
265
|
+
|
|
266
|
+
MIT
|
package/bin/codebase
ADDED
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
import { homedir } from "node:os";
|
|
2
|
+
import { isAbsolute, join, resolve } from "node:path";
|
|
3
|
+
import { Agent } from "@earendil-works/pi-agent-core";
|
|
4
|
+
import { CompactionEngine } from "../compaction/engine.js";
|
|
5
|
+
import { DiagnosticsEngine, formatDiagnostics } from "../diagnostics/engine.js";
|
|
6
|
+
import { GlueClient, resolveGlueModels } from "../glue/client.js";
|
|
7
|
+
import { HookManager } from "../hooks/manager.js";
|
|
8
|
+
import { buildMemoryAddendum } from "../memory/inject.js";
|
|
9
|
+
import { MemoryStore } from "../memory/store.js";
|
|
10
|
+
import { PermissionStore } from "../permissions/store.js";
|
|
11
|
+
import { PlanModeStore } from "../plan/store.js";
|
|
12
|
+
import { SessionStore } from "../sessions/store.js";
|
|
13
|
+
import { FileStateCache } from "../tools/file-state-cache.js";
|
|
14
|
+
import { buildTools } from "../tools/registry.js";
|
|
15
|
+
import { TaskStore } from "../tools/task-store.js";
|
|
16
|
+
import { UserQueryStore } from "../user-queries/store.js";
|
|
17
|
+
import { resolveConfig } from "./config.js";
|
|
18
|
+
import { buildSystemPrompt } from "./system-prompt.js";
|
|
19
|
+
const WRITE_TOOL_NAMES = new Set(["write_file", "edit_file", "multi_edit", "notebook_edit"]);
|
|
20
|
+
/**
|
|
21
|
+
* Tools blocked while plan mode is active. Anything that mutates working-tree
|
|
22
|
+
* state, runs commands, or talks to git's index belongs here. Read tools
|
|
23
|
+
* (read_file, list_files, glob, grep, dispatch_agent, web_*, git read trio)
|
|
24
|
+
* stay available so the agent can investigate and write the plan.
|
|
25
|
+
*/
|
|
26
|
+
const PLAN_MODE_BLOCKED = new Set([
|
|
27
|
+
"write_file",
|
|
28
|
+
"edit_file",
|
|
29
|
+
"multi_edit",
|
|
30
|
+
"notebook_edit",
|
|
31
|
+
"shell",
|
|
32
|
+
"git_commit",
|
|
33
|
+
"git_branch",
|
|
34
|
+
"enter_worktree",
|
|
35
|
+
"exit_worktree",
|
|
36
|
+
]);
|
|
37
|
+
export function createAgent(opts = {}) {
|
|
38
|
+
const { model, apiKey, source } = resolveConfig();
|
|
39
|
+
const cwd = opts.cwd ?? process.cwd();
|
|
40
|
+
const systemPrompt = opts.systemPrompt ?? buildSystemPrompt(cwd);
|
|
41
|
+
const permissions = new PermissionStore();
|
|
42
|
+
const userQueries = new UserQueryStore();
|
|
43
|
+
const planMode = new PlanModeStore();
|
|
44
|
+
const memory = new MemoryStore({ cwd });
|
|
45
|
+
const hooks = new HookManager();
|
|
46
|
+
hooks.loadFrom(join(homedir(), ".codebase", "hooks.json"), join(cwd, ".codebase", "hooks.json"));
|
|
47
|
+
const diagnostics = new DiagnosticsEngine({ cwd });
|
|
48
|
+
const glueModels = resolveGlueModels({ parentModel: model, parentApiKey: apiKey });
|
|
49
|
+
const glue = new GlueClient({
|
|
50
|
+
fastModel: glueModels.fast,
|
|
51
|
+
smartModel: glueModels.smart,
|
|
52
|
+
apiKey: glueModels.apiKey,
|
|
53
|
+
});
|
|
54
|
+
const compaction = new CompactionEngine({ glue, modelId: model.id });
|
|
55
|
+
const sessions = new SessionStore({ cwd });
|
|
56
|
+
const resumed = opts.resume ? sessions.load(model.id) : null;
|
|
57
|
+
const toolContext = {
|
|
58
|
+
cwd,
|
|
59
|
+
fileStateCache: new FileStateCache(),
|
|
60
|
+
tasks: new TaskStore(),
|
|
61
|
+
userQueries,
|
|
62
|
+
planMode,
|
|
63
|
+
memory,
|
|
64
|
+
spawnSubagent: ({ systemPrompt: subPrompt, tools: subTools }) => new Agent({
|
|
65
|
+
initialState: { model, systemPrompt: subPrompt, tools: subTools },
|
|
66
|
+
getApiKey: () => apiKey,
|
|
67
|
+
}),
|
|
68
|
+
};
|
|
69
|
+
// MEMORY.md gets concatenated onto the system prompt at agent creation.
|
|
70
|
+
// Reload-after-save is a Phase 11 polish item.
|
|
71
|
+
const fullSystemPrompt = systemPrompt + buildMemoryAddendum(memory);
|
|
72
|
+
const agent = new Agent({
|
|
73
|
+
initialState: {
|
|
74
|
+
model,
|
|
75
|
+
systemPrompt: fullSystemPrompt,
|
|
76
|
+
tools: buildTools(toolContext),
|
|
77
|
+
messages: resumed?.messages ?? [],
|
|
78
|
+
},
|
|
79
|
+
getApiKey: () => apiKey,
|
|
80
|
+
transformContext: async (messages, signal) => {
|
|
81
|
+
if (!compaction.needsCompaction(messages))
|
|
82
|
+
return messages;
|
|
83
|
+
const result = await compaction.compact(messages, signal);
|
|
84
|
+
return result.messages;
|
|
85
|
+
},
|
|
86
|
+
beforeToolCall: async (ctx, signal) => {
|
|
87
|
+
// 1. Plan mode gate: block destructive tools entirely while planning.
|
|
88
|
+
if (planMode.isActive() && PLAN_MODE_BLOCKED.has(ctx.toolCall.name)) {
|
|
89
|
+
return {
|
|
90
|
+
block: true,
|
|
91
|
+
reason: `${ctx.toolCall.name} is blocked while plan mode is active. ` +
|
|
92
|
+
"Use exit_plan_mode after presenting your plan to regain write access.",
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
// 2. Built-in permission gate (fast, sync for read-only tools).
|
|
96
|
+
const decision = await permissions.evaluate(ctx.toolCall.name, ctx.args);
|
|
97
|
+
if (decision === "block") {
|
|
98
|
+
return { block: true, reason: "Permission denied by user." };
|
|
99
|
+
}
|
|
100
|
+
// 3. User-defined hooks (typically audit/lint/validation steps).
|
|
101
|
+
const filePath = ctx.args?.path;
|
|
102
|
+
const outcome = await hooks.dispatch("PreToolUse", {
|
|
103
|
+
event: "PreToolUse",
|
|
104
|
+
toolName: ctx.toolCall.name,
|
|
105
|
+
toolArgs: ctx.args,
|
|
106
|
+
filePath,
|
|
107
|
+
workingDir: cwd,
|
|
108
|
+
}, signal);
|
|
109
|
+
if (outcome.blocked) {
|
|
110
|
+
return { block: true, reason: outcome.reason ?? "Blocked by hook." };
|
|
111
|
+
}
|
|
112
|
+
return undefined;
|
|
113
|
+
},
|
|
114
|
+
afterToolCall: async (ctx, signal) => {
|
|
115
|
+
const filePath = ctx.args?.path;
|
|
116
|
+
await hooks.dispatch("PostToolUse", {
|
|
117
|
+
event: "PostToolUse",
|
|
118
|
+
toolName: ctx.toolCall.name,
|
|
119
|
+
toolArgs: ctx.args,
|
|
120
|
+
filePath,
|
|
121
|
+
workingDir: cwd,
|
|
122
|
+
}, signal);
|
|
123
|
+
// After a write/edit tool, run language checkers on the affected file
|
|
124
|
+
// and steer the result into the next turn. Fire-and-forget so the
|
|
125
|
+
// tool result return isn't blocked by a 15s checker run.
|
|
126
|
+
if (filePath && WRITE_TOOL_NAMES.has(ctx.toolCall.name)) {
|
|
127
|
+
const absPath = isAbsolute(filePath) ? filePath : resolve(cwd, filePath);
|
|
128
|
+
diagnostics
|
|
129
|
+
.forFiles([absPath], signal)
|
|
130
|
+
.then((diags) => {
|
|
131
|
+
if (diags.length === 0)
|
|
132
|
+
return;
|
|
133
|
+
const body = formatDiagnostics(diags);
|
|
134
|
+
agentRef?.steer({
|
|
135
|
+
role: "user",
|
|
136
|
+
content: `<system-reminder>\n${body}\n</system-reminder>`,
|
|
137
|
+
timestamp: Date.now(),
|
|
138
|
+
});
|
|
139
|
+
})
|
|
140
|
+
.catch(() => {
|
|
141
|
+
// Diagnostics failures are non-fatal — surface nothing.
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
return undefined;
|
|
145
|
+
},
|
|
146
|
+
});
|
|
147
|
+
// agentRef lets the afterToolCall closure call agent.steer() once the
|
|
148
|
+
// Agent is constructed. JS hoisting makes the assignment safe because
|
|
149
|
+
// afterToolCall fires inside the event loop, well after this assignment.
|
|
150
|
+
const agentRef = agent;
|
|
151
|
+
const subscribe = (listener) => agent.subscribe((event) => {
|
|
152
|
+
listener(event);
|
|
153
|
+
});
|
|
154
|
+
// Persist after every agent_end so a crash mid-session doesn't lose work.
|
|
155
|
+
agent.subscribe((event) => {
|
|
156
|
+
if (event.type !== "agent_end")
|
|
157
|
+
return;
|
|
158
|
+
try {
|
|
159
|
+
const messages = event.messages.length > 0 ? event.messages : (resumed?.messages ?? []);
|
|
160
|
+
if (messages.length === 0)
|
|
161
|
+
return;
|
|
162
|
+
sessions.save({
|
|
163
|
+
modelId: model.id,
|
|
164
|
+
title: resumed?.title ?? null,
|
|
165
|
+
messages,
|
|
166
|
+
usage: resumed?.usage ?? {
|
|
167
|
+
input: 0,
|
|
168
|
+
output: 0,
|
|
169
|
+
cacheRead: 0,
|
|
170
|
+
cacheWrite: 0,
|
|
171
|
+
totalTokens: 0,
|
|
172
|
+
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
|
|
173
|
+
},
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
catch {
|
|
177
|
+
// Persistence is best-effort — don't crash the agent over a write failure.
|
|
178
|
+
}
|
|
179
|
+
});
|
|
180
|
+
void agentRef;
|
|
181
|
+
return {
|
|
182
|
+
agent,
|
|
183
|
+
model,
|
|
184
|
+
source,
|
|
185
|
+
toolContext,
|
|
186
|
+
permissions,
|
|
187
|
+
userQueries,
|
|
188
|
+
planMode,
|
|
189
|
+
memory,
|
|
190
|
+
glue,
|
|
191
|
+
compaction,
|
|
192
|
+
sessions,
|
|
193
|
+
hooks,
|
|
194
|
+
diagnostics,
|
|
195
|
+
subscribe,
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
//# sourceMappingURL=agent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent.js","sourceRoot":"","sources":["../../src/agent/agent.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { getEnvApiKey, getModel } from "@earendil-works/pi-ai";
|
|
2
|
+
import { CredentialsStore } from "../auth/credentials.js";
|
|
3
|
+
/**
|
|
4
|
+
* Provider+model selection, in priority order:
|
|
5
|
+
* 1. Saved OAuth/API credentials (~/.codebase/credentials.json) — if
|
|
6
|
+
* present and not expired, route the chosen model through the
|
|
7
|
+
* codebase.foundation inference proxy so the backend can deduct
|
|
8
|
+
* credits. The model metadata stays the same; only baseUrl + apiKey
|
|
9
|
+
* change.
|
|
10
|
+
* 2. CODEBASE_PROVIDER + CODEBASE_MODEL env (explicit override)
|
|
11
|
+
* 3. First provider in {@link AUTO_DETECT_ORDER} with a usable env key
|
|
12
|
+
* 4. Throw — caller should surface this as an onboarding hint
|
|
13
|
+
*
|
|
14
|
+
* pi-ai's `getEnvApiKey` already handles every quirky case: OAuth-only
|
|
15
|
+
* providers, Vertex ADC, AWS multi-source. We just trust it.
|
|
16
|
+
*/
|
|
17
|
+
const DEFAULT_PROXY_BASE = "https://codebase.foundation/api/cli";
|
|
18
|
+
const AUTO_DETECT_ORDER = [
|
|
19
|
+
"anthropic",
|
|
20
|
+
"openai",
|
|
21
|
+
"groq",
|
|
22
|
+
"google",
|
|
23
|
+
"mistral",
|
|
24
|
+
"deepseek",
|
|
25
|
+
"cerebras",
|
|
26
|
+
"xai",
|
|
27
|
+
"openrouter",
|
|
28
|
+
];
|
|
29
|
+
const DEFAULT_MODELS = {
|
|
30
|
+
anthropic: "claude-sonnet-4-6",
|
|
31
|
+
openai: "gpt-5.1",
|
|
32
|
+
groq: "llama-3.3-70b-versatile",
|
|
33
|
+
google: "gemini-2.5-pro",
|
|
34
|
+
mistral: "mistral-large-latest",
|
|
35
|
+
deepseek: "deepseek-chat",
|
|
36
|
+
cerebras: "llama-3.3-70b",
|
|
37
|
+
xai: "grok-4",
|
|
38
|
+
openrouter: "anthropic/claude-sonnet-4-6",
|
|
39
|
+
};
|
|
40
|
+
export class ConfigError extends Error {
|
|
41
|
+
}
|
|
42
|
+
export function resolveConfig(envOrOpts = process.env) {
|
|
43
|
+
const opts = isProcessEnv(envOrOpts) ? { env: envOrOpts } : envOrOpts;
|
|
44
|
+
const env = opts.env ?? process.env;
|
|
45
|
+
const credentials = opts.credentials ?? new CredentialsStore();
|
|
46
|
+
// 1. OAuth/API credentials → proxy mode (unless explicitly disabled).
|
|
47
|
+
const useProxy = env.CODEBASE_DISABLE_PROXY !== "1";
|
|
48
|
+
if (useProxy) {
|
|
49
|
+
const creds = credentials.load();
|
|
50
|
+
if (creds && !credentials.isExpired(creds)) {
|
|
51
|
+
const proxied = buildProxiedConfig(env, creds.accessToken);
|
|
52
|
+
if (proxied)
|
|
53
|
+
return proxied;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
const explicitProvider = env.CODEBASE_PROVIDER;
|
|
57
|
+
const explicitModel = env.CODEBASE_MODEL;
|
|
58
|
+
if (explicitProvider && explicitModel) {
|
|
59
|
+
const model = getModel(explicitProvider, explicitModel);
|
|
60
|
+
if (!model) {
|
|
61
|
+
throw new ConfigError(`CODEBASE_PROVIDER=${explicitProvider} CODEBASE_MODEL=${explicitModel} not in pi-ai's model registry. ` +
|
|
62
|
+
`Check the spelling, or unset both to auto-detect.`);
|
|
63
|
+
}
|
|
64
|
+
const apiKey = getEnvApiKey(explicitProvider);
|
|
65
|
+
if (!apiKey) {
|
|
66
|
+
throw new ConfigError(`CODEBASE_PROVIDER=${explicitProvider} has no API key in env. Set the appropriate *_API_KEY var.`);
|
|
67
|
+
}
|
|
68
|
+
return { model, apiKey, source: "explicit" };
|
|
69
|
+
}
|
|
70
|
+
for (const provider of AUTO_DETECT_ORDER) {
|
|
71
|
+
const apiKey = getEnvApiKey(provider);
|
|
72
|
+
if (!apiKey)
|
|
73
|
+
continue;
|
|
74
|
+
const modelId = DEFAULT_MODELS[provider];
|
|
75
|
+
if (!modelId)
|
|
76
|
+
continue;
|
|
77
|
+
const model = getModel(provider, modelId);
|
|
78
|
+
if (!model)
|
|
79
|
+
continue;
|
|
80
|
+
return { model, apiKey, source: "auto" };
|
|
81
|
+
}
|
|
82
|
+
throw new ConfigError("No usable LLM provider found. Sign in with `codebase auth login`, paste an API key with " +
|
|
83
|
+
"`codebase auth <key>`, or set one of: ANTHROPIC_API_KEY, OPENAI_API_KEY, GROQ_API_KEY, " +
|
|
84
|
+
"GOOGLE_API_KEY, MISTRAL_API_KEY, DEEPSEEK_API_KEY, CEREBRAS_API_KEY, XAI_API_KEY, OPENROUTER_API_KEY. " +
|
|
85
|
+
"Or set CODEBASE_PROVIDER + CODEBASE_MODEL explicitly.");
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Build a model whose baseUrl points at the codebase.foundation
|
|
89
|
+
* inference proxy. The proxy MUST mimic the chosen provider's wire
|
|
90
|
+
* protocol (Anthropic Messages, OpenAI Responses, etc.) — what we send
|
|
91
|
+
* here is identical to a direct call, the bearer token is the only
|
|
92
|
+
* thing that changes.
|
|
93
|
+
*/
|
|
94
|
+
function buildProxiedConfig(env, accessToken) {
|
|
95
|
+
const explicitProvider = env.CODEBASE_PROVIDER;
|
|
96
|
+
const explicitModel = env.CODEBASE_MODEL;
|
|
97
|
+
const provider = explicitProvider ?? "anthropic";
|
|
98
|
+
const modelId = explicitModel ?? DEFAULT_MODELS[provider];
|
|
99
|
+
if (!modelId)
|
|
100
|
+
return null;
|
|
101
|
+
const baseModel = getModel(provider, modelId);
|
|
102
|
+
if (!baseModel)
|
|
103
|
+
return null;
|
|
104
|
+
const proxyBase = (env.CODEBASE_PROXY_BASE_URL ?? DEFAULT_PROXY_BASE).replace(/\/+$/, "");
|
|
105
|
+
const proxiedModel = { ...baseModel, baseUrl: proxyBase };
|
|
106
|
+
return { model: proxiedModel, apiKey: accessToken, source: "proxy" };
|
|
107
|
+
}
|
|
108
|
+
function isProcessEnv(value) {
|
|
109
|
+
if (!value)
|
|
110
|
+
return true;
|
|
111
|
+
// ResolveConfigOptions has at most env/credentials properties; ProcessEnv has many.
|
|
112
|
+
const keys = Object.keys(value);
|
|
113
|
+
if (keys.length === 0)
|
|
114
|
+
return true;
|
|
115
|
+
return !keys.every((k) => k === "env" || k === "credentials");
|
|
116
|
+
}
|
|
117
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/agent/config.ts"],"names":[],"mappings":"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"}
|