@pentoshi/clai 3.8.44 → 3.8.46
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 +249 -251
- package/dist/attachments/clipboard-image.d.ts +10 -0
- package/dist/attachments/clipboard-image.js +188 -0
- package/dist/attachments/clipboard-image.js.map +1 -0
- package/dist/attachments/image-content.d.ts +3 -0
- package/dist/attachments/image-content.js +51 -0
- package/dist/attachments/image-content.js.map +1 -0
- package/dist/attachments/service.js +6 -2
- package/dist/attachments/service.js.map +1 -1
- package/dist/commands/providers.js +4 -2
- package/dist/commands/providers.js.map +1 -1
- package/dist/commands/search-providers.d.ts +1 -0
- package/dist/commands/search-providers.js +4 -2
- package/dist/commands/search-providers.js.map +1 -1
- package/dist/llm/capabilities.js +17 -4
- package/dist/llm/capabilities.js.map +1 -1
- package/dist/prompts/embedded.js +2 -2
- package/dist/prompts/embedded.js.map +1 -1
- package/dist/prompts/index.js +1 -1
- package/dist/prompts/system.agent.md +5 -3
- package/dist/prompts/system.ask.md +1 -1
- package/dist/repl/prompt-line.js +39 -6
- package/dist/repl/prompt-line.js.map +1 -1
- package/dist/repl.js +1 -1
- package/dist/repl.js.map +1 -1
- package/dist/store/config.d.ts +5 -1
- package/dist/store/config.js +8 -0
- package/dist/store/config.js.map +1 -1
- package/dist/store/history.js +43 -5
- package/dist/store/history.js.map +1 -1
- package/dist/store/keys.js +1 -0
- package/dist/store/keys.js.map +1 -1
- package/dist/tools/definitions.js +13 -7
- package/dist/tools/definitions.js.map +1 -1
- package/dist/tools/http.d.ts +6 -1
- package/dist/tools/http.js +247 -68
- package/dist/tools/http.js.map +1 -1
- package/dist/tools/registry.js +2 -1
- package/dist/tools/registry.js.map +1 -1
- package/dist/tools/web/decode.d.ts +17 -0
- package/dist/tools/web/decode.js +65 -0
- package/dist/tools/web/decode.js.map +1 -0
- package/dist/tools/web/fetch-core.js +14 -20
- package/dist/tools/web/fetch-core.js.map +1 -1
- package/dist/tools/web/providers/exa.d.ts +51 -0
- package/dist/tools/web/providers/exa.js +303 -0
- package/dist/tools/web/providers/exa.js.map +1 -0
- package/dist/tools/web/readable.d.ts +5 -5
- package/dist/tools/web/readable.js +34 -12
- package/dist/tools/web/readable.js.map +1 -1
- package/dist/tools/web/search.d.ts +3 -1
- package/dist/tools/web/search.js +6 -4
- package/dist/tools/web/search.js.map +1 -1
- package/dist/tools/web/types.d.ts +25 -2
- package/dist/tools/web/types.js +32 -0
- package/dist/tools/web/types.js.map +1 -1
- package/dist/tui-v2/app/commands/key-commands.js +1 -1
- package/dist/tui-v2/app/commands/key-commands.js.map +1 -1
- package/dist/tui-v2/app/commands/picker-commands.js +59 -8
- package/dist/tui-v2/app/commands/picker-commands.js.map +1 -1
- package/dist/tui-v2/components/transcript/intro-card.js +11 -5
- package/dist/tui-v2/components/transcript/intro-card.js.map +1 -1
- package/dist/tui-v2/composer/composer-editor.js +11 -9
- package/dist/tui-v2/composer/composer-editor.js.map +1 -1
- package/dist/tui-v2/composer/composer-image-paste.d.ts +19 -0
- package/dist/tui-v2/composer/composer-image-paste.js +56 -0
- package/dist/tui-v2/composer/composer-image-paste.js.map +1 -0
- package/dist/ui/keys.d.ts +1 -0
- package/dist/ui/keys.js +4 -0
- package/dist/ui/keys.js.map +1 -1
- package/dist/ui/mentions.d.ts +2 -16
- package/dist/ui/mentions.js +132 -102
- package/dist/ui/mentions.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
|
@@ -1,48 +1,31 @@
|
|
|
1
1
|
# clai
|
|
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
|
|
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 entirely in your terminal with a full-screen console UI (and a classic line REPL fallback).
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
Two things make it practical for everyday use:
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
## Why clai for pentesting?
|
|
12
|
-
|
|
13
|
-
| Pain | What clai does |
|
|
14
|
-
|------|----------------|
|
|
15
|
-
| Chatbots that only *describe* scans | **Runs** recon, fuzzers, and PoCs via shell + dedicated tools |
|
|
16
|
-
| Long engagements lose the thread | **Session plan** + task checklist survives compaction and reloads from history |
|
|
17
|
-
| Spray-and-pray tooling | **Stack fingerprint first**, then stack-matched wordlists and vectors |
|
|
18
|
-
| Noisy full dumps fill context | **High-signal tool use**, artifacts for long output, expandable cards |
|
|
19
|
-
| Unscoped scanning | **Authorize once**, optional **engagement scope**, confirm on mutating work |
|
|
20
|
-
| “AI said vulnerable” without evidence | Findings require **command + real output**; report-style structure encouraged |
|
|
9
|
+
- **It's cheap-to-free to run.** Point it at Groq, Google Gemini, NVIDIA NIM, OpenRouter, Bynara, Kimchi, or a local Ollama — all have free access — and clai stacks them. Add several keys per provider; when one hits a rate limit, it rotates to the next automatically.
|
|
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.
|
|
21
11
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
```
|
|
25
|
-
recon / discovery → fingerprint stack → plan.create (kind=pentest)
|
|
26
|
-
↑ │
|
|
27
|
-
│ /implement (approve)
|
|
28
|
-
│ ↓
|
|
29
|
-
└──── enumerate → exploit → post-ex → report
|
|
30
|
-
(revise plan as surface grows; keep completed tasks)
|
|
31
|
-
```
|
|
12
|
+
---
|
|
32
13
|
|
|
33
|
-
|
|
34
|
-
2. **Analyze evidence**, then **`plan.create`** with `kind=pentest` from real ports/services/endpoints/weaknesses — then **stop**.
|
|
35
|
-
3. You **`/implement`**, refine in chat, or **`/discard`**.
|
|
36
|
-
4. Execute task-by-task with **`task.update`**; expand the plan when new surface appears without wiping done work.
|
|
14
|
+
## Highlights
|
|
37
15
|
|
|
38
|
-
|
|
16
|
+
- **Free-tier first.** 12 providers wired in, 6 cloud free tiers + local Ollama. Default provider is NVIDIA NIM (`openai/gpt-oss-20b`) so a fresh install can run at no cost.
|
|
17
|
+
- **Multi-key smart switching.** Up to 10 keys per provider with a *sticky* active key and circular rotation on rate-limit / auth / quota / transient / 5xx / empty-response errors. Optional cross-provider fallback and a free-only filter.
|
|
18
|
+
- **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.
|
|
19
|
+
- **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.
|
|
20
|
+
- **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.
|
|
21
|
+
- **Native + text tool calling.** Uses provider-native function calling where available, with a text-fence fallback (`toolCalling: auto|native|text`).
|
|
22
|
+
- **Safety gate you control.** Every action is classified safe / confirm / block; deletes always confirm with a preview; destructive patterns are blocked.
|
|
39
23
|
|
|
40
24
|
---
|
|
41
25
|
|
|
42
|
-
##
|
|
26
|
+
## Install
|
|
43
27
|
|
|
44
28
|
### macOS
|
|
45
|
-
|
|
46
29
|
```sh
|
|
47
30
|
brew tap pentoshi007/clai && brew install clai
|
|
48
31
|
# or
|
|
@@ -50,248 +33,280 @@ curl -fsSL https://raw.githubusercontent.com/pentoshi007/clai/main/install/insta
|
|
|
50
33
|
```
|
|
51
34
|
|
|
52
35
|
### Linux
|
|
53
|
-
|
|
54
36
|
```sh
|
|
55
37
|
curl -fsSL https://raw.githubusercontent.com/pentoshi007/clai/main/install/install.sh | sh
|
|
56
38
|
```
|
|
57
39
|
|
|
58
40
|
### Windows
|
|
59
|
-
|
|
60
41
|
```powershell
|
|
61
42
|
irm https://raw.githubusercontent.com/pentoshi007/clai/main/install/install.ps1 | iex
|
|
62
|
-
# or
|
|
43
|
+
# or
|
|
44
|
+
scoop bucket add clai https://github.com/pentoshi007/clai && scoop install clai
|
|
63
45
|
```
|
|
64
46
|
|
|
65
47
|
### npm / from source
|
|
66
|
-
|
|
67
48
|
```sh
|
|
68
49
|
npm i -g @pentoshi/clai
|
|
69
|
-
|
|
70
50
|
# or
|
|
71
51
|
git clone https://github.com/pentoshi007/clai.git
|
|
72
52
|
cd clai && npm install && npm run build && npm start
|
|
73
53
|
```
|
|
74
54
|
|
|
75
|
-
Type `clai` in any terminal to start.
|
|
55
|
+
Node.js ≥ 20. Type `clai` in any terminal to start.
|
|
76
56
|
|
|
77
57
|
---
|
|
78
58
|
|
|
79
|
-
## Quick start
|
|
59
|
+
## Quick start
|
|
60
|
+
|
|
61
|
+
Get a free key from any supported provider, add it, and go:
|
|
80
62
|
|
|
81
63
|
```sh
|
|
82
|
-
#
|
|
64
|
+
# Add a free key (Groq shown; NVIDIA/Gemini/OpenRouter/Bynara/Kimchi work the same)
|
|
65
|
+
clai set groq gsk_your_key_here
|
|
66
|
+
|
|
67
|
+
# Launch the full-screen agent console
|
|
83
68
|
clai
|
|
84
69
|
|
|
85
|
-
#
|
|
86
|
-
clai
|
|
70
|
+
# Or one-shot from the shell
|
|
71
|
+
clai "explain what this repo does and find the entrypoint"
|
|
72
|
+
clai --mode agent "add a /health endpoint to the Express app and run the tests"
|
|
73
|
+
```
|
|
87
74
|
|
|
88
|
-
|
|
89
|
-
clai scope add --targets lab.example.com,10.10.0.0/24
|
|
75
|
+
Prefer fully local and offline? Point at Ollama:
|
|
90
76
|
|
|
91
|
-
|
|
92
|
-
clai
|
|
77
|
+
```sh
|
|
78
|
+
clai set ollama --url http://localhost:11434
|
|
79
|
+
clai use ollama
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
## Run it on free tiers (and keep it running)
|
|
85
|
+
|
|
86
|
+
This is the core of clai's design: assemble capacity from free tiers, then survive rate limits automatically.
|
|
87
|
+
|
|
88
|
+
### Supported providers
|
|
89
|
+
|
|
90
|
+
| Provider | Default model | Tier | Env var |
|
|
91
|
+
|----------|---------------|------|---------|
|
|
92
|
+
| NVIDIA NIM | `openai/gpt-oss-20b` | Free | `NVIDIA_API_KEY` |
|
|
93
|
+
| Groq | `llama-3.3-70b-versatile` | Free | `GROQ_API_KEY` |
|
|
94
|
+
| Google Gemini | `gemini-3.5-flash` | Free | `GEMINI_API_KEY` |
|
|
95
|
+
| OpenRouter | `meta-llama/llama-3.3-70b-instruct:free` | Free | `OPENROUTER_API_KEY` |
|
|
96
|
+
| Bynara | `mimo-v2.5-free` | Free | `BYNARA_API_KEY` |
|
|
97
|
+
| Kimchi | `kimi-k2.6` | Free | `CASTAI_API_KEY` |
|
|
98
|
+
| Ollama | `llama3.1:8b` | Local / free | `OLLAMA_HOST` |
|
|
99
|
+
| OpenAI | `gpt-5.4-mini` | Paid | `OPENAI_API_KEY` |
|
|
100
|
+
| Anthropic | `claude-3-5-haiku-latest` | Paid | `ANTHROPIC_API_KEY` |
|
|
101
|
+
| AgentRouter | `claude-opus-4-6` | Paid | `AGENTROUTER_API_KEY` |
|
|
102
|
+
| AWS Mantle | `anthropic.claude-haiku-4-5` | Paid | `ANTHROPIC_API_KEY` |
|
|
103
|
+
| Qwen Cloud | `qwen3.7-plus` | Paid (DashScope) | `DASHSCOPE_API_KEY` |
|
|
104
|
+
|
|
105
|
+
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.
|
|
106
|
+
|
|
107
|
+
### Manage keys
|
|
93
108
|
|
|
94
|
-
|
|
95
|
-
clai
|
|
109
|
+
```sh
|
|
110
|
+
clai set groq gsk_first_key # store a key (appends if one exists)
|
|
111
|
+
clai set groq gsk_second_key # add another key for the same provider
|
|
112
|
+
clai set gemini --from-env GEMINI_API_KEY
|
|
113
|
+
echo "gsk_..." | clai set groq --stdin
|
|
114
|
+
clai set ollama --url http://localhost:11434
|
|
115
|
+
clai keys # list providers + masked keys, active key marked ★
|
|
116
|
+
clai use groq # set active provider
|
|
117
|
+
clai provider # interactive provider/model picker
|
|
118
|
+
clai unset groq # remove ALL keys for a provider
|
|
96
119
|
```
|
|
97
120
|
|
|
98
|
-
|
|
121
|
+
In the console, **`/set`** opens a multi-row key editor: add rows with `+`, remove rows, **Save**, or **Reset all**. **`/keys`** lists them masked; **`/unset`** clears a provider.
|
|
122
|
+
|
|
123
|
+
### Smart switching (how it stays up)
|
|
99
124
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
125
|
+
- **Multi-key rotation** — up to **10 keys per provider**. The last key that worked is *sticky*; on failure clai rotates circularly to the next key.
|
|
126
|
+
- **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.
|
|
127
|
+
- **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).
|
|
128
|
+
- **Free-only mode** *(opt-in)* — `/freeonly on` excludes paid-cloud providers from the fallback chain, so you never accidentally spend.
|
|
129
|
+
- **Quiet status** — a single non-stacking status line shows what happened, e.g. `switching groq key [2/4] …ab12 (rate limited)`. Keys are always masked to the last 4 chars.
|
|
130
|
+
|
|
131
|
+
```sh
|
|
132
|
+
/freeonly on # stay on free tiers only
|
|
133
|
+
/fallback on # allow other providers when the current one is exhausted
|
|
107
134
|
```
|
|
108
135
|
|
|
109
136
|
---
|
|
110
137
|
|
|
111
|
-
##
|
|
138
|
+
## What clai is good at
|
|
112
139
|
|
|
113
|
-
###
|
|
140
|
+
### Building & debugging
|
|
114
141
|
|
|
115
|
-
|
|
116
|
-
|------|----------------|
|
|
117
|
-
| **Network** | `net.scan` (nmap wrapper, SYN with privilege / TCP fallback), `net.context`, `net.pingSweep`, `pentest.recon` (whois + dig + top ports) |
|
|
118
|
-
| **HTTP evidence** | `http.fetch` — status, headers, cookies, TLS, body for **raw protocol / pentest** work (not casual page reading) |
|
|
119
|
-
| **Web reading / OSINT** | `web.search`, `web.fetch` (readable pages), plus shell for specialized CLIs |
|
|
120
|
-
| **Batch recon** | `tool.batch` — up to 20 lookups in one call; optional `on_fail` fail-fast or selective cancel when dependents need a prerequisite |
|
|
121
|
-
| **Discovery** | `tool.check`, `pkg.install`, `wordlist.find` — install only what is missing; locate wordlists per OS (no Kali-only path guesses) |
|
|
122
|
-
| **DNS / ownership** | `dns.lookup`, `whois.lookup` for narrow questions |
|
|
123
|
-
| **Shell** | Full toolbox: `nmap`, `ffuf`, `gobuster`, `feroxbuster`, `sqlmap`, `hydra`, `nikto`, `masscan`, `nuclei`, `tshark`, … via `shell.exec` |
|
|
124
|
-
| **Jobs** | Long scanners/listeners as background jobs (`shell.start` / `/jobs` / `Ctrl+J`) |
|
|
125
|
-
| **Reporting** | Markdown tables, artifact paths for long scans, structured finding style (title, severity, evidence, repro, impact, remediations) |
|
|
142
|
+
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:
|
|
126
143
|
|
|
127
|
-
|
|
144
|
+
- Scaffolds and extends apps; replaces starter boilerplate with real features (a scaffold alone is treated as incomplete).
|
|
145
|
+
- Surgical file tools: `fs.edit`, `fs.replaceLines`, `fs.append`, plus multi-file writes.
|
|
146
|
+
- Runs the checks that apply — typecheck, build, unit/integration tests — and fixes failures before claiming success.
|
|
147
|
+
- Starts dev servers as background jobs, tails until ready, probes `localhost`, and reports the URL / port / job id with the server left running.
|
|
148
|
+
- Debugging loop: reproduce → read the actual error → fix root cause → re-verify (never "diagnosed but not fixed").
|
|
128
149
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
- **Verify from tool output** — no fabricated banners or fake CVE hits
|
|
134
|
-
- **Scope discipline** — flag out-of-scope hosts; keep authorized targets as the boundary
|
|
150
|
+
```sh
|
|
151
|
+
clai --mode agent "convert this Vite React app to Next.js App Router, keep all features, run the build"
|
|
152
|
+
clai --mode agent "this test is flaky — find the race and fix it"
|
|
153
|
+
```
|
|
135
154
|
|
|
136
|
-
###
|
|
155
|
+
### Scope-based pentesting & bug bounty
|
|
137
156
|
|
|
138
|
-
clai
|
|
157
|
+
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.
|
|
139
158
|
|
|
140
|
-
```
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
159
|
+
```
|
|
160
|
+
recon / discovery → fingerprint stack → plan.create (kind=pentest)
|
|
161
|
+
↑ │
|
|
162
|
+
│ /implement (approve)
|
|
163
|
+
│ ↓
|
|
164
|
+
└──── enumerate → exploit → post-ex → report
|
|
165
|
+
(revise the plan as surface grows; keep completed tasks)
|
|
144
166
|
```
|
|
145
167
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
168
|
+
1. **Authorize once**, then optionally **define scope** — authorized targets, exclusions, allowed phases, rate/concurrency ceilings, and an expiry.
|
|
169
|
+
2. **Recon first** (read-only discovery needs no plan): whois, DNS, `net.scan`, `net.context`, `http.fetch`, `pentest.recon`, and shell tools like `nmap`, `ffuf`, `nuclei`, `sqlmap`.
|
|
170
|
+
3. **Analyze real evidence**, then `plan.create` with `kind=pentest` from actual ports/services/endpoints — then stop for your approval.
|
|
171
|
+
4. `/implement` and execute task-by-task; expand the plan as new attack surface appears without wiping completed work.
|
|
172
|
+
5. **Report** with structure — title, severity, evidence, reproduction, impact, remediation — and honest residual/untested notes.
|
|
151
173
|
|
|
152
|
-
|
|
174
|
+
**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. Loopback GET/HEAD stays allowed for local dev verification. Scope is opt-in: with no scope defined, scoping is simply off.
|
|
153
175
|
|
|
154
|
-
|
|
176
|
+
```sh
|
|
177
|
+
clai authorize-pentest AGREE
|
|
178
|
+
clai scope new --targets lab.example.com,10.10.0.0/24 --exclude prod.example.com \
|
|
179
|
+
--phases recon,enumeration --max-rate 5 --max-concurrency 2
|
|
180
|
+
# in the console: /scope show · /scope add <targets> · /scope clear
|
|
181
|
+
```
|
|
155
182
|
|
|
156
|
-
|
|
157
|
-
- Full plan + notes pager (`Ctrl+P` / `/plan`)
|
|
158
|
-
- Approve with `/implement`, revise in chat, cancel with `/discard`
|
|
159
|
-
- Plans **survive context compaction** and **reload with `/history`**
|
|
160
|
-
- Agent mode: working checklist + evidence-before-done; plan mode: roadmap you approve before execution
|
|
183
|
+
Dedicated recon tools: `pentest.recon` (bundled whois/dns/nmap), `pentest.webDiscover` (scoped path discovery), `pentest.apiEnumerate` (OpenAPI/Swagger), `pentest.authCompare` (auth-context diffing), `pentest.scanStatus` (durable scan checkpoints).
|
|
161
184
|
|
|
162
|
-
|
|
185
|
+
### General security & sysadmin workflows
|
|
163
186
|
|
|
164
|
-
|
|
187
|
+
Log triage, config hardening, packaging, network questions, OCR of a screenshot or PDF report, quick OSINT — all handled by the same agent under the same safety gate.
|
|
165
188
|
|
|
166
|
-
|
|
189
|
+
---
|
|
167
190
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
| Newline | `Shift+Enter` |
|
|
172
|
-
| Abort turn | `Esc` / `Ctrl+C` (cancels in-flight tools cleanly) |
|
|
173
|
-
| Expand thinking | `Ctrl+T` (clickable on status strip) |
|
|
174
|
-
| Expand tool / compacted output | `Ctrl+O` |
|
|
175
|
-
| Plan pane | `Ctrl+H` |
|
|
176
|
-
| Full plan document | `Ctrl+P` |
|
|
177
|
-
| Background jobs | `Ctrl+J` |
|
|
178
|
-
| Commands / files | `/` · `@` |
|
|
179
|
-
| Exit | `Ctrl+C` twice |
|
|
191
|
+
## Modes & reasoning
|
|
192
|
+
|
|
193
|
+
Three modes, switchable anytime with a slash command, `Shift+Tab`, or `clai --mode`:
|
|
180
194
|
|
|
181
|
-
|
|
195
|
+
| Mode | Use |
|
|
196
|
+
|------|-----|
|
|
197
|
+
| **ask** | Answers, methodology, and read-only tools — no mutations, no attacks. |
|
|
198
|
+
| **agent** | Executes: edits, installs, scans, verifies, works the plan. |
|
|
199
|
+
| **plan** | Research and design a durable plan; approve with `/implement` before execution. |
|
|
182
200
|
|
|
183
|
-
|
|
201
|
+
**Reasoning / thinking** is controlled with `/variants` (alias `/reasoning`), accepting `on`, `off`, `none`, `minimal`, `low`, `medium`, `high`, or `xhigh`. clai only sends reasoning options to models that support them — and if a model rejects them at runtime, it marks that model, retries once without them, and tells you (`… rejected reasoning options — retrying without them`) so a session never hangs on an unsupported knob.
|
|
184
202
|
|
|
185
203
|
---
|
|
186
204
|
|
|
187
|
-
##
|
|
205
|
+
## Safety gate
|
|
188
206
|
|
|
189
|
-
|
|
190
|
-
|------|----------------|
|
|
191
|
-
| **`/agent`** | Run recon, build a pentest plan, execute after `/implement`, verify findings with tools |
|
|
192
|
-
| **`/ask`** | Methodology, commands, and writeups **without** executing tools |
|
|
207
|
+
You own authorization; clai still gates risk on every action:
|
|
193
208
|
|
|
194
|
-
|
|
209
|
+
| Level | Behavior |
|
|
210
|
+
|-------|----------|
|
|
211
|
+
| **safe** | Auto-runs read-only work: `fs.read/list/search`, `sysinfo`, `dns.lookup`, `whois.lookup`, `http.fetch` GET, `web.search`/`web.fetch`, recon scanners. |
|
|
212
|
+
| **confirm** | Asks first for mutations: file writes/edits, installs, moves, aggressive/mutating shell. |
|
|
213
|
+
| **block** | Refuses destructive patterns (`rm -rf /`, fork bombs, classic exfil signatures) and SSRF-prone fetches. |
|
|
195
214
|
|
|
196
|
-
|
|
215
|
+
`fs.delete` always confirms (with an optional `v` preview) even under allow-all. `tool.batch` inherits the highest risk level of its children. Use `/permissions` to choose the default confirmation level and `/allow` / `/disallow` for a per-session tool allow-list.
|
|
197
216
|
|
|
198
217
|
---
|
|
199
218
|
|
|
200
|
-
##
|
|
201
|
-
|
|
202
|
-
- **Pentest-first agent loop** — recon-before-plan, stack-aware enum, evidence-backed findings
|
|
203
|
-
- **Durable plans** — `plan.create` / `task.update`, side pane, approve/refine/discard; agent vs plan task workflows
|
|
204
|
-
- **Parallel multi-tool turns** — independent reads run together; failures do **not** cancel siblings by default
|
|
205
|
-
- **`tool.batch` fail policy** — opt-in `on_fail=cancel_pending` or selective `cancel_on_fail` / rules when later work depends on earlier success
|
|
206
|
-
- **Native + text tool calling** — `toolCalling: auto|native|text`
|
|
207
|
-
- **11+ LLM providers** with streaming (free tiers + local Ollama)
|
|
208
|
-
- **Safety gate** + pentest authorization + optional engagement scope (deletes always confirm with preview)
|
|
209
|
-
- **OS-aware** installs and wordlist discovery (macOS / Linux / Windows)
|
|
210
|
-
- **Context compaction** (auto + `/compact`) that keeps the plan alive
|
|
211
|
-
- **Session history** with full transcript + plan restore
|
|
212
|
-
- **Background jobs** for long scanners and listeners
|
|
213
|
-
- **Web OSINT** — `web.search` / `web.fetch` alongside raw `http.fetch`
|
|
214
|
-
- **Stall / cancel robustness** — tool heartbeats, hard deadlines, clean Esc abort with results recorded
|
|
219
|
+
## Terminal UI
|
|
215
220
|
|
|
216
|
-
|
|
221
|
+
A full-screen console by default: streaming chat, nested tool cards (including `tool.batch` sub-calls), file diffs, a live plan pane, pickers, history, and secure masked key prompts. It falls back to a classic REPL when the terminal can't host the UI.
|
|
217
222
|
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
|
221
|
-
|
|
222
|
-
|
|
|
223
|
-
|
|
|
224
|
-
|
|
|
225
|
-
|
|
|
226
|
-
|
|
|
227
|
-
|
|
|
228
|
-
|
|
|
229
|
-
|
|
|
230
|
-
|
|
|
231
|
-
| Ollama | `llama3.1:8b` | ✓ local | URL |
|
|
232
|
-
| Bynara | `mimo-v2.5-free` | ✓ | `sk_nry_` |
|
|
223
|
+
| Action | Key |
|
|
224
|
+
|--------|-----|
|
|
225
|
+
| Send / newline | `Enter` / `Shift+Enter` |
|
|
226
|
+
| Abort turn (keeps results) | `Esc` |
|
|
227
|
+
| Interrupt / quit | `Ctrl+C` (twice to quit) |
|
|
228
|
+
| Cycle mode (ask→agent→plan) | `Shift+Tab` |
|
|
229
|
+
| Plan pane / plan detail | `Ctrl+H` / `Ctrl+P` |
|
|
230
|
+
| Background jobs | `Ctrl+J` |
|
|
231
|
+
| Expand thinking / tool output | `Ctrl+T` / `Ctrl+O` |
|
|
232
|
+
| Search transcript | `Ctrl+R` |
|
|
233
|
+
| Copy selection | `Ctrl+Shift+C` |
|
|
234
|
+
| Commands / file mentions | `/` · `@` |
|
|
235
|
+
| Help / shortcuts | `Ctrl+G` |
|
|
233
236
|
|
|
234
|
-
|
|
235
|
-
clai set groq gsk_... # store / append an API key (multi-key supported)
|
|
236
|
-
clai set groq gsk_another_... # add a second key for the same provider
|
|
237
|
-
clai set gemini --from-env GEMINI_API_KEY
|
|
238
|
-
echo "gsk_..." | clai set groq --stdin
|
|
239
|
-
clai set ollama --url http://localhost:11434
|
|
240
|
-
clai keys # lists each key (masked) + sticky active ★
|
|
241
|
-
clai use groq
|
|
242
|
-
clai provider # picker shows selected model per provider
|
|
243
|
-
clai unset groq # removes ALL keys for that provider
|
|
244
|
-
```
|
|
237
|
+
Tool cards show the command/input clearly and keep long scan tails in an expandable OUTPUT pager (search, copy, export). File writes show a diff preview. Compaction cards preserve session memory without dropping the plan, and `/history` restores full sessions — prompts, tool results, and the matching plan — even after an abort or autosave.
|
|
245
238
|
|
|
246
|
-
|
|
239
|
+
---
|
|
247
240
|
|
|
248
|
-
|
|
241
|
+
## Slash commands
|
|
242
|
+
|
|
243
|
+
| Command | Does |
|
|
244
|
+
|---------|------|
|
|
245
|
+
| `/ask` · `/agent` · `/plan` | Switch mode (plan = design-then-approve) |
|
|
246
|
+
| `/implement` · `/discard` | Approve+execute or drop the current plan |
|
|
247
|
+
| `/model [name\|#]` · `/provider [name]` · `/use <provider>` | Pick model / switch provider |
|
|
248
|
+
| `/set [provider]` · `/unset [provider]` · `/keys` · `/info [provider]` | Manage API keys and view provider info |
|
|
249
|
+
| `/variants [level]` · `/reasoning [level]` | Thinking / reasoning effort |
|
|
250
|
+
| `/freeonly [on\|off]` · `/fallback [on\|off]` | Free-only filter · cross-provider fallback |
|
|
251
|
+
| `/search [provider]` · `/search-provider` | Choose web-search backend |
|
|
252
|
+
| `/scope [show\|add\|new\|clear]` | Engagement scope |
|
|
253
|
+
| `/output [last\|id\|list]` | Open full tool output (also `Ctrl+O`) |
|
|
254
|
+
| `/jobs` | Background jobs (also `Ctrl+J`) |
|
|
255
|
+
| `/compact` · `/context` | Compact history now · show context size |
|
|
256
|
+
| `/history` · `/save <name>` · `/new` · `/clear` · `/reset` | Session lifecycle |
|
|
257
|
+
| `/allow <tool>` · `/disallow <tool>` · `/permissions` | Tool permissions |
|
|
258
|
+
| `/cwd <path>` | Change working directory |
|
|
259
|
+
| `/think` · `/thinking` | Show thinking from the last response |
|
|
260
|
+
| `/privacy [...]` | Private mode · clear history/logs/artifacts |
|
|
261
|
+
| `/update` · `/help` · `/shortcuts` · `/clean` · `/exit` | Housekeeping |
|
|
249
262
|
|
|
250
263
|
---
|
|
251
264
|
|
|
252
|
-
##
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
265
|
+
## CLI commands
|
|
266
|
+
|
|
267
|
+
```sh
|
|
268
|
+
clai [prompt...] # interactive console, or one-shot with a prompt
|
|
269
|
+
--mode <ask|agent|plan> --provider <p> --model <m>
|
|
270
|
+
-y/--yes --no-history --classic --ui <legacy|tui|v2>
|
|
271
|
+
|
|
272
|
+
clai set <provider> [key] # --from-env <VAR> | --stdin | --url <url> | --skip-ping
|
|
273
|
+
clai unset <provider> # remove all keys for a provider
|
|
274
|
+
clai keys # list providers with masked keys
|
|
275
|
+
clai use <provider> # set active provider
|
|
276
|
+
clai provider [provider] # switch provider or open picker
|
|
277
|
+
clai model <model> # set model for the active provider
|
|
278
|
+
clai mode <ask|agent|plan> # set default mode
|
|
279
|
+
clai search-provider <brave|tavily|duckduckgo>
|
|
280
|
+
clai config [key] [value] # print / get / set config
|
|
281
|
+
clai doctor # check installed tools + provider config
|
|
282
|
+
clai history [--show <id>] # list sessions / print one
|
|
283
|
+
clai update # check for updates
|
|
284
|
+
clai authorize-pentest AGREE # enable scan/attack tools (one-time ack)
|
|
285
|
+
clai scope <show|new|add|clear> # engagement scope (new: --targets --exclude --phases
|
|
286
|
+
# --name --note --expires --max-rate --max-concurrency)
|
|
287
|
+
clai privacy <status|on|off|retention|clear-history|clear-logs|clear-artifacts|clear-all>
|
|
288
|
+
```
|
|
270
289
|
|
|
271
290
|
---
|
|
272
291
|
|
|
273
|
-
## Built-in tools
|
|
292
|
+
## Built-in tools
|
|
274
293
|
|
|
275
|
-
|
|
|
276
|
-
|
|
277
|
-
| `
|
|
278
|
-
| `
|
|
279
|
-
| `
|
|
280
|
-
| `web.search` · `web.fetch`
|
|
281
|
-
| `
|
|
282
|
-
| `tool.batch`
|
|
283
|
-
| `
|
|
284
|
-
|
|
|
285
|
-
| `plan.create` · `task.update` | Engagement checklist / working tasks |
|
|
286
|
-
| `sysinfo` · `image.ocr` · `pdf.read` | Host context, report/screenshot OCR |
|
|
287
|
-
| `agent.handoff` | Ask mode → offer agent mode when the user wants action, not explanation |
|
|
294
|
+
| Group | Tools |
|
|
295
|
+
|-------|-------|
|
|
296
|
+
| **Files** | `fs.read` · `fs.list` · `fs.search` · `fs.write` · `fs.writeMany` · `fs.edit` · `fs.replaceLines` · `fs.append` · `fs.delete` |
|
|
297
|
+
| **Shell & jobs** | `shell.exec` · `shell.start` · `shell.jobs` · `shell.tail` · `shell.stop` · `pkg.install` |
|
|
298
|
+
| **Network** | `net.scan` (nmap) · `net.context` · `net.pingSweep` · `dns.lookup` · `whois.lookup` |
|
|
299
|
+
| **HTTP / web** | `http.fetch` (raw evidence) · `web.search` · `web.fetch` (readable) |
|
|
300
|
+
| **Pentest** | `pentest.recon` · `pentest.webDiscover` · `pentest.apiEnumerate` · `pentest.authCompare` · `pentest.scanStatus` |
|
|
301
|
+
| **Orchestration** | `tool.batch` (up to 20 calls, `on_fail` policies) · `tool.check` · `wordlist.find` |
|
|
302
|
+
| **Plan** | `plan.create` · `task.update` · `agent.handoff` |
|
|
303
|
+
| **Context** | `sysinfo` · `image.ocr` · `pdf.read` |
|
|
288
304
|
|
|
289
|
-
###
|
|
305
|
+
### tool.batch fail policy
|
|
290
306
|
|
|
291
|
-
Default is **continue** — one failed lookup never kills the rest (
|
|
307
|
+
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:
|
|
292
308
|
|
|
293
309
|
```json
|
|
294
|
-
// Fail-fast: stop remaining calls after the first failure
|
|
295
310
|
{"name":"tool.batch","args":{
|
|
296
311
|
"on_fail":"cancel_pending",
|
|
297
312
|
"calls":[
|
|
@@ -299,21 +314,19 @@ Default is **continue** — one failed lookup never kills the rest (best for rec
|
|
|
299
314
|
{"name":"http.fetch","args":{"url":"https://lab.example/"}}
|
|
300
315
|
]
|
|
301
316
|
}}
|
|
302
|
-
|
|
303
|
-
// Selective: if scan fails, cancel only fuzz (dns still runs)
|
|
304
|
-
{"name":"tool.batch","args":{
|
|
305
|
-
"calls":[
|
|
306
|
-
{"id":"dns","name":"dns.lookup","args":{"target":"lab.example"}},
|
|
307
|
-
{"id":"scan","name":"net.scan","args":{"target":"lab.example"},
|
|
308
|
-
"cancel_on_fail":["fuzz"]},
|
|
309
|
-
{"id":"fuzz","name":"shell.exec","args":{"command":"ffuf …"}}
|
|
310
|
-
]
|
|
311
|
-
}}
|
|
312
317
|
```
|
|
313
318
|
|
|
314
|
-
Top-level
|
|
319
|
+
Top-level messages with several separate tool blocks never cancel siblings — use `tool.batch` when you need a fail policy.
|
|
320
|
+
|
|
321
|
+
---
|
|
315
322
|
|
|
316
|
-
|
|
323
|
+
## Web search / OSINT
|
|
324
|
+
|
|
325
|
+
| Provider | Key | Env var |
|
|
326
|
+
|----------|-----|---------|
|
|
327
|
+
| DuckDuckGo | none (default) | — |
|
|
328
|
+
| Brave | required | `BRAVE_SEARCH_API_KEY` |
|
|
329
|
+
| Tavily | required | `TAVILY_API_KEY` |
|
|
317
330
|
|
|
318
331
|
```sh
|
|
319
332
|
clai set brave bsx-...
|
|
@@ -321,34 +334,27 @@ clai set tavily tvly-...
|
|
|
321
334
|
clai search-provider tavily
|
|
322
335
|
```
|
|
323
336
|
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
---
|
|
327
|
-
|
|
328
|
-
## Updates & doctor
|
|
329
|
-
|
|
330
|
-
```sh
|
|
331
|
-
clai update
|
|
332
|
-
clai doctor # OS, keys, and which security tools are installed
|
|
333
|
-
```
|
|
337
|
+
Search-provider keys are multi-key and rotate just like model providers.
|
|
334
338
|
|
|
335
339
|
---
|
|
336
340
|
|
|
337
341
|
## Per-project context
|
|
338
342
|
|
|
339
|
-
`.clai/context.md` in a repo
|
|
343
|
+
Drop a `.clai/context.md` in a repo and its contents are injected every turn — lab topology, in-scope hosts, stack assumptions, coding conventions, or anything the agent should always know for that project.
|
|
340
344
|
|
|
341
345
|
---
|
|
342
346
|
|
|
343
|
-
## Configuration
|
|
347
|
+
## Configuration & privacy
|
|
344
348
|
|
|
345
349
|
```sh
|
|
346
|
-
clai config
|
|
347
|
-
clai mode agent
|
|
348
|
-
clai model <name>
|
|
350
|
+
clai config # view config
|
|
351
|
+
clai mode agent # default mode
|
|
352
|
+
clai model <name> # default model for the active provider
|
|
353
|
+
/privacy on # private mode: don't persist this session
|
|
354
|
+
/privacy clear-all # wipe history, logs, and artifacts
|
|
349
355
|
```
|
|
350
356
|
|
|
351
|
-
Config lives under
|
|
357
|
+
Config lives under your OS user config dir (e.g. `~/.config/clai/`). Keys are stored locally and shown only masked.
|
|
352
358
|
|
|
353
359
|
---
|
|
354
360
|
|
|
@@ -356,27 +362,23 @@ Config lives under the OS user config dir (e.g. `~/.config/clai/`).
|
|
|
356
362
|
|
|
357
363
|
```sh
|
|
358
364
|
npm install
|
|
359
|
-
npm run dev
|
|
365
|
+
npm run dev # run from source
|
|
360
366
|
npm run typecheck
|
|
361
367
|
npm run build
|
|
362
|
-
npm test
|
|
363
|
-
npm run compile
|
|
368
|
+
npm test # full vitest suite
|
|
369
|
+
npm run compile # native binaries (Bun)
|
|
364
370
|
```
|
|
365
371
|
|
|
366
|
-
Node.js ≥ 20.
|
|
367
|
-
|
|
368
372
|
---
|
|
369
373
|
|
|
370
374
|
## Releasing
|
|
371
375
|
|
|
372
|
-
Tag-driven CI (`.github/workflows/release.yml`): tests → multi-platform binaries → GitHub Release → npm `@pentoshi/clai` → Homebrew tap.
|
|
376
|
+
Tag-driven CI (`.github/workflows/release.yml`): validate (typecheck + tests + prompt-budget + release checks) → multi-platform binaries → GitHub Release → npm `@pentoshi/clai` → Homebrew tap.
|
|
373
377
|
|
|
374
378
|
```sh
|
|
375
|
-
#
|
|
379
|
+
# package.json "version" is the single source of truth.
|
|
376
380
|
npm version 3.8.0 --no-git-tag-version
|
|
377
|
-
|
|
378
|
-
# (also runs automatically on build / pretest / compile)
|
|
379
|
-
npm run sync-version
|
|
381
|
+
npm run sync-version # refreshes version.generated.ts + install manifests + lockfile
|
|
380
382
|
git commit -am "v3.8.0" && git push origin main
|
|
381
383
|
git tag -a v3.8.0 -m "clai v3.8.0" && git push origin v3.8.0
|
|
382
384
|
```
|
|
@@ -385,22 +387,20 @@ Secrets: `NPM_TOKEN`, `TAP_GITHUB_TOKEN`. Optional: `NPM_PROVENANCE=true`.
|
|
|
385
387
|
|
|
386
388
|
---
|
|
387
389
|
|
|
388
|
-
## Architecture
|
|
390
|
+
## Architecture
|
|
389
391
|
|
|
390
392
|
```
|
|
391
393
|
clai/
|
|
392
394
|
├─ src/
|
|
393
|
-
│ ├─ index.ts
|
|
394
|
-
│ ├─
|
|
395
|
-
│ ├─
|
|
396
|
-
│ ├─
|
|
397
|
-
│ ├─
|
|
398
|
-
│ ├─
|
|
399
|
-
│ ├─
|
|
400
|
-
│ ├─
|
|
401
|
-
│
|
|
402
|
-
│ └─ prompts/ # agent methodology (incl. pentest; embedded for bun)
|
|
403
|
-
├─ bin/clai.mjs
|
|
395
|
+
│ ├─ index.ts # CLI entry + subcommands
|
|
396
|
+
│ ├─ agent/ # loop, plans, compaction, resume orientation, tool parsing
|
|
397
|
+
│ ├─ llm/ # 12 providers, streaming, native tools, key rotation + fallback
|
|
398
|
+
│ ├─ tools/ # fs, shell, net, http, web, pentest, batch, plan
|
|
399
|
+
│ ├─ safety/ # risk classifier + engagement (scope) policy
|
|
400
|
+
│ ├─ store/ # config, history, keys, plans, scope
|
|
401
|
+
│ ├─ tui-v2/ # full-screen OpenTUI console (primary)
|
|
402
|
+
│ ├─ app/ # session controllers, commands, events
|
|
403
|
+
│ └─ prompts/ # agent methodology (embedded for the compiled binary)
|
|
404
404
|
├─ install/ · manifests/
|
|
405
405
|
└─ package.json
|
|
406
406
|
```
|
|
@@ -409,8 +409,6 @@ clai/
|
|
|
409
409
|
|
|
410
410
|
## License
|
|
411
411
|
|
|
412
|
-
MIT
|
|
413
|
-
|
|
414
|
-
---
|
|
412
|
+
MIT.
|
|
415
413
|
|
|
416
|
-
**Use only on systems you are authorized to test.** clai is an operator tool: authorization, scope, and impact are yours
|
|
414
|
+
**Use only on systems you are authorized to test.** clai is an operator's tool: authorization, scope, and impact are yours. The agent executes with the gates and confirmations you configure — nothing more.
|