@pentoshi/clai 4.11.18 → 4.11.20
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 +112 -547
- package/dist/agent/runner.js +4 -2
- package/dist/agent/runner.js.map +1 -1
- package/dist/agent/stream-recovery.js +1 -1
- package/dist/agent/turn/loop/request-assembly.js +4 -1
- package/dist/agent/turn/loop/request-assembly.js.map +1 -1
- package/dist/classic/chrome/status-rows.js +10 -2
- package/dist/classic/chrome/status-rows.js.map +1 -1
- package/dist/llm/capability/tool-dialect.js +6 -0
- package/dist/llm/capability/tool-dialect.js.map +1 -1
- package/dist/llm/key-rotation.js +1 -1
- package/dist/llm/key-rotation.js.map +1 -1
- package/dist/llm/routing/key-rotation.js +5 -2
- package/dist/llm/routing/key-rotation.js.map +1 -1
- package/dist/llm/wire/chat-body.js +20 -8
- package/dist/llm/wire/chat-body.js.map +1 -1
- package/dist/tui-v2/components/status/status-line.js +11 -3
- package/dist/tui-v2/components/status/status-line.js.map +1 -1
- package/dist/version.generated.d.ts +2 -2
- package/dist/version.generated.js +2 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,27 +2,27 @@
|
|
|
2
2
|
|
|
3
3
|
> A fast, terminal-native AI agent that runs real tools — built to run on **free API tiers**, stay alive across rate limits with **multi-key + multi-provider switching**, and do serious work: **building, debugging, and scope-based pentesting / bug bounty**.
|
|
4
4
|
|
|
5
|
-
`clai` is an agentic CLI. It doesn't just describe what to do — it edits files, runs shell commands, scans hosts, fetches HTTP evidence, keeps a durable task plan, and verifies its own work before claiming success. It runs in your terminal with three full surfaces — an OpenTUI full-screen console (default on macOS/Linux), a classic Ink UI (default on Windows), and a noninteractive stream renderer for prompts and pipes.
|
|
5
|
+
`clai` is an agentic CLI. It doesn't just describe what to do — it edits files, runs shell commands, scans hosts, fetches HTTP evidence, keeps a durable task plan, and verifies its own work before claiming success. It runs in your terminal with three full surfaces — an OpenTUI full-screen console (default on macOS/Linux), a classic Ink UI (default on Windows), and a noninteractive stream renderer for prompts and pipes. Every interactive surface is a full-screen app sharing the same features, commands, and session state.
|
|
6
6
|
|
|
7
7
|
Two things make it practical for everyday use:
|
|
8
8
|
|
|
9
|
-
- **It's cheap-to-free to run.** A fresh install runs **keyless out of the box** on the built-in Free provider — no signup, no API key. Point it at
|
|
9
|
+
- **It's cheap-to-free to run.** A fresh install runs **keyless out of the box** on the built-in Free provider — no signup, no API key. Point it at DeepSeek, Kimi, GLM, MiniMax, Gemini, NVIDIA NIM, OpenRouter, OpenAI, Anthropic, or run completely offline with local Ollama. Add multiple keys per provider; when one hits a rate limit, it rotates to the next automatically.
|
|
10
10
|
- **It's honest.** Findings need real tool output. Builds get typechecked/run before "done." Compaction and history keep long sessions coherent instead of hallucinating progress.
|
|
11
11
|
|
|
12
12
|
---
|
|
13
13
|
|
|
14
14
|
## Highlights
|
|
15
15
|
|
|
16
|
-
- **Free-tier first.**
|
|
17
|
-
- **Multi-key smart switching.** Up to 10 keys per provider with a *sticky* active key and circular rotation on rate-limit
|
|
18
|
-
- **
|
|
16
|
+
- **Free-tier first.** Built-in **keyless Free** gateway (`free-2/kilo-auto/free`) so a fresh install runs at no cost with zero setup — no API key required.
|
|
17
|
+
- **Multi-key smart switching.** Up to 10 keys per provider with a *sticky* active key and circular rotation on rate-limit, quota, transient, or 5xx errors. Disable any key to skip it without deleting it. Optional cross-provider fallback and a free-only filter.
|
|
18
|
+
- **Broad provider support.** Native support for DeepSeek, Kimi (Moonshot), GLM (Zhipu AI), MiniMax, OpenAI, Anthropic, Google Gemini, Ollama, NVIDIA NIM, OpenRouter, Qwen, and custom OpenAI-compatible endpoints.
|
|
19
19
|
- **Scope-based pentesting.** Opt-in engagement scope with authorized/excluded targets, allowed phases, rate and concurrency ceilings, redirect and DNS-rebinding escape detection, and out-of-scope flagging — designed for authorized pentests and bug-bounty programs.
|
|
20
20
|
- **Real building & debugging.** Scaffolds apps, edits code surgically, installs packages, runs builds/tests, starts dev servers as background jobs, and probes them before reporting success.
|
|
21
21
|
- **Durable plans.** `plan.create` / `task.update` drive a live checklist that survives context compaction and reloads with `/history` — the agent works task-by-task and won't fake completion.
|
|
22
|
-
- **Durable agent sessions.** Interactive sessions run behind
|
|
23
|
-
- **Persistent interactive terminals.** Conversation-owned PTY or pipe sessions keep REPLs such as Python, Metasploit, Meterpreter, database consoles, and debuggers open across model turns.
|
|
22
|
+
- **Durable agent sessions.** Interactive sessions run behind a local broker, so an agent keeps working after `/minimise`, an SSH disconnect, or switching to another history session; `clai --resume <id>` reattaches to the same live UI and output stream.
|
|
23
|
+
- **Persistent interactive terminals.** Conversation-owned PTY or pipe sessions keep REPLs such as Python, Metasploit, Meterpreter, database consoles, and debuggers open across model turns.
|
|
24
24
|
- **Native + text tool calling.** Uses provider-native function calling where available, with a text-fence fallback (`toolCalling: auto|native|text`).
|
|
25
|
-
- **MCP, explicitly controlled.** Discovers local stdio and remote HTTP/SSE servers from project
|
|
25
|
+
- **MCP, explicitly controlled.** Discovers local stdio and remote HTTP/SSE servers from project configs. MCP tools are off by default; `/mcp` inspects and adds servers, and picking one drops an editable `@mcp:<server>` token into your prompt.
|
|
26
26
|
- **Safety gate you control.** Every action is classified safe / confirm / block; deletes always confirm with a preview; destructive patterns are blocked.
|
|
27
27
|
|
|
28
28
|
---
|
|
@@ -58,112 +58,29 @@ cd clai && npm install && npm run build && npm start
|
|
|
58
58
|
|
|
59
59
|
Node.js ≥ 22. Type `clai` in any terminal to start.
|
|
60
60
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
| Environment | Default surface | Explicit alternative |
|
|
64
|
-
|---|---|---|
|
|
65
|
-
| Interactive macOS/Linux terminal at least 60×14 | OpenTUI full-screen console | `clai --classic` for the Ink UI |
|
|
66
|
-
| Interactive Windows terminal | Classic Ink UI | `--ui classic` / `--classic` |
|
|
67
|
-
| stdin or stdout is not a TTY | Noninteractive stream renderer | use a prompt or pipe stdin |
|
|
68
|
-
|
|
69
|
-
**Windows:** the platform-selection code chooses the classic Ink UI before any Bun/OpenTUI
|
|
70
|
-
startup probe. This repository's macOS validation does not claim Windows Terminal,
|
|
71
|
-
PowerShell, cmd.exe/conhost, VS Code terminal, ConPTY, or Windows-binary runtime evidence;
|
|
72
|
-
those target-host checks remain release gates. Use `clai --classic` explicitly when you want
|
|
73
|
-
the same selection on any platform.
|
|
74
|
-
|
|
75
|
-
**Linux — terminal recommendations for full mouse & hover support:**
|
|
76
|
-
|
|
77
|
-
The full-screen TUI uses mouse tracking and hover events via OpenTUI's Zig FFI renderer. Not all Linux terminal emulators report these correctly. If you see missing hover highlights, broken scroll, or no mouse response:
|
|
78
|
-
|
|
79
|
-
| Terminal | Mouse/Hover | Notes |
|
|
80
|
-
|----------|-------------|-------|
|
|
81
|
-
| **Kitty** | ✅ Full | Recommended — fastest GPU-rendered terminal, full mouse protocol support |
|
|
82
|
-
| **Alacritty** | ✅ Full | GPU-accelerated, excellent mouse support |
|
|
83
|
-
| **WezTerm** | ✅ Full | Cross-platform, great defaults |
|
|
84
|
-
| **iTerm2** (macOS) | ✅ Full | Native macOS, full mouse + hover |
|
|
85
|
-
| **macOS Terminal** | ✅ Full | Works out of the box |
|
|
86
|
-
| **GNOME Terminal** | ⚠️ Partial | Mouse clicks work; hover/SGR mouse mode may be limited |
|
|
87
|
-
| **Konsole** | ⚠️ Partial | Some hover events may not report |
|
|
88
|
-
| **xterm** | ⚠️ Partial | Needs `xterm -xrm 'XTerm*allowMouseOps: true'` |
|
|
89
|
-
| **Linux TTY** (bare `/dev/tty`) | ❌ None | No mouse support; use `clai --classic` |
|
|
90
|
-
| **tmux / screen** | ⚠️ Varies | Add `set -g mouse on` to `~/.tmux.conf`; passthrough depends on the outer terminal |
|
|
91
|
-
|
|
92
|
-
> **Tip:** For the best experience on Linux, use **Kitty**, **Alacritty**, or **WezTerm**. These support SGR extended mouse reporting, which is what OpenTUI requires for hover, click, and scroll events. If your terminal doesn't support hover, clai still works — you just won't see hover highlights on buttons and links.
|
|
93
|
-
>
|
|
94
|
-
> For tmux users: `set -g mouse on` enables mouse passthrough, but hover quality depends on the outer terminal emulator.
|
|
61
|
+
> **Tip for Linux users:** For the best mouse and hover support in the full-screen TUI, modern GPU-rendered terminals like **Kitty**, **Alacritty**, or **WezTerm** are recommended. On macOS, **iTerm2** and the default Terminal work out of the box.
|
|
95
62
|
|
|
96
63
|
---
|
|
97
64
|
|
|
98
|
-
## Fast downloads (Cloudflare R2 mirror)
|
|
99
|
-
|
|
100
|
-
Release binaries are mirrored to a **Cloudflare R2** bucket served through Cloudflare's global CDN — significantly faster than GitHub's release hosting in most regions, and free for this project's traffic (R2 has **zero egress fees**).
|
|
101
|
-
|
|
102
|
-
Mirror layout at `https://downloads.clai.aniketpandey.website`:
|
|
103
|
-
|
|
104
|
-
| Path | Contents |
|
|
105
|
-
|---|---|
|
|
106
|
-
| `/vX.Y.Z/` | Binaries + `.sha256` sidecars for release vX.Y.Z (latest release only — see retention) |
|
|
107
|
-
| `/latest/` | Same files, refreshed on every release |
|
|
108
|
-
| `/install/` | `install.sh` / `install.ps1` used by the one-liners above |
|
|
109
|
-
| `/version.json` | Latest released version (update-check fallback) |
|
|
110
|
-
|
|
111
|
-
**Retention.** R2's free tier covers 10 GB and a single release is roughly 650 MB across six
|
|
112
|
-
platforms, so the mirror keeps only the newest release: after the new binaries are uploaded
|
|
113
|
-
*and* re-verified byte-for-byte through the public URL, superseded `vX.Y.Z/` prefixes are
|
|
114
|
-
purged. `/latest/`, `/install/` and `/version.json` are always retained. Set the repo variable
|
|
115
|
-
`R2_KEEP_RELEASES` to keep more than one version (default `1`). Pruning never runs unless the
|
|
116
|
-
new release verified successfully, and a failed purge only warns — it can never fail a release.
|
|
117
|
-
GitHub Releases keeps every version permanently, so older downloads still work through the
|
|
118
|
-
automatic fallback; only the CDN acceleration is lost for them.
|
|
119
|
-
|
|
120
|
-
**Security model:** installers and `clai update` try the R2 mirror first for speed and fall back to GitHub Releases automatically. The SHA256 checksum is fetched from GitHub Releases (falling back to the mirror) and verified locally before anything is installed — the trust anchor stays with GitHub, so a bad mirror can only slow you down, never feed you tampered bytes. `CLAI_SKIP_CHECKSUM=1` still bypasses verification, at your own risk. If the mirror is unreachable but raw.githubusercontent.com works, grab the installer from `https://raw.githubusercontent.com/pentoshi007/clai/main/install/` instead — it makes the same mirror-first/fallback choices when it runs.
|
|
121
|
-
|
|
122
|
-
User knobs:
|
|
123
|
-
|
|
124
|
-
```sh
|
|
125
|
-
CLAI_DOWNLOAD_BASE=https://your-mirror.example
|
|
126
|
-
CLAI_NO_MIRROR=1
|
|
127
|
-
```
|
|
128
|
-
|
|
129
|
-
### Maintainer setup (one-time, ~10 minutes)
|
|
130
|
-
|
|
131
|
-
1. **Create the bucket.** Cloudflare dashboard → R2 → Create bucket, e.g. `clai-releases`. Any location hint works.
|
|
132
|
-
2. **Make it publicly readable.** Bucket → Settings → Public access:
|
|
133
|
-
- **Option A — `r2.dev` (zero DNS config):** enable the managed "r2.dev URL" → you get `https://pub-<hash>.r2.dev`.
|
|
134
|
-
- **Option B — custom domain (the default everywhere in this repo):** add `downloads.clai.aniketpandey.website` as a custom domain (requires the zone's DNS on Cloudflare). Free SSL, and eligible for the edge cache once the cache rule in step 7 is in place.
|
|
135
|
-
If you end up on a different hostname, update `DEFAULT_MIRROR_BASE` in `src/commands/update-install.ts`, the default base in `install/install.sh` and `install/install.ps1`, and the URLs in `manifests/` — or export `CLAI_DOWNLOAD_BASE` until a release ships the change.
|
|
136
|
-
3. **Create an API token.** R2 → Manage R2 API Tokens → Create API token: permission **Object Read & Write**, scoped to the `clai-releases` bucket only. Keep the **Access Key ID**, **Secret Access Key**, and the **Account ID** shown on the token page.
|
|
137
|
-
4. **Add repo secrets** (GitHub repo → Settings → Secrets and variables → Actions → Secrets): `R2_ACCOUNT_ID`, `R2_ACCESS_KEY_ID`, `R2_SECRET_ACCESS_KEY`, `R2_BUCKET_NAME`.
|
|
138
|
-
5. **Add repo variable** (Variables tab): `R2_PUBLIC_URL` = your public base URL, e.g. `https://downloads.clai.aniketpandey.website`, no trailing slash.
|
|
139
|
-
6. **Done.** On every `v*.*.*` tag, the `publish-r2` job in `.github/workflows/release.yml` uploads binaries + checksums to `/vX.Y.Z/` and `/latest/`, refreshes `/install/` and `/version.json`, re-downloads every asset through the public URL to re-verify its SHA256 against the sidecars, then purges superseded `vX.Y.Z/` prefixes. Missing secrets → the job skips without failing the release; missing `R2_PUBLIC_URL` → the public-URL verification is skipped and, because nothing was verified, pruning is skipped too. The `/version.json` write is advisory: if the token cannot write bucket-root objects the job warns and mirrors the manifest to `/latest/version.json` instead, since update checks already fall back to GitHub Releases.
|
|
140
|
-
|
|
141
|
-
7. **Turn on edge caching (one cache rule).** Release binaries have no file extension, and Cloudflare's default cache only covers known static extensions — so without a rule every download is served from R2 origin and `cf-cache-status` stays `DYNAMIC`. Add a Cache Rule (dashboard → Caching → Cache Rules) matching `Hostname eq downloads.clai.aniketpandey.website` with **Cache eligibility: Eligible for cache** and **Use origin cache-control: on**. The upload job already stamps the right `Cache-Control` on every object — `public, max-age=31536000, immutable` for `/vX.Y.Z/` (content-addressed by version, so it can never go stale), `max-age=300` for `/latest/` and `/install/`, and `max-age=60` for `/version.json`. Verify with `curl -sI <url> | grep cf-cache-status`: the second request for the same asset should report `HIT`.
|
|
142
|
-
|
|
143
|
-
**Cost:** the R2 free tier covers 10 GB-months of storage, 1M Class A and 10M Class B operations per month, and egress is always free, so this stays $0 at clai's scale. With the cache rule in place repeat downloads are served from the edge and never reach R2, which also keeps Class B operations near zero.
|
|
144
|
-
|
|
145
|
-
---
|
|
146
|
-
|
|
147
|
-
|
|
148
65
|
## Quick start
|
|
149
66
|
|
|
150
|
-
Out of the box, clai runs **keyless** on the built-in Free provider — no signup, no API key:
|
|
67
|
+
Out of the box, `clai` runs **keyless** on the built-in Free provider — no signup, no API key:
|
|
151
68
|
|
|
152
69
|
```sh
|
|
153
70
|
clai # launch the full-screen agent console (already on the free provider)
|
|
154
71
|
```
|
|
155
72
|
|
|
156
|
-
Prefer a different provider?
|
|
73
|
+
Prefer a different provider? Set your key and start:
|
|
157
74
|
|
|
158
75
|
```sh
|
|
159
|
-
# Add
|
|
160
|
-
clai set
|
|
161
|
-
clai use
|
|
76
|
+
# Add an API key (DeepSeek shown; Gemini, OpenAI, Anthropic, Kimi, etc. work the same)
|
|
77
|
+
clai set deepseek sk-your_key_here
|
|
78
|
+
clai use deepseek
|
|
162
79
|
|
|
163
80
|
# Launch the full-screen agent console
|
|
164
81
|
clai
|
|
165
82
|
|
|
166
|
-
# Or one-shot from the shell
|
|
83
|
+
# Or one-shot directly from the shell
|
|
167
84
|
clai "explain what this repo does and find the entrypoint"
|
|
168
85
|
clai --mode agent "add a /health endpoint to the Express app and run the tests"
|
|
169
86
|
```
|
|
@@ -175,237 +92,56 @@ clai set ollama --url http://localhost:11434
|
|
|
175
92
|
clai use ollama
|
|
176
93
|
```
|
|
177
94
|
|
|
178
|
-
Want a frontier open model on your own hardware budget? Deploy **Kimi K3** to a Modal endpoint and run it on Modal's **$30/month of free compute credit** — see [Modal](#modal--run-kimi-k3-on-your-own-endpoint-on-30month-of-free-credit).
|
|
179
|
-
|
|
180
95
|
---
|
|
181
96
|
|
|
182
|
-
##
|
|
183
|
-
|
|
184
|
-
This is the core of clai's design: assemble capacity from free tiers, then survive rate limits automatically.
|
|
185
|
-
|
|
186
|
-
### Supported providers
|
|
187
|
-
|
|
188
|
-
| Provider | Default model | Tier | Env var |
|
|
189
|
-
|----------|---------------|------|---------|
|
|
190
|
-
| Free (keyless) | `free-2/kilo-auto/free` | Free · keyless | — (no key needed) |
|
|
191
|
-
| NVIDIA NIM | `openai/gpt-oss-20b` | Free | `NVIDIA_API_KEY` |
|
|
192
|
-
| Google Gemini | `gemini-3.5-flash` | Free | `GEMINI_API_KEY` |
|
|
193
|
-
| OpenRouter | `meta-llama/llama-3.3-70b-instruct:free` | Free | `OPENROUTER_API_KEY` |
|
|
194
|
-
| Bynara | `mimo-v2.5-free` | Free | `BYNARA_API_KEY` |
|
|
195
|
-
| Ollama | `llama3.1:8b` | Local / free | `OLLAMA_HOST` |
|
|
196
|
-
| OpenAI | `gpt-5.4-mini` | Paid | `OPENAI_API_KEY` |
|
|
197
|
-
| Anthropic | `claude-3-5-haiku-latest` | Paid | `ANTHROPIC_API_KEY` |
|
|
198
|
-
| AgentRouter | `claude-opus-4-6` | Paid | `AGENTROUTER_API_KEY` |
|
|
199
|
-
| AWS Mantle | `anthropic.claude-haiku-4-5` | Paid | `ANTHROPIC_API_KEY` |
|
|
200
|
-
| Qwen Cloud | `qwen3.7-plus` | Paid (DashScope) | `DASHSCOPE_API_KEY` |
|
|
201
|
-
| Modal | `moonshotai/Kimi-K3` | Usage-based ($30/mo credit) | `MODAL_PROXY_TOKEN_ID` + `MODAL_PROXY_TOKEN_SECRET` |
|
|
202
|
-
| Lightning AI | `openai/gpt-5` | Per token (40M free to start) | `LIGHTNING_API_KEY` |
|
|
203
|
-
| TokenRouter | `moonshotai/kimi-k3` | Per token (prepaid) | `TOKENROUTER_API_KEY` |
|
|
204
|
-
| Meta (Muse Spark) | `muse-spark-1.2` | Paid (per token) | `MODEL_API_KEY` |
|
|
205
|
-
| Fireworks | `accounts/fireworks/models/kimi-k2p6` | Paid (per token) | `FIREWORKS_API_KEY` |
|
|
206
|
-
| Hetzner | `Qwen/Qwen3.6-35B-A3B-FP8` | Free (experiment — no billing yet) | `HETZNER_API_KEY` |
|
|
207
|
-
| OrcaRouter | `openai/gpt-4o-mini` | Paid (per token, zero markup) | `ORCAROUTER_API_KEY` |
|
|
208
|
-
| Merge Gateway | `openai/gpt-5.2` | Paid (per token, free tier budget) | `MERGE_GATEWAY_API_KEY` |
|
|
209
|
-
|
|
210
|
-
Several "paid" providers also expose limited free allowances — the tier label reflects what the default keys usually buy you. Flip `freeOnly` off to include paid providers in fallback.
|
|
211
|
-
|
|
212
|
-
#### Free — keyless, zero setup
|
|
213
|
-
|
|
214
|
-
clai's default provider needs **no account, no API key, and no config**. It bundles **two keyless gateways** under one provider, namespaced by source so overlapping model names never collide: `free-1/…` ids come from the primary gateway and `free-2/…` ids from the [Kilo gateway](https://api.kilo.ai/api/gateway). Both serve rotating catalogs of free OpenAI-compatible models — `free-2/kilo-auto/free` (default), `free-1/mimo-v2.5-free`, `free-1/hy3-free`, `free-1/x-preview-f-free`, `free-2/stepfun/step-3.7-flash:free`, `free-2/nvidia/nemotron-3-ultra-550b-a55b:free` — with SSE streaming, native tool calling, `/effort` reasoning levels, and `reasoning_content` thinking folded into the normal `/think` block.
|
|
215
|
-
|
|
216
|
-
```sh
|
|
217
|
-
clai # already on free — nothing to set up
|
|
218
|
-
/model # live catalogs from both gateways, free-1/… + free-2/… (cached 1h)
|
|
219
|
-
```
|
|
220
|
-
|
|
221
|
-
- **Keyless by design.** Requests go out with no `Authorization` header; `/model` lists only the keyless models from each gateway, so premium ids stay hidden until you add a key.
|
|
222
|
-
- **Two sources, one provider.** Pick `free-1/…` or `free-2/…` in `/model`; a bare id with no prefix routes to `free-1`. If one gateway is rate limited, switching to the other is one `/model` pick away.
|
|
223
|
-
- **Optional key upgrades you.** `clai set free <key>` (or `FREE_API_KEY`) unlocks premium models on your account. Premium ids without a key fail fast with a clear 402-style message instead of a confusing upstream error.
|
|
224
|
-
- **Best-effort tier.** The free sets rotate upstream and are capacity-constrained / rate limited — if a request fails, retry once. For dependable daily use, add a key for any other provider (`clai set <provider> <key>`, then `clai use <provider>`).
|
|
225
|
-
|
|
226
|
-
#### Modal — run Kimi K3 on your own endpoint, on $30/month of free credit
|
|
97
|
+
## Providers & Key Management
|
|
227
98
|
|
|
228
|
-
|
|
99
|
+
### Supported Providers
|
|
229
100
|
|
|
230
|
-
|
|
101
|
+
| Provider | Default Model | Tier | Environment Variable |
|
|
102
|
+
|----------|---------------|------|----------------------|
|
|
103
|
+
| **Free (keyless)** | `free-2/kilo-auto/free` | Free · Keyless | — (no key needed) |
|
|
104
|
+
| **DeepSeek** | `deepseek-chat` | Paid / Usage | `DEEPSEEK_API_KEY` |
|
|
105
|
+
| **Kimi (Moonshot)** | `moonshot-v1-auto` | Paid / Usage | `KIMI_API_KEY` / `MOONSHOT_API_KEY` |
|
|
106
|
+
| **GLM (Zhipu AI)** | `glm-4-flash` | Free tier / Paid | `GLM_API_KEY` / `ZHIPU_API_KEY` |
|
|
107
|
+
| **MiniMax** | `MiniMax-Text-01` | Paid / Usage | `MINIMAX_API_KEY` |
|
|
108
|
+
| **Google Gemini** | `gemini-2.5-flash` | Free tier / Paid | `GEMINI_API_KEY` |
|
|
109
|
+
| **NVIDIA NIM** | `openai/gpt-oss-20b` | Free tier | `NVIDIA_API_KEY` |
|
|
110
|
+
| **OpenRouter** | `meta-llama/llama-3.3-70b-instruct:free` | Free / Paid | `OPENROUTER_API_KEY` |
|
|
111
|
+
| **Ollama** | `llama3.1:8b` | Local / Free | `OLLAMA_HOST` |
|
|
112
|
+
| **OpenAI** | `gpt-5.4-mini` | Paid | `OPENAI_API_KEY` |
|
|
113
|
+
| **Anthropic** | `claude-3-5-haiku-latest` | Paid | `ANTHROPIC_API_KEY` |
|
|
114
|
+
| **Qwen Cloud** | `qwen3.7-plus` | Paid (DashScope) | `DASHSCOPE_API_KEY` |
|
|
115
|
+
| **Bynara** | `mimo-v2.5-free` | Free | `BYNARA_API_KEY` |
|
|
116
|
+
| **Hetzner** | `Qwen/Qwen3.6-35B-A3B-FP8` | Free (experiment) | `HETZNER_API_KEY` |
|
|
231
117
|
|
|
232
|
-
|
|
233
|
-
pip install modal && modal setup # once
|
|
234
|
-
modal endpoint create --model moonshotai/Kimi-K3 --name kimi-k3 # prints an id + dashboard link
|
|
235
|
-
modal endpoint list # copy the endpoint URL from here
|
|
236
|
-
modal workspace proxy-tokens create # wk-… id + ws-… secret (shown once)
|
|
237
|
-
|
|
238
|
-
clai set modal --url <endpoint-url> # e.g. https://ws--ep-kimi-k3-server.us-west.modal.direct
|
|
239
|
-
clai set modal wk-yourTokenId:ws-yourTokenSecret
|
|
240
|
-
clai use modal # model defaults to moonshotai/Kimi-K3
|
|
241
|
-
```
|
|
118
|
+
Model lists for all providers are fetched dynamically from their respective APIs. You can switch models anytime using `/model` or `clai model <name>`.
|
|
242
119
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
Endpoints and token pairs are both multi-entry lists with a sticky active choice, up to 10 each:
|
|
120
|
+
### Manage Keys
|
|
246
121
|
|
|
247
122
|
```sh
|
|
248
|
-
clai set
|
|
249
|
-
clai set
|
|
250
|
-
clai unset modal --url # clear the URLs, keep the token pairs
|
|
251
|
-
clai keys # every URL listed, ★ marks the active one
|
|
252
|
-
```
|
|
253
|
-
|
|
254
|
-
Token pairs rotate on failure like any other provider's keys (the pair is stored as one `id:secret` string). Endpoints fail over alongside them: on a rate limit, workspace/auth mismatch, quota error, or 5xx, clai tries the next stored endpoint with the next key, and the ★ active endpoint sticks to the one that worked, so the next run starts on the healthy URL. `MODAL_BASE_URL` overrides the stored list entirely.
|
|
255
|
-
|
|
256
|
-
From inside the console, `/provider modal` walks the same setup in two prompts — endpoint URL first (shown in full, since it isn't a secret), then the token pair — and leaves the active provider untouched if you cancel.
|
|
257
|
-
|
|
258
|
-
Sticky sessions are on by default — clai sends a stable `Modal-Session-ID` for each conversation, with separate IDs for each subagent and auxiliary request stream. `MODAL_SESSION_ID` optionally seeds those IDs; it does not collapse active agents onto one shared ID. Standalone requests without a conversation use the configured ID directly, or a generated process-local ID. Sticky routing helps preserve warm caches, but does not guarantee a cache hit. The first request after idle still pays container start-up, so clai allows up to 3 minutes for the first token.
|
|
259
|
-
|
|
260
|
-
`/info modal` prints the whole thing as a walkthrough: numbered setup steps, which credentials go where, the plan limits (Starter also caps you at 3 seats, 100 containers and 10 GPUs of concurrency), and a troubleshooting table.
|
|
261
|
-
|
|
262
|
-
#### Lightning AI (one key, many vendors)
|
|
263
|
-
|
|
264
|
-
[Lightning AI Model APIs](https://lightning.ai/docs/platform/inference/model-apis) are an OpenAI-compatible gateway in front of OpenAI, Anthropic, Google and Lightning-hosted open models — one key, billed per token, with **up to 40 million free tokens to start**. Model ids are vendor-namespaced.
|
|
265
|
-
|
|
266
|
-
```sh
|
|
267
|
-
clai set lightning <your-api-key> # key: lightning.ai → Model APIs → show API key
|
|
268
|
-
clai use lightning
|
|
269
|
-
/model openai/gpt-5 # or anthropic/claude-opus-4-8, google/gemini-3.5-flash,
|
|
270
|
-
# lightning-ai/gpt-oss-120b (cheapest open weights)
|
|
271
|
-
```
|
|
272
|
-
|
|
273
|
-
`/model` reads the gateway's live catalog (41 ids at last check) and dedupes it. Keys are multi-key with rotation like everywhere else. The base URL defaults to the shared gateway but is overridable the same way as Modal's — point it at a private Lightning Inference deployment with `clai set lightning --url <url>`, or `LIGHTNING_BASE_URL`. Costs vary by orders of magnitude across the catalog, so check `/info lightning` before long agent runs.
|
|
274
|
-
|
|
275
|
-
#### TokenRouter (frontier open models, one key)
|
|
276
|
-
|
|
277
|
-
[TokenRouter](https://docs.tokenrouter.me) is an OpenAI-compatible gateway to Kimi, DeepSeek, Qwen, GLM, GPT-OSS and MiniMax — long-context open models aimed at agentic coding, billed per token from a prepaid balance.
|
|
278
|
-
|
|
279
|
-
```sh
|
|
280
|
-
clai set tokenrouter sk-your-key # key: your account → API Keys
|
|
281
|
-
clai use tokenrouter # model defaults to moonshotai/kimi-k3
|
|
282
|
-
/model deepseek/deepseek-v4-pro # 1M context · or moonshotai/kimi-k2.7-code, z-ai/glm-5.1, MiniMax-M3
|
|
283
|
-
```
|
|
284
|
-
|
|
285
|
-
Model ids are vendor-namespaced (`moonshotai/kimi-k2.6`, `deepseek/deepseek-v4-pro`, `qwen/qwen3.7-plus`); the old short ids (`kimi-k2p6`, `glm-5p1`, …) are still accepted and silently redirected to the current namespaced id. `/model` reads the live `/models` list, which is filtered to the channels your key can reach. clai carries the real per-model context windows — 1M for DeepSeek V4, 512K for MiniMax M3, 256K for Kimi/Qwen, 200K for GLM — so the context meter and auto-compaction are accurate instead of guessing 128K. Reasoning arrives as `reasoning_content` and is folded into the normal thinking block, so `/think` and `/effort` work. Base URL defaults to `https://api.tokenrouter.com/v1` and is overridable with `clai set tokenrouter --url <url>` or `TOKENROUTER_BASE_URL` if your account uses a different host.
|
|
286
|
-
|
|
287
|
-
#### Fireworks and Hetzner (open-model inference)
|
|
288
|
-
|
|
289
|
-
[Fireworks](https://fireworks.ai) is a per-token inference gateway for open models — Kimi, DeepSeek, GLM, Qwen, GPT-OSS, Llama — with SSE streaming and native tool calling.
|
|
290
|
-
|
|
291
|
-
```sh
|
|
292
|
-
clai set fireworks fw_your_key # key: fireworks.ai → API keys
|
|
293
|
-
clai use fireworks # model defaults to accounts/fireworks/models/kimi-k2p6
|
|
294
|
-
```
|
|
295
|
-
|
|
296
|
-
[Hetzner Inference](https://docs.hetzner.com/general/company-and-policy/experiments/inference/) is Hetzner's OpenAI-compatible experiment API serving open-weight models (Qwen3.6-35B with vision, 262K context) from EU servers. It is free while experimental — there is no billing yet — with fair-use per-key rate limits and no SLA or production guarantee.
|
|
297
|
-
|
|
298
|
-
```sh
|
|
299
|
-
clai set hetzner your-token # token: experiments.hetzner.com → Create API Token
|
|
300
|
-
clai use hetzner # model defaults to Qwen/Qwen3.6-35B-A3B-FP8
|
|
301
|
-
```
|
|
302
|
-
|
|
303
|
-
Both fetch the live model catalog for `/model` (cached 1h) and rotate keys like every other provider.
|
|
304
|
-
|
|
305
|
-
#### OrcaRouter (one key, eleven upstreams, zero markup)
|
|
306
|
-
|
|
307
|
-
[OrcaRouter](https://docs.orcarouter.ai) is an OpenAI-compatible gateway that routes OpenAI, Anthropic, Google Gemini, DeepSeek, xAI Grok, Qwen, Kimi, MiniMax, Z.ai GLM and more behind one key — billed at each provider's published price with no token markup. Model ids are vendor-prefixed (`openai/gpt-4o-mini`, `anthropic/claude-sonnet-4.6`, `google/gemini-2.5-flash`, `deepseek/deepseek-reasoner`, …), and `orcarouter/auto` picks the cheapest model that fits the request.
|
|
308
|
-
|
|
309
|
-
```sh
|
|
310
|
-
clai set orcarouter sk-your-key # key: orcarouter.ai/console (starts with sk-)
|
|
311
|
-
clai use orcarouter # model defaults to openai/gpt-4o-mini
|
|
312
|
-
/model anthropic/claude-sonnet-4.6 # or any id from the live /models catalog
|
|
313
|
-
```
|
|
314
|
-
|
|
315
|
-
Streaming, native tool calling, structured outputs (`response_format`), vision via `image_url` and prompt caching all work. Reasoning uses one unified `reasoning_effort` knob (low/medium/high, plus minimal/max on some models) that the gateway translates to each upstream's native shape — `/think` and `/effort` map onto it, and thinking arrives as `reasoning_content` in the usual thinking block. `/model` reads the live catalog (cached 1h), filtered to Chat-Completions-reachable models so image/video/tts ids stay out of the picker. Keys are multi-key with rotation like everywhere else; env var is `ORCAROUTER_API_KEY`.
|
|
316
|
-
|
|
317
|
-
#### Merge Gateway (one key, many vendors, OpenAI-compatible)
|
|
318
|
-
|
|
319
|
-
[Merge Gateway](https://gateway.merge.dev) fronts OpenAI, Anthropic, Google and other
|
|
320
|
-
upstreams behind a single key. It exposes two surfaces: its own Responses-style API at
|
|
321
|
-
`/v1` and a drop-in OpenAI-compatible surface at `/v1/openai`. clai drives the
|
|
322
|
-
OpenAI-compatible surface, so streaming, native tool calling, prompt caching, reasoning
|
|
323
|
-
effort, multi-key rotation and cross-provider fallback all behave exactly as they do for
|
|
324
|
-
every other OpenAI-compatible provider.
|
|
325
|
-
|
|
326
|
-
```sh
|
|
327
|
-
clai set merge-gateway mg_your-key # key: https://gateway.merge.dev (starts with mg_)
|
|
328
|
-
clai use merge-gateway # model defaults to openai/gpt-5.2
|
|
329
|
-
/model anthropic/claude-sonnet-4-6 # or any id from the live /models catalog
|
|
330
|
-
```
|
|
331
|
-
|
|
332
|
-
Model ids are vendor-prefixed (`openai/gpt-5.2`, `anthropic/claude-sonnet-4-6`,
|
|
333
|
-
`google/gemini-3.5-flash`, `deepseek/deepseek-reasoner`). `/model` reads the live catalog
|
|
334
|
-
(cached 1h) filtered to ids reachable over Chat Completions, so embedding, image and audio
|
|
335
|
-
entries stay out of the picker; if the catalog cannot be fetched, a documented offline
|
|
336
|
-
subset is shown. Reasoning uses one `reasoning_effort` knob (low/medium/high) that the
|
|
337
|
-
gateway translates per upstream, and thinking arrives as `reasoning_content` in the usual
|
|
338
|
-
`/think` block. Requests carry both `Authorization: Bearer` and `X-API-Key`, matching the
|
|
339
|
-
two shapes the gateway accepts. The free tier has a budget: once exhausted the gateway
|
|
340
|
-
answers `402`, which clai treats as a quota error and rotates to the next key or provider.
|
|
341
|
-
Aliases: `merge-gateway`, `mergegateway`, `merge`, `mg`. Env var `MERGE_GATEWAY_API_KEY`.
|
|
342
|
-
`/info merge-gateway` prints the full walkthrough.
|
|
343
|
-
|
|
344
|
-
#### Experiential Labs (one key, every vendor, OpenAI-compatible)
|
|
345
|
-
|
|
346
|
-
[Experiential Labs](https://platform.experientiallabs.ai) fronts hosted providers,
|
|
347
|
-
your own provider keys (BYOK) and platform-funded credits behind a single key. Every
|
|
348
|
-
model is a slug that resolves through a provider waterfall with automatic failover, and
|
|
349
|
-
the gateway is a drop-in OpenAI-compatible endpoint — streaming, native tool calling,
|
|
350
|
-
prompt caching and reasoning effort all behave exactly as they do for every other
|
|
351
|
-
OpenAI-compatible provider.
|
|
352
|
-
|
|
353
|
-
```sh
|
|
354
|
-
clai set explabs xpl_your-key # key: https://platform.experientiallabs.ai/settings/api-keys (starts with xpl_)
|
|
355
|
-
clai use explabs # model defaults to claude-fable-5.1
|
|
356
|
-
/model gpt-5.6-sol # or any slug from the live catalog
|
|
357
|
-
```
|
|
358
|
-
|
|
359
|
-
`/model` lists the slugs your key can call (from `/v1/models`), enriched with catalog
|
|
360
|
-
facts from the public `/api/models` (context window, vision, per-model reasoning
|
|
361
|
-
efforts) and cached for an hour; image/embedding/batch slugs stay out of the picker and
|
|
362
|
-
a documented offline subset is shown when the gateway is unreachable. Reasoning uses one
|
|
363
|
-
`reasoning_effort` knob (low/medium/high/xhigh/max) that passes through when the route
|
|
364
|
-
supports it and snaps to the nearest supported level otherwise, so `/think` and `/effort`
|
|
365
|
-
work across every vendor. Keys are multi-key with rotation like everywhere else; env var
|
|
366
|
-
is `EXPLABS_API_KEY`. Aliases: `explabs`, `experiential`, `experientiallabs`,
|
|
367
|
-
`experiential-labs`, `exp`. `/info explabs` prints the full walkthrough.
|
|
368
|
-
|
|
369
|
-
### Manage keys
|
|
370
|
-
|
|
371
|
-
```sh
|
|
372
|
-
clai set nvidia nvapi-first_key # store a key (appends if one exists)
|
|
373
|
-
clai set nvidia nvapi-second_key # add another key for the same provider
|
|
123
|
+
clai set deepseek sk-first_key # store a key
|
|
124
|
+
clai set deepseek sk-second_key # add another key for multi-key rotation
|
|
374
125
|
clai set gemini --from-env GEMINI_API_KEY
|
|
375
|
-
echo "
|
|
126
|
+
echo "sk-..." | clai set deepseek --stdin
|
|
376
127
|
clai set ollama --url http://localhost:11434
|
|
377
|
-
clai
|
|
378
|
-
clai
|
|
379
|
-
clai
|
|
380
|
-
clai
|
|
381
|
-
clai set fireworks fw_your_key # Fireworks
|
|
382
|
-
clai set hetzner your-token # Hetzner Inference (experiments.hetzner.com)
|
|
383
|
-
clai set orcarouter sk-your-key # OrcaRouter (orcarouter.ai/console)
|
|
384
|
-
clai set merge-gateway mg_your-key # Merge Gateway (gateway.merge.dev)
|
|
385
|
-
clai set explabs xpl_your-key # Experiential Labs (platform.experientiallabs.ai)
|
|
386
|
-
clai set free <key> # optional: unlock premium models (free is keyless by default)
|
|
387
|
-
clai unset modal --url # drop stored endpoint URLs, keep the keys
|
|
388
|
-
clai keys # providers + masked keys (★ active) + endpoint URLs
|
|
389
|
-
clai use nvidia # set active provider
|
|
390
|
-
clai provider # interactive provider/model picker
|
|
391
|
-
clai unset nvidia # remove ALL keys for a provider
|
|
128
|
+
clai keys # list providers with masked keys (★ active)
|
|
129
|
+
clai use deepseek # set active provider
|
|
130
|
+
clai provider # interactive provider/model selector
|
|
131
|
+
clai unset deepseek # remove keys for a provider
|
|
392
132
|
```
|
|
393
133
|
|
|
394
|
-
In the console
|
|
395
|
-
|
|
396
|
-
|
|
134
|
+
In the interactive console:
|
|
135
|
+
- **`/set`** opens the multi-row key editor. Add keys (`+`), set the active key (★), or disable a key (`○`) without deleting it.
|
|
136
|
+
- **`/keys`** displays configured keys (masked) and active status.
|
|
137
|
+
- **`/provider`** and **`/model`** open interactive pickers for switching providers and models on the fly.
|
|
397
138
|
|
|
398
|
-
|
|
399
|
-
- **Disable without deleting** — toggle any key or endpoint row disabled in the `/set` editor and rotation skips it until you re-enable it.
|
|
400
|
-
- **What triggers a switch** — HTTP 429 (rate limit), 401/403 (auth), 402 / quota / billing text, transient network errors, 500–504, and empty completions. Auth and quota errors switch **immediately** (no backoff wait); rate limits back off briefly first.
|
|
401
|
-
- **Cross-provider fallback** *(opt-in)* — `/fallback on` lets clai try other configured providers after the active one is exhausted (only when running a provider's default model).
|
|
402
|
-
- **Free-only mode** *(opt-in)* — `/freeonly on` excludes paid-cloud providers from the fallback chain, so you never accidentally spend.
|
|
403
|
-
- **Quiet status** — a single non-stacking status line shows what happened, e.g. `switching nvidia key [2/4] …ab12 (rate limited)`. Keys are always masked to the last 4 chars.
|
|
139
|
+
### Smart Switching & Resilience
|
|
404
140
|
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
141
|
+
- **Multi-key rotation** — Store up to **10 keys per provider**. The last key that worked is *sticky*. On encountering a rate limit (HTTP 429), quota limit, auth error, or 5xx server error, `clai` automatically rotates to the next available key.
|
|
142
|
+
- **Disable without deleting** — Toggle any key disabled in the `/set` editor; rotation skips it until you re-enable it.
|
|
143
|
+
- **Cross-provider fallback** *(opt-in)* — `/fallback on` lets `clai` fall back to other configured providers when the active provider is exhausted.
|
|
144
|
+
- **Free-only mode** *(opt-in)* — `/freeonly on` restricts fallback strictly to free tiers so you never accidentally spend.
|
|
409
145
|
|
|
410
146
|
---
|
|
411
147
|
|
|
@@ -415,11 +151,11 @@ In the console, **`/set`** opens a multi-row editor: add rows with `+`, remove r
|
|
|
415
151
|
|
|
416
152
|
The same agent that runs recon also ships code. It explores before it writes, matches your existing stack from lockfiles, edits surgically, and proves the result:
|
|
417
153
|
|
|
418
|
-
- Scaffolds and extends apps; replaces starter boilerplate with real features
|
|
154
|
+
- Scaffolds and extends apps; replaces starter boilerplate with real features.
|
|
419
155
|
- Surgical file tools: `fs.edit`, `fs.replaceLines`, `fs.append`, plus multi-file writes.
|
|
420
156
|
- Runs the checks that apply — typecheck, build, unit/integration tests — and fixes failures before claiming success.
|
|
421
157
|
- Starts dev servers as background jobs, tails until ready, probes `localhost`, and reports the URL / port / job id with the server left running.
|
|
422
|
-
- Debugging loop: reproduce → read the actual error → fix root cause → re-verify
|
|
158
|
+
- Debugging loop: reproduce → read the actual error → fix root cause → re-verify.
|
|
423
159
|
|
|
424
160
|
```sh
|
|
425
161
|
clai --mode agent "convert this Vite React app to Next.js App Router, keep all features, run the build"
|
|
@@ -428,7 +164,7 @@ clai --mode agent "this test is flaky — find the race and fix it"
|
|
|
428
164
|
|
|
429
165
|
### Scope-based pentesting & bug bounty
|
|
430
166
|
|
|
431
|
-
clai is built to run real, authorized security work — not to narrate it. It follows a recon-first methodology and keeps you inside the boundaries you set.
|
|
167
|
+
`clai` is built to run real, authorized security work — not to narrate it. It follows a recon-first methodology and keeps you inside the boundaries you set.
|
|
432
168
|
|
|
433
169
|
```
|
|
434
170
|
recon / discovery → fingerprint stack → plan.create (kind=pentest)
|
|
@@ -445,7 +181,7 @@ recon / discovery → fingerprint stack → plan.create (kind=pentest)
|
|
|
445
181
|
4. `/implement` and execute task-by-task; expand the plan as new attack surface appears without wiping completed work.
|
|
446
182
|
5. **Report** with structure — title, severity, evidence, reproduction, impact, remediation — and honest residual/untested notes.
|
|
447
183
|
|
|
448
|
-
**Scope enforcement is real, not cosmetic.** When scope is active, clai checks each target against your authorized/excluded lists, enforces token-bucket rate limits and a concurrency ceiling, detects **redirects that leave scope** and **DNS-rebinding escapes**, and flags out-of-scope hosts instead of touching them.
|
|
184
|
+
**Scope enforcement is real, not cosmetic.** When scope is active, `clai` checks each target against your authorized/excluded lists, enforces token-bucket rate limits and a concurrency ceiling, detects **redirects that leave scope** and **DNS-rebinding escapes**, and flags out-of-scope hosts instead of touching them.
|
|
449
185
|
|
|
450
186
|
```sh
|
|
451
187
|
clai authorize-pentest AGREE
|
|
@@ -458,7 +194,7 @@ Dedicated recon tools: `pentest.recon` (bundled whois/dns/nmap), `pentest.webDis
|
|
|
458
194
|
|
|
459
195
|
### General security & sysadmin workflows
|
|
460
196
|
|
|
461
|
-
Log triage, config hardening, packaging, network
|
|
197
|
+
Log triage, config hardening, packaging, network analysis, OCR of a screenshot or PDF report, quick OSINT — all handled by the same agent under the same safety gate.
|
|
462
198
|
|
|
463
199
|
---
|
|
464
200
|
|
|
@@ -472,27 +208,27 @@ Three modes, switchable anytime with a slash command, `Shift+Tab`, or `clai --mo
|
|
|
472
208
|
| **agent** | Executes: edits, installs, scans, verifies, works the plan. |
|
|
473
209
|
| **plan** | Research and design a durable plan; approve with `/implement` before execution. |
|
|
474
210
|
|
|
475
|
-
**Reasoning / thinking** is controlled with `/effort` (alias `/reasoning`), accepting `on`, `off`, `none`, `minimal`, `low`, `medium`, `high`, or `xhigh`. clai
|
|
211
|
+
**Reasoning / thinking** is controlled with `/effort` (alias `/reasoning`), accepting `on`, `off`, `none`, `minimal`, `low`, `medium`, `high`, or `xhigh`. `clai` sends reasoning options only to models that support them.
|
|
476
212
|
|
|
477
213
|
---
|
|
478
214
|
|
|
479
215
|
## Safety gate
|
|
480
216
|
|
|
481
|
-
You own authorization; clai
|
|
217
|
+
You own authorization; `clai` gates risk on every action:
|
|
482
218
|
|
|
483
219
|
| Level | Behavior |
|
|
484
220
|
|-------|----------|
|
|
485
221
|
| **safe** | Auto-runs read-only work: `fs.read/list/search`, `sysinfo`, `dns.lookup`, `whois.lookup`, `http.fetch` GET, `web.search`/`web.fetch`, recon scanners. |
|
|
486
|
-
| **confirm** | Asks first for mutations: file writes/edits, installs, moves,
|
|
487
|
-
| **block** | Refuses destructive patterns (`rm -rf /`, fork bombs,
|
|
222
|
+
| **confirm** | Asks first for mutations: file writes/edits, installs, moves, mutating shell commands. |
|
|
223
|
+
| **block** | Refuses destructive patterns (`rm -rf /`, fork bombs, exfiltration signatures) and SSRF-prone fetches. |
|
|
488
224
|
|
|
489
|
-
`fs.delete` always confirms (with an optional
|
|
225
|
+
`fs.delete` always confirms (with an optional diff preview) even under allow-all. Use `/permissions` to choose the confirmation level and `/allow` / `/disallow` for a per-session tool allow-list.
|
|
490
226
|
|
|
491
227
|
---
|
|
492
228
|
|
|
493
229
|
## Terminal UI
|
|
494
230
|
|
|
495
|
-
The
|
|
231
|
+
The interactive console provides streaming chat, nested tool cards, file diffs, a live plan pane, pickers, session history, and masked key prompts.
|
|
496
232
|
|
|
497
233
|
| Action | Key |
|
|
498
234
|
|--------|-----|
|
|
@@ -503,62 +239,24 @@ The old line REPL has been removed — there are only full surfaces now. An Open
|
|
|
503
239
|
| Plan pane / plan detail | `Ctrl+H` / `Ctrl+P` |
|
|
504
240
|
| Background jobs | `Ctrl+J` |
|
|
505
241
|
| Expand thinking / tool output | `Ctrl+T` / `Ctrl+O` |
|
|
506
|
-
| Copy
|
|
242
|
+
| Copy focused thinking block | `c` |
|
|
507
243
|
| Search transcript | `Ctrl+R` |
|
|
508
244
|
| Copy selection | `Ctrl+Shift+C` |
|
|
509
245
|
| Commands / file mentions | `/` · `@` |
|
|
510
246
|
| MCP servers / project config | `/mcp` |
|
|
511
247
|
| Command help / shortcut reference | `Ctrl+G` / `/shortcuts` |
|
|
512
248
|
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
Automatic session titles describe the conversation's combined tasks, rather than replacing earlier work with the latest topic. Related follow-ups are grouped into shared themes, aiming for at most 12 words and 96 characters. Naming uses balanced request excerpts and the saved conversation transcript, including prompts inside compacted sections, so earlier tasks remain available after compaction and resume. Titles are first generated after two user prompts and reconsidered every three prompts; manually naming a session disables further automatic updates until it is reset or restored.
|
|
518
|
-
|
|
519
|
-
On exit, both interactive surfaces leave the alternate screen and print a sign-off card on the normal terminal: the wordmark beside a labelled block — session title, folder, elapsed time and message count, reasoning/cache token notes, and the command that reopens the session — followed by the same per-provider/model token table `/usage` shows. Resuming is `clai --resume <id>` (a unique id prefix is enough, and `-c/--continue` picks the newest session for the current directory). Sessions that were never persisted (`--no-history`, private mode, or nothing sent) say so instead of offering a resume command. The card is borderless and reflows down to very narrow terminals: the wordmark drops from six rows to four, then the block stacks beneath it, and labels give way before the resume command is ever shortened.
|
|
520
|
-
|
|
521
|
-
### Context usage and prompt caching
|
|
522
|
-
|
|
523
|
-
The composer context chip shows the latest provider-reported input token count, including during follow-ups and compaction. It waits for the first response instead of showing a speculative count. Local estimates are marked `~` and used when prompt usage is unavailable; internal request-size checks remain separate. A new provider measurement can legitimately be lower after compaction. Cached tokens are part of the reported prompt total, not an extra context bucket to add again.
|
|
524
|
-
|
|
525
|
-
Automatic compaction targets 200,000 assembled request tokens by default, including tool schemas and replayed context. Existing saved budgets at or below the former 180,000 default are migrated to `autoCompactRequestTokens: 200000` in the configuration file. When a custom session context window is set, its compaction target is 70% of that window instead: for example, 253,000 → 177,100 and 1,000,000 → 700,000. Both targets remain subject to output, safety, and compaction headroom: without a custom window, a 200,000-token model has a 156,992-token trigger, while a sufficiently large model reaches the full 200,000 default target. Dispatch also reserves the actual requested completion budget, including expanded continuations, and attempts compaction if the request no longer fits. Unusable summaries preserve the original history; clai will not silently delete context to force an oversized request through.
|
|
526
|
-
|
|
527
|
-
Same-route follow-ups retain previously sent request state, and supported cache-affinity keys stay stable for the session. Compaction reuses the previous request prefix when it fits and makes at most one generation attempt; rejected, truncated, or unusable summaries retain the original history rather than silently issuing another request. Cache hits still depend on the provider's expiry, routing, and supported caching behavior. Changing models or replacing history with a compacted summary can require a new cache prefix.
|
|
528
|
-
|
|
529
|
-
Recovery instructions and responder result ledgers append changed snapshots without deleting previously sent messages; identical updates are not duplicated. This shared history behavior applies to AgentRouter and other compatible providers. Custom OpenAI-compatible providers can declare `profile.cache.kind: "affinity-key"` with an `affinityField` and optional `isolationField` supported by their API. Chat Completions and Responses requests populate those fields with stable session keys; unrelated request controls cannot be replaced by cache fields. API compatibility alone does not imply support for every provider-specific caching option.
|
|
530
|
-
|
|
531
|
-
Anthropic, AWS Mantle, and Gemini keep changing request context in conversation order rather than moving it ahead of all prior messages. Anthropic-compatible requests use bounded conversation cache checkpoints in addition to the stable system checkpoint. The cache percentage is cumulative cached input divided by cumulative input tokens for requests with cache accounting, not the percentage of the session still held in a provider cache. A few uncached requests can lower that percentage, and later hits improve it gradually rather than immediately restoring its previous value.
|
|
532
|
-
|
|
533
|
-
Long-session memory optimizations preserve conversation and transcript content: rendering caches have size-aware eviction, terminal reattachment uses a fixed-size ring with the existing replay limit, and history recovery scans records incrementally. Bounded output previews and diagnostic excerpts own their text instead of retaining the full backing strings of large tool outputs. These are storage and rendering optimizations, not additional model-context truncation.
|
|
534
|
-
|
|
535
|
-
Compatible providers negotiate their API before sending the conversation: a short synthetic request uses the production serializers, authentication/custom headers, streaming mode, and reasoning/tool-control options, with at most 512 output tokens. Optional Responses fields are negotiated on these small requests. If Responses exposes no visible reasoning, a small Chat request checks whether Chat actually exposes it; clai prefers Chat only with positive evidence, otherwise retaining Responses. Encrypted/private reasoning and reasoning-token counts are not treated as visible text, and neither API can guarantee reasoning text on every answer.
|
|
536
|
-
|
|
537
|
-
Preflight uses no conversation history, images, or original tool schemas and has separate cache affinity. Choices are shared for matching provider, endpoint, model, credentials, headers, mode, and options; concurrent callers share negotiation. Observations expire after 30 minutes for new sessions, while active sessions retain their choice to protect cache prefixes. Cancellation, authentication/rate-limit failures, timeouts, and server errors do not mark a route unsupported. A cold negotiation uses at most three small requests with a shared 30-second deadline; these are billable provider calls, not conversation generations, and do not replace the real request's usage/context reporting. Small probes validate basic protocol/control support, not every image format, tool schema, or replay artifact.
|
|
538
|
-
|
|
539
|
-
Successful real Responses API requests are retained even when the provider does not expose reasoning; clai does not regenerate an answer or silently change protocols merely to obtain visible thinking. Ordinary requests do not evict earlier tool interactions just because their accumulated arguments cross a rolling size threshold. Explicit compaction and context admission checks still apply.
|
|
540
|
-
|
|
541
|
-
When switching providers or models, incompatible reasoning and interrupted native tool transactions are projected into compatible history without deleting the original conversation. Tool results remain available as text where native replay is unsafe, while compatible new tool transactions stay native. Known text-only GLM-5 routes do not receive image parts or the `image.view` tool. If a route rejects image input, clai can retry once without images and tells both the user and model that the image contents are unavailable; the original attachments remain available when switching back to a vision-capable model.
|
|
249
|
+
- **Thinking blocks:** Clickable `✦ Thought for 3.2s` rows open internal reasoning in a scrollable card (`Ctrl+T`). Pressing `c` copies the reasoning text.
|
|
250
|
+
- **Tool cards:** Show running commands with live elapsed timers, status indicators, and expandable output pagers (`Ctrl+O`) with search and copy capabilities.
|
|
251
|
+
- **File diffs:** Edits and writes render clean inline diff previews before changes take effect.
|
|
542
252
|
|
|
543
253
|
### Background sessions, minimise, and SSH reattach
|
|
544
254
|
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
- `/minimise` (also `/minimize`) detaches immediately and returns the shell prompt without cancelling the current turn. It prints the session id and the exact `clai --resume <id>` command.
|
|
548
|
-
- An SSH or terminal disconnect has the same detach behavior. SSH into the VM again as the same OS user and run `clai --resume <id>`; `clai -c` prefers the newest live session in the current directory.
|
|
549
|
-
- `/history` marks running, attached, and detached sessions. Selecting another session attaches or starts its own runtime instead of loading over a running agent, so the outgoing agent continues independently.
|
|
550
|
-
- One terminal controls a session at a time. Attaching from another terminal safely transfers control and releases the old terminal; this prevents duplicate keystrokes while still allowing cross-computer SSH takeover.
|
|
551
|
-
- The broker stores only bounded terminal replay (2 MiB), uses an authenticated user-only Unix socket or Windows named pipe, and keeps runtime metadata/locks user-readable only. It never opens a TCP port.
|
|
552
|
-
- A detached runtime stays alive while a turn, compaction, queued prompt, or responder job is active. Once truly idle and detached, it exits after 30 minutes by default; the saved session still resumes normally without keeping idle processes forever.
|
|
553
|
-
- `--no-history`, private mode, non-TTY/one-shot runs, and systems without a usable PTY retain the existing direct foreground behavior. `/minimise` reports that background detach is unavailable instead of partially detaching.
|
|
554
|
-
|
|
555
|
-
Optional controls:
|
|
255
|
+
Interactive sessions run behind a local broker so an agent continues working across terminal disconnects:
|
|
556
256
|
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
CLAI_DISABLE_SESSION_RUNTIME=1 # force legacy direct foreground ownership
|
|
561
|
-
```
|
|
257
|
+
- **`/minimise`** (or `/minimize`) detaches immediately and returns you to your shell without interrupting the turn. It displays the session ID and resume command.
|
|
258
|
+
- **SSH disconnects:** If an SSH session drops, reconnect and run `clai --resume <id>` (or `clai -c` to continue the latest session in the current directory).
|
|
259
|
+
- **`/history`** lists all active, attached, and detached sessions.
|
|
562
260
|
|
|
563
261
|
---
|
|
564
262
|
|
|
@@ -567,72 +265,24 @@ CLAI_DISABLE_SESSION_RUNTIME=1 # force legacy direct foreground ownership
|
|
|
567
265
|
| Command | Does |
|
|
568
266
|
|---------|------|
|
|
569
267
|
| `/ask` · `/agent` · `/plan` | Switch mode (plan = design-then-approve) |
|
|
570
|
-
| `/implement` · `/discard` | Approve
|
|
571
|
-
| `/model [name
|
|
572
|
-
| `/set [provider]` · `/unset [provider]` · `/keys`
|
|
573
|
-
| `/effort [level]` · `/reasoning [level]` |
|
|
268
|
+
| `/implement` · `/discard` | Approve and execute or drop the current plan |
|
|
269
|
+
| `/model [name]` · `/provider [name]` | Select model / switch provider |
|
|
270
|
+
| `/set [provider]` · `/unset [provider]` · `/keys` | Manage API keys and view provider configuration |
|
|
271
|
+
| `/effort [level]` · `/reasoning [level]` | Configure thinking / reasoning effort |
|
|
574
272
|
| `/freeonly [on\|off]` · `/fallback [on\|off]` | Free-only filter · cross-provider fallback |
|
|
575
273
|
| `/search [provider]` · `/search-provider` | Choose web-search backend |
|
|
576
|
-
| `/mcp [
|
|
577
|
-
| `/scope [show\|add\|new\|clear]` |
|
|
578
|
-
| `/output [last\|id\|list]` | Open full tool output (also `Ctrl+O`) |
|
|
579
|
-
| `/jobs` |
|
|
580
|
-
| `/
|
|
581
|
-
| `/
|
|
582
|
-
| `/
|
|
583
|
-
| `/history` · `/save <name>` · `/new` · `/clear` · `/reset` | Session lifecycle (`/clear` deletes the current session outright) |
|
|
584
|
-
| `/allow <tool>` · `/disallow <tool>` · `/permissions` | Tool permissions |
|
|
274
|
+
| `/mcp [...]` | Browse, configure, start, or stop MCP servers |
|
|
275
|
+
| `/scope [show\|add\|new\|clear]` | Manage engagement scope |
|
|
276
|
+
| `/output [last\|id\|list]` | Open full tool output pager (also `Ctrl+O`) |
|
|
277
|
+
| `/jobs` | View background jobs (also `Ctrl+J`) |
|
|
278
|
+
| `/compact` · `/context` | Compact history now · show context token size |
|
|
279
|
+
| `/history` · `/save <name>` · `/new` · `/clear` | Session lifecycle management |
|
|
280
|
+
| `/allow <tool>` · `/disallow <tool>` · `/permissions` | Tool permission management |
|
|
585
281
|
| `/cwd <path>` | Change working directory |
|
|
586
282
|
| `/think` · `/thinking` | Show thinking from the last response |
|
|
587
|
-
| `/privacy [...]` | Private mode · clear history
|
|
588
|
-
| `/minimise` · `/minimize` | Detach
|
|
589
|
-
| `/update` · `/help` · `/shortcuts` · `/exit` |
|
|
590
|
-
|
|
591
|
-
Orchestration is enabled in new and restored sessions. `/orchestrator`,
|
|
592
|
-
`/orchestration`, and `/orchastrator` show the current status and open a picker
|
|
593
|
-
with **On**, **Off**, and **Models…**. `/orchestrator status` prints the status
|
|
594
|
-
without changing it, `/orchestrator on` / `/orchestrator off` set it directly,
|
|
595
|
-
and `/orchestrator models` opens the subagent model editor. The active position
|
|
596
|
-
determines the first eligible model; other enabled rows are fallbacks in rotation
|
|
597
|
-
order. With no saved chain, subagents follow the parent session route. A fallback
|
|
598
|
-
is used only for a retryable pre-output failure, and model-chain changes apply to
|
|
599
|
-
new attempts.
|
|
600
|
-
Turning orchestration off stops active children and blocks new starts and
|
|
601
|
-
restarts for this session; turning it back on re-enables delegation. `/agents`
|
|
602
|
-
opens the separate live inspector. `/agents` opens the same live inspector in
|
|
603
|
-
Classic and OpenTUI: select a child, press `Esc` to return to the picker, then
|
|
604
|
-
select another child or **Main agent**. Inspecting output never interrupts the
|
|
605
|
-
main turn. The pager follows live output; `l` toggles follow. Turning
|
|
606
|
-
orchestration off stops active children and prevents new starts and restarts.
|
|
607
|
-
`/agents stop <id>` stops an individual child. `/agents restart <id>` reruns the
|
|
608
|
-
assignment when orchestration is enabled. Saved child reports can be inspected
|
|
609
|
-
after resuming their parent session; `--no-history` keeps child records in
|
|
610
|
-
memory only.
|
|
611
|
-
|
|
612
|
-
The last usable child summary is stored separately from activity and survives
|
|
613
|
-
stop, restart, and compaction. `subagent.read` with `view=summary` recovers it with
|
|
614
|
-
its original attempt and completion status; a prior summary never marks a stopped
|
|
615
|
-
attempt complete. Undelivered terminal results return through the parent inbox on
|
|
616
|
-
session restore, and acknowledged results are not replayed on later restores.
|
|
617
|
-
|
|
618
|
-
Children have no fixed concurrency, step, or assignment-time budget. By default,
|
|
619
|
-
they inherit the parent's provider/model and project root; a configured subagent
|
|
620
|
-
model chain selects a primary execution route and fallbacks without changing the
|
|
621
|
-
assignment identity. Children retain independent histories and stable cache
|
|
622
|
-
prefixes. Their only tools are confined file reads/listings/searches and web
|
|
623
|
-
search/fetch; shell, editing, MCP, arbitrary HTTP actions, and further delegation
|
|
624
|
-
are unavailable. Provider context and transport safety limits still apply. Context
|
|
625
|
-
compaction retains evidence and continues research without displaying internal
|
|
626
|
-
partial reports as deliverables.
|
|
627
|
-
|
|
628
|
-
The parent leaves delegated investigations to their children and continues only
|
|
629
|
-
necessary non-overlapping work. Results arrive automatically at safe model
|
|
630
|
-
boundaries or wake an idle parent. When no independent work remains,
|
|
631
|
-
`subagent.wait` suspends without polling or a default deadline; omit the ID to
|
|
632
|
-
receive whichever child completes, fails, or stops first. Healthy work should not
|
|
633
|
-
be cancelled for slowness or because the parent repeated it. Reports are retained
|
|
634
|
-
whole and paged with `subagent.read`; use the returned attempt and `nextOffset`
|
|
635
|
-
to continue reading. Activity reads default to three recent events.
|
|
283
|
+
| `/privacy [...]` | Private mode · clear history, logs, or artifacts |
|
|
284
|
+
| `/minimise` · `/minimize` | Detach terminal while the session runs in background |
|
|
285
|
+
| `/update` · `/help` · `/shortcuts` · `/exit` | Utilities and exit |
|
|
636
286
|
|
|
637
287
|
---
|
|
638
288
|
|
|
@@ -644,49 +294,34 @@ clai [prompt...] # interactive UI, or one-shot with a prom
|
|
|
644
294
|
-y/--yes --no-history
|
|
645
295
|
--show-thinking --verbose --quiet # one-shot stream controls
|
|
646
296
|
--tui --classic
|
|
647
|
-
--
|
|
648
|
-
--resume <sessionId> -c/--continue # reattach live or reopen saved session; ignored with a prompt
|
|
297
|
+
--resume <sessionId> -c/--continue # reattach live or reopen saved session
|
|
649
298
|
|
|
650
|
-
clai set <provider> [key] # --from-env <VAR> | --stdin | --url <url>
|
|
651
|
-
clai unset <provider> # remove all keys for a provider
|
|
652
|
-
clai keys # list providers with masked keys
|
|
299
|
+
clai set <provider> [key] # --from-env <VAR> | --stdin | --url <url>
|
|
300
|
+
clai unset <provider> # remove all keys for a provider
|
|
301
|
+
clai keys # list providers with masked keys
|
|
653
302
|
clai use <provider> # set active provider
|
|
654
303
|
clai provider [provider] # switch provider or open picker
|
|
655
304
|
clai model <model> # set model for the active provider
|
|
656
305
|
clai mode <ask|agent|plan> # set default mode
|
|
657
306
|
clai search-provider <brave|tavily|duckduckgo>
|
|
658
|
-
clai config [key] [value] #
|
|
307
|
+
clai config [key] [value] # view or update configuration
|
|
659
308
|
clai doctor # check installed tools + provider config
|
|
660
|
-
clai history [--show <id>] # list sessions
|
|
661
|
-
clai update # check for updates
|
|
309
|
+
clai history [--show <id>] # list saved sessions
|
|
310
|
+
clai update # check for updates and upgrade
|
|
662
311
|
clai authorize-pentest AGREE # enable scan/attack tools (one-time ack)
|
|
663
|
-
clai scope <show|new|add|clear> # engagement scope
|
|
664
|
-
|
|
665
|
-
clai privacy <status|on|off|retention|clear-history|clear-logs|clear-artifacts|clear-all>
|
|
312
|
+
clai scope <show|new|add|clear> # engagement scope management
|
|
313
|
+
clai privacy <status|on|off|clear-all> # privacy and history clearing
|
|
666
314
|
```
|
|
667
315
|
|
|
668
|
-
### One-shot output and exit status
|
|
669
|
-
|
|
670
|
-
`clai "prompt"` and piped prompts use the noninteractive stream renderer. The final
|
|
671
|
-
assistant answer is written to **stdout**; progress, tool cards, diffs, thinking (when
|
|
672
|
-
`--show-thinking` is enabled), confirmations, and errors are written to **stderr**. `--quiet`
|
|
673
|
-
suppresses progress while retaining the final answer on stdout, and `--verbose` expands tool
|
|
674
|
-
output and diff hunks. `--no-history` disables persistence for that run.
|
|
675
|
-
|
|
676
|
-
A completed, partially completed, blocked, or failed turn returns exit code `0`; an aborted
|
|
677
|
-
turn returns `130`; an unhandled or loader error returns `1`. While one-shot work is running,
|
|
678
|
-
press `Esc` or `Ctrl+C` to abort it, including commands launched through `bun run dev`.
|
|
679
|
-
`--show-thinking` can also be enabled with `CLAI_SHOW_THINKING=1`.
|
|
680
|
-
|
|
681
316
|
---
|
|
682
317
|
|
|
683
318
|
## Model Context Protocol (MCP)
|
|
684
319
|
|
|
685
|
-
clai can discover and call tools from local or remote MCP servers. MCP tools are **off by default
|
|
320
|
+
`clai` can discover and call tools from local or remote MCP servers. MCP tools are **off by default**; they are activated when a prompt mentions `@mcp:<server>` or via `/mcp all`.
|
|
686
321
|
|
|
687
322
|
### Project configuration
|
|
688
323
|
|
|
689
|
-
|
|
324
|
+
Define MCP servers in `.clai/mcp.json` (or standard `.vscode/mcp.json` / `.cursor/mcp.json` locations):
|
|
690
325
|
|
|
691
326
|
```json
|
|
692
327
|
{
|
|
@@ -708,38 +343,7 @@ The native project file is `.clai/mcp.json`. It accepts JSON or JSONC and the co
|
|
|
708
343
|
}
|
|
709
344
|
```
|
|
710
345
|
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
The picker can add one server without hand-editing the file: choose **+ add MCP server** and a full multiline editor opens — visible caret, arrow-key and word/line navigation, mid-text edits, selection, and multi-line paste. `Enter` inserts a newline, `Ctrl+S` saves, `Esc` cancels. If the JSON does not validate, the editor reopens with your text intact and the parse error in the header, so a long paste is never retyped. You can also supply the fragment inline:
|
|
714
|
-
|
|
715
|
-
```text
|
|
716
|
-
/mcp add {"name":"docs","command":"docs-server","args":[]}
|
|
717
|
-
```
|
|
718
|
-
|
|
719
|
-
The add flow accepts one named object or a one-entry `servers` / `mcpServers` fragment, validates it, then atomically merges it into the current project `.clai/mcp.json` with deterministic server ordering and restrictive permissions. Existing unrelated metadata is preserved.
|
|
720
|
-
|
|
721
|
-
clai also inherits compatible configuration from `CLAI_MCP_CONFIG` (an OS-delimited file list), ancestor `.clai/mcp.json` and `.mcp.json` files, repository `.github/mcp.json` and `.vscode/mcp.json`, clai user config, and supported Copilot, Claude, and VS Code user locations. Higher-precedence definitions deterministically shadow inherited servers with the same name. `/mcp locations` shows the exact project target and inherited paths for the current workspace.
|
|
722
|
-
|
|
723
|
-
### Select and inspect servers
|
|
724
|
-
|
|
725
|
-
```text
|
|
726
|
-
/mcp # picker: add, off, all, or one server
|
|
727
|
-
/mcp docs # drop @mcp:docs into the prompt (repeat for more servers)
|
|
728
|
-
/mcp all # expose tools from every live server
|
|
729
|
-
/mcp off # default: expose no MCP tools
|
|
730
|
-
/mcp list # sources, transports, state, selection, and catalog
|
|
731
|
-
/mcp status # live, failed, and invalid server details
|
|
732
|
-
/mcp tools [server] # canonical mcp.<server>.<tool> names
|
|
733
|
-
/mcp locations # project and inherited configuration paths
|
|
734
|
-
/mcp refresh # rediscover configs and live tools
|
|
735
|
-
/mcp reconnect docs # restart one server connection
|
|
736
|
-
/mcp stop docs # shut the server down and drop its tools from every request
|
|
737
|
-
/mcp start docs # bring a stopped server back
|
|
738
|
-
/mcp login docs # run OAuth browser sign-in, store the token, reconnect
|
|
739
|
-
/mcp add notion # add https://mcp.notion.com/mcp and sign in
|
|
740
|
-
```
|
|
741
|
-
|
|
742
|
-
Static built-in tools always remain first; selected MCP definitions are appended in deterministic order as `mcp.<server>.<tool>`. Each schema is normalised once — documentation-only keywords dropped, descriptions bounded, keywords canonically ordered — and sent exactly once per request in the native function payload rather than repeated as prompt text, so a large server such as GitHub MCP costs a stable, cacheable prefix instead of tens of thousands of duplicated tokens per turn. Selection is never silently widened or dropped mid-refresh, and `/mcp stop <server>` closes the connection and removes its tools from every subsequent request until `/mcp start <server>`. A tool explicitly annotated read-only can run under the normal safe/parallel policy. Unmarked, mutating, or destructive MCP tools require the usual confirmation, and ask mode exposes only safe tools. Server descriptions and results are treated as untrusted data, secrets are redacted, response sizes and lifecycles are bounded, and HTTP credentials are never forwarded through redirects.
|
|
346
|
+
Use `/mcp` inside the interactive console to browse servers, inspect available tools, view logs, restart connections, or add new servers interactively.
|
|
743
347
|
|
|
744
348
|
---
|
|
745
349
|
|
|
@@ -756,31 +360,15 @@ Static built-in tools always remain first; selected MCP definitions are appended
|
|
|
756
360
|
| **Plan** | `plan.create` · `task.update` · `agent.handoff` |
|
|
757
361
|
| **Context** | `sysinfo` · `image.ocr` · `pdf.read` |
|
|
758
362
|
|
|
759
|
-
### tool.batch fail policy
|
|
760
|
-
|
|
761
|
-
Default is **continue** — one failed lookup never kills the rest (ideal for recon). Opt into fail-fast or selective cancellation when later work depends on earlier success:
|
|
762
|
-
|
|
763
|
-
```json
|
|
764
|
-
{"name":"tool.batch","args":{
|
|
765
|
-
"on_fail":"cancel_pending",
|
|
766
|
-
"calls":[
|
|
767
|
-
{"name":"net.scan","args":{"target":"lab.example"}},
|
|
768
|
-
{"name":"http.fetch","args":{"url":"https://lab.example/"}}
|
|
769
|
-
]
|
|
770
|
-
}}
|
|
771
|
-
```
|
|
772
|
-
|
|
773
|
-
Top-level messages with several separate tool blocks never cancel siblings — use `tool.batch` when you need a fail policy.
|
|
774
|
-
|
|
775
363
|
---
|
|
776
364
|
|
|
777
365
|
## Web search / OSINT
|
|
778
366
|
|
|
779
|
-
| Provider | Key |
|
|
780
|
-
|
|
781
|
-
| DuckDuckGo |
|
|
782
|
-
| Brave |
|
|
783
|
-
| Tavily |
|
|
367
|
+
| Provider | Key | Environment Variable |
|
|
368
|
+
|----------|-----|----------------------|
|
|
369
|
+
| **DuckDuckGo** | None (default) | — |
|
|
370
|
+
| **Brave** | Required | `BRAVE_SEARCH_API_KEY` |
|
|
371
|
+
| **Tavily** | Required | `TAVILY_API_KEY` |
|
|
784
372
|
|
|
785
373
|
```sh
|
|
786
374
|
clai set brave bsx-...
|
|
@@ -788,41 +376,37 @@ clai set tavily tvly-...
|
|
|
788
376
|
clai search-provider tavily
|
|
789
377
|
```
|
|
790
378
|
|
|
791
|
-
Search-provider keys are multi-key and rotate just like model providers.
|
|
792
|
-
|
|
793
379
|
---
|
|
794
380
|
|
|
795
381
|
## Per-project context
|
|
796
382
|
|
|
797
|
-
Drop a `.clai/context.md` in
|
|
383
|
+
Drop a `.clai/context.md` in any project root, and its content is injected automatically on every turn — repo architecture, stack conventions, testing instructions, or scope rules.
|
|
798
384
|
|
|
799
385
|
---
|
|
800
386
|
|
|
801
387
|
## Interactive REPLs and terminals
|
|
802
388
|
|
|
803
|
-
|
|
389
|
+
When a task requires multi-step interactive terminal interactions, `clai` maintains a persistent terminal session attached to the conversation:
|
|
804
390
|
|
|
805
391
|
```text
|
|
806
|
-
Start a Python REPL,
|
|
392
|
+
Start a Python REPL, test the regular expression against our test cases, and show me the output.
|
|
807
393
|
```
|
|
808
394
|
|
|
809
|
-
The agent
|
|
810
|
-
|
|
811
|
-
For authorized security work, interactive effects are re-evaluated against the active engagement scope at the time they are delivered. That includes the target, port, phase, and expiry accumulated from prior REPL commands, so a split sequence cannot bypass scope controls.
|
|
395
|
+
The agent runs interactive commands in persistent PTY sessions, reads incremental output, sends follow-up commands, and safely terminates processes upon completion.
|
|
812
396
|
|
|
813
397
|
---
|
|
814
398
|
|
|
815
399
|
## Configuration & privacy
|
|
816
400
|
|
|
817
401
|
```sh
|
|
818
|
-
clai config # view config
|
|
819
|
-
clai mode agent # default mode
|
|
820
|
-
clai model <name> # default model
|
|
402
|
+
clai config # view current config
|
|
403
|
+
clai mode agent # set default mode
|
|
404
|
+
clai model <name> # set default model
|
|
821
405
|
/privacy on # private mode: don't persist this session
|
|
822
406
|
/privacy clear-all # wipe history, logs, and artifacts
|
|
823
407
|
```
|
|
824
408
|
|
|
825
|
-
Config
|
|
409
|
+
Config is stored locally in your OS user directory (e.g. `~/.config/clai/`). Keys are stored locally and never exposed in plain text.
|
|
826
410
|
|
|
827
411
|
---
|
|
828
412
|
|
|
@@ -833,31 +417,12 @@ npm install
|
|
|
833
417
|
npm run dev # run from source
|
|
834
418
|
npm run typecheck
|
|
835
419
|
npm run build
|
|
836
|
-
npm test # full
|
|
837
|
-
npm run
|
|
838
|
-
npm run compile # native binaries (Bun)
|
|
839
|
-
npm run release:verify
|
|
840
|
-
npm pack --dry-run
|
|
420
|
+
npm test # full test suite
|
|
421
|
+
npm run compile # compile native binaries with Bun
|
|
841
422
|
```
|
|
842
423
|
|
|
843
424
|
---
|
|
844
425
|
|
|
845
|
-
## Releasing
|
|
846
|
-
|
|
847
|
-
Tag-driven CI (`.github/workflows/release.yml`): validate (typecheck + tests + release checks) → multi-platform binaries → GitHub Release → npm `@pentoshi/clai` → Homebrew tap.
|
|
848
|
-
|
|
849
|
-
```sh
|
|
850
|
-
# package.json "version" is the single source of truth.
|
|
851
|
-
npm version 3.8.0 --no-git-tag-version
|
|
852
|
-
npm run sync-version # refreshes version.generated.ts + install manifests + lockfile
|
|
853
|
-
git commit -am "v3.8.0" && git push origin main
|
|
854
|
-
git tag -a v3.8.0 -m "clai v3.8.0" && git push origin v3.8.0
|
|
855
|
-
```
|
|
856
|
-
|
|
857
|
-
Secrets: `NPM_TOKEN`, `TAP_GITHUB_TOKEN`. Optional: `NPM_PROVENANCE=true`.
|
|
858
|
-
|
|
859
|
-
---
|
|
860
|
-
|
|
861
426
|
## Architecture
|
|
862
427
|
|
|
863
428
|
```
|
|
@@ -865,7 +430,7 @@ clai/
|
|
|
865
430
|
├─ src/
|
|
866
431
|
│ ├─ index.ts # CLI entry + subcommands
|
|
867
432
|
│ ├─ agent/ # loop, plans, compaction, resume orientation, tool parsing
|
|
868
|
-
│ ├─ llm/ #
|
|
433
|
+
│ ├─ llm/ # providers, streaming, native tools, key rotation + fallback
|
|
869
434
|
│ ├─ mcp/ # discovery, validation, transports, lifecycle, and tool dispatch
|
|
870
435
|
│ ├─ tools/ # fs, shell, net, http, web, pentest, batch, plan
|
|
871
436
|
│ ├─ safety/ # risk classifier + engagement (scope) policy
|