privateer-agent 0.2.1 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +135 -443
- package/bin/privateer-tui +86 -0
- package/bin/privateer.mjs +17 -6
- package/bin/pv +28 -0
- package/package.json +26 -23
- package/src/auth/privateer.ts +57 -0
- package/src/boot.ts +43 -0
- package/src/bridge/engineAdapter.ts +182 -0
- package/src/cli/chat.ts +243 -0
- package/src/config/paths.ts +24 -46
- package/src/config/permissionMode.ts +5 -0
- package/src/crypto/outboxSeal.ts +61 -0
- package/src/daemon/index.ts +204 -121
- package/src/daemon/ipc.ts +1 -1
- package/src/engine/errors.ts +85 -45
- package/src/engine/router.ts +11 -165
- package/src/ext/permissionGate.ts +216 -0
- package/src/main.ts +32 -0
- package/src/permissions/classify.ts +172 -0
- package/src/permissions/gate.ts +11 -14
- package/src/permissions/mode.ts +6 -2
- package/src/permissions/{uiGate.ts → modeGate.ts} +18 -3
- package/src/providers/account.ts +170 -0
- package/src/providers/catalog.ts +73 -61
- package/src/providers/genModelsJson.ts +97 -0
- package/src/remote/relayClient.ts +15 -0
- package/src/remote/remoteBridge.ts +152 -0
- package/src/routines/delivery.ts +118 -9
- package/src/routines/schema.ts +24 -5
- package/src/routines/store.ts +44 -1
- package/src/routines/toolSelect.ts +3 -1
- package/src/session.ts +81 -273
- package/src/tools/routine.ts +120 -101
- package/src/tools/saveAttachment.ts +39 -42
- package/src/tools/sendFile.ts +75 -0
- package/src/util/attachmentStore.ts +18 -35
- package/src/util/redact.ts +33 -3
- package/LICENSE +0 -21
- package/src/agents/loader.ts +0 -49
- package/src/commands/custom.ts +0 -123
- package/src/commands/registry.ts +0 -618
- package/src/components/AgentGroupView.tsx +0 -104
- package/src/components/App.tsx +0 -1626
- package/src/components/ApprovalPrompt.tsx +0 -49
- package/src/components/Banner.tsx +0 -78
- package/src/components/Markdown.tsx +0 -183
- package/src/components/ModeHint.tsx +0 -40
- package/src/components/ModelPicker.tsx +0 -302
- package/src/components/Onboarding.tsx +0 -203
- package/src/components/OptionPicker.tsx +0 -134
- package/src/components/PlanConfirm.tsx +0 -37
- package/src/components/PrivateerLogin.tsx +0 -109
- package/src/components/PromptInput.tsx +0 -602
- package/src/components/RewindPicker.tsx +0 -69
- package/src/components/Root.tsx +0 -116
- package/src/components/SessionPicker.tsx +0 -64
- package/src/components/StatusBar.tsx +0 -131
- package/src/components/TodoPanel.tsx +0 -36
- package/src/components/ToolCallView.tsx +0 -113
- package/src/components/Transcript.tsx +0 -210
- package/src/components/figures.ts +0 -14
- package/src/components/promptModel.ts +0 -73
- package/src/components/spinnerVerbs.ts +0 -46
- package/src/components/theme.ts +0 -57
- package/src/components/types.ts +0 -34
- package/src/components/useTeeShield.ts +0 -104
- package/src/components/useTerminalWidth.ts +0 -24
- package/src/components/useZdrShield.ts +0 -126
- package/src/config/load.ts +0 -115
- package/src/config/schema.ts +0 -94
- package/src/context/outputStyles.ts +0 -42
- package/src/context/projectInfo.ts +0 -59
- package/src/context/systemPrompt.ts +0 -176
- package/src/engine/QueryEngine.ts +0 -399
- package/src/hooks/engine.ts +0 -155
- package/src/main.tsx +0 -209
- package/src/mcp/client.ts +0 -251
- package/src/mcp/oauth.ts +0 -245
- package/src/memory/auto.ts +0 -146
- package/src/memory/checkpoints.ts +0 -227
- package/src/memory/store.ts +0 -127
- package/src/providers/attestation.ts +0 -149
- package/src/providers/capabilities.ts +0 -104
- package/src/providers/models.ts +0 -183
- package/src/providers/registry.ts +0 -71
- package/src/providers/resolve.ts +0 -78
- package/src/skills/installer.ts +0 -222
- package/src/skills/loader.ts +0 -88
- package/src/tools/askUser.ts +0 -92
- package/src/tools/bash.ts +0 -98
- package/src/tools/context.ts +0 -128
- package/src/tools/edit.ts +0 -67
- package/src/tools/exec.ts +0 -60
- package/src/tools/glob.ts +0 -39
- package/src/tools/grep.ts +0 -86
- package/src/tools/index.ts +0 -83
- package/src/tools/memory.ts +0 -53
- package/src/tools/processRegistry.ts +0 -77
- package/src/tools/read.ts +0 -42
- package/src/tools/sendFileToClient.ts +0 -55
- package/src/tools/skill.ts +0 -44
- package/src/tools/task.ts +0 -52
- package/src/tools/todo.ts +0 -36
- package/src/tools/todoStore.ts +0 -31
- package/src/tools/walk.ts +0 -44
- package/src/tools/web.ts +0 -145
- package/src/tools/worktree.ts +0 -145
- package/src/tools/write.ts +0 -40
- package/src/util/images.ts +0 -378
- package/src/util/limit.ts +0 -32
- package/src/version.ts +0 -13
package/README.md
CHANGED
|
@@ -5,20 +5,18 @@
|
|
|
5
5
|
<h1 align="center">⚓ Privateer</h1>
|
|
6
6
|
|
|
7
7
|
<p align="center">
|
|
8
|
-
<strong>A provider-agnostic terminal coding agent — bring your own model.</strong>
|
|
8
|
+
<strong>A provider-agnostic terminal coding agent — bring your own model, keep your own privacy.</strong>
|
|
9
9
|
</p>
|
|
10
10
|
|
|
11
11
|
<p align="center">
|
|
12
|
-
<a href="https://github.com/privateer-agent/privateer-agent/actions/workflows/ci.yml">
|
|
13
|
-
<img src="https://github.com/privateer-agent/privateer-agent/actions/workflows/ci.yml/badge.svg" alt="CI" />
|
|
14
|
-
</a>
|
|
15
12
|
<a href="https://www.npmjs.com/package/privateer-agent">
|
|
16
13
|
<img src="https://img.shields.io/npm/v/privateer-agent" alt="npm" />
|
|
17
14
|
</a>
|
|
18
|
-
<img src="https://img.shields.io/badge/node-%E2%89%
|
|
15
|
+
<img src="https://img.shields.io/badge/node-%E2%89%A522.19-brightgreen" alt="Node >= 22.19" />
|
|
19
16
|
<img src="https://img.shields.io/badge/license-MIT-blue" alt="MIT License" />
|
|
20
|
-
<img src="https://img.shields.io/badge/
|
|
21
|
-
<img src="https://img.shields.io/badge/
|
|
17
|
+
<img src="https://img.shields.io/badge/permissions-safe%20by%20default-2ea44f" alt="Safe by default" />
|
|
18
|
+
<img src="https://img.shields.io/badge/inference-TEE%20attested%20·%20on--device%20PII%20gate-5b8def" alt="Private inference" />
|
|
19
|
+
<img src="https://img.shields.io/badge/providers-OpenRouter%20·%20Anthropic%20·%20OpenAI%20·%20Google%20·%20xAI%20·%20Groq%20·%20Mistral%20·%20Z.ai%20·%20DeepSeek%20·%20Qwen%20·%20Ollama%20·%20NEAR%20AI%20·%20Tinfoil%20·%20Venice-5b8def" alt="Providers" />
|
|
22
20
|
</p>
|
|
23
21
|
|
|
24
22
|
```bash
|
|
@@ -26,75 +24,69 @@ curl -fsSL https://privateer.pro/install.sh | sh # installs the `privateer` c
|
|
|
26
24
|
npx privateer-agent # or run it instantly, nothing installed
|
|
27
25
|
```
|
|
28
26
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
27
|
+
Point it at a frontier model today and a local Ollama model tomorrow — **OpenRouter**,
|
|
28
|
+
**Anthropic**, **OpenAI**, **Google**, **xAI**, **Groq**, **Mistral**, **Z.ai** (GLM),
|
|
29
|
+
**DeepSeek**, **Qwen**, local **Ollama**, **NEAR AI** or **Tinfoil** (verifiable TEE
|
|
30
|
+
inference), **Venice** / **Fireworks** (no-retention inference), and any **custom
|
|
31
|
+
OpenAI-compatible endpoint** (LM Studio, vLLM, llama.cpp…) are interchangeable at
|
|
32
|
+
`/model` time, including mid-session. No model lock-in, no separate code paths. MCP
|
|
33
|
+
servers, sub-agents, scheduled routines, and one-tap approval from your phone are
|
|
34
|
+
included — and every one of the agent's actions runs through a **safe-by-default
|
|
35
|
+
permission gate**.
|
|
38
36
|
|
|
39
37
|
## Why Privateer?
|
|
40
38
|
|
|
41
|
-
- **No lock-in.**
|
|
42
|
-
|
|
43
|
-
- **No API key required.** Bring your own key
|
|
44
|
-
|
|
45
|
-
- **
|
|
46
|
-
commands
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
39
|
+
- **No lock-in.** One agent, every provider. `/model` swaps mid-session and your config,
|
|
40
|
+
commands, and agents come along for the ride. No vendor's models are privileged.
|
|
41
|
+
- **No API key required.** Bring your own key from any supported provider, run keyless
|
|
42
|
+
against a local Ollama — or `/signin` to bill a Privateer account instead.
|
|
43
|
+
- **Safe by default.** Every edit, shell command, and network call is classified and gated
|
|
44
|
+
before it runs; destructive commands are blocked even in unattended runs. You stay in
|
|
45
|
+
control, whether you're watching or not.
|
|
46
|
+
- **Privacy you can verify, not just trust.** Confidential-enclave (TEE) inference is
|
|
47
|
+
cryptographically **attested** — not a policy promise — and an **on-device PII gate**
|
|
48
|
+
warns before structured personal data ever leaves your machine for an unverified model.
|
|
49
|
+
- **Genuinely extensible.** MCP servers, sub-agents, custom commands, and skills — all just
|
|
50
|
+
files. Nothing to compile.
|
|
51
51
|
|
|
52
52
|
## Highlights
|
|
53
53
|
|
|
54
|
-
- **
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
- **
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
-
|
|
67
|
-
|
|
68
|
-
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
54
|
+
- **Private, verifiable inference** via **NEAR AI** and **Tinfoil**: every model runs inside
|
|
55
|
+
a Trusted Execution Environment, a live status shield reflects the attestation, and
|
|
56
|
+
`/verify` fetches and checks the cryptographic report on demand — genuine proof the
|
|
57
|
+
inference ran on real confidential hardware, not a terms-of-service page.
|
|
58
|
+
- **On-device PII gate.** Before a prompt goes to an *unverified* channel, Privateer scans it
|
|
59
|
+
locally for structured personal data (emails, phone numbers, SSNs, cards, IBANs, IPs…) and
|
|
60
|
+
offers to redact or hold it — detection never leaves your machine, and an attested TEE
|
|
61
|
+
channel skips the check because it provably can't read your data anyway.
|
|
62
|
+
- **Honest privacy posture, graded.** A verified TEE and a "we promise not to retain"
|
|
63
|
+
policy are **never rendered the same** — the badge tells you exactly how strong the
|
|
64
|
+
guarantee is (cryptographically verified → observable → policy → none).
|
|
65
|
+
- **Approve it from your phone.** Link the terminal to the Privateer app with
|
|
66
|
+
`/remote-access` (off by default) and Allow/Deny every action remotely while execution
|
|
67
|
+
stays on your machine — supervise long agent runs from anywhere.
|
|
68
|
+
- **Scheduled routines.** A background daemon runs approved tasks unattended — cron or
|
|
69
|
+
one-off — and the agent can schedule its own follow-up work. Results deliver to a file,
|
|
70
|
+
the next session, your phone, email, or a webhook.
|
|
71
|
+
- **MCP servers, sub-agents & skills.** Connect Model Context Protocol servers (local stdio
|
|
72
|
+
or remote HTTP with OAuth), delegate work to bounded parallel sub-agents, and drop in
|
|
73
|
+
skills — all gated like everything else.
|
|
74
|
+
- **Zero-Data-Retention surfacing** for OpenRouter — see the selected model's retention
|
|
75
|
+
posture before you send, and pin routing to zero-retention endpoints.
|
|
76
|
+
- **Plan mode**, checkpoint/rewind, session branching, a modal prompt with `/` command and
|
|
77
|
+
`@` file autocomplete, `!` shell passthrough, background shells, and image attachment for
|
|
78
|
+
vision-capable models.
|
|
74
79
|
|
|
75
80
|
## Quickstart
|
|
76
81
|
|
|
77
82
|
```bash
|
|
78
83
|
curl -fsSL https://privateer.pro/install.sh | sh # or: npm install -g privateer-agent
|
|
79
|
-
export OPENROUTER_API_KEY=sk-or-... # one provider is enough — or skip and
|
|
80
|
-
privateer # launches the interactive
|
|
84
|
+
export OPENROUTER_API_KEY=sk-or-... # one provider is enough — or skip and /signin
|
|
85
|
+
privateer # launches the interactive agent
|
|
81
86
|
```
|
|
82
87
|
|
|
83
88
|
First run walks you through picking a provider and default model. From there, just type.
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
## Contents
|
|
87
|
-
|
|
88
|
-
- [Requirements](#requirements) · [Install](#install) · [Configure a provider](#configure-a-provider) · [Model routing](#model-routing) · [Data retention (ZDR)](#data-retention-zdr) · [Private inference (NEAR AI)](#private-inference-near-ai) · [Privateer account](#privateer-account-billed-inference--what-it-sees) · [Usage](#usage)
|
|
89
|
-
- [The prompt](#the-prompt) · [Slash commands](#slash-commands) · [Tools](#tools)
|
|
90
|
-
- [Customize & extend](#customize--extend) · [Permission modes](#permission-modes) · [Project context](#project-context)
|
|
91
|
-
- [How it compares](#how-it-compares) · [Develop](#develop) · [Caveats](#caveats) · [Docs](#docs) · [License](#license)
|
|
92
|
-
|
|
93
|
-
## Requirements
|
|
94
|
-
|
|
95
|
-
- macOS or Linux
|
|
96
|
-
- Node.js ≥ 20 (pure Node, zero binary dependencies)
|
|
97
|
-
- An API key for at least one provider — or a local Ollama install, or a Privateer account (`/login`)
|
|
89
|
+
No install at all: `npx privateer-agent`.
|
|
98
90
|
|
|
99
91
|
## Install
|
|
100
92
|
|
|
@@ -102,348 +94,95 @@ First run walks you through picking a provider and default model. From there, ju
|
|
|
102
94
|
npm install -g privateer-agent # installs the `privateer` command
|
|
103
95
|
# or run it without installing:
|
|
104
96
|
npx privateer-agent
|
|
105
|
-
# or the one-liner installer (verifies Node
|
|
97
|
+
# or the one-liner installer (verifies Node, then installs globally):
|
|
106
98
|
curl -fsSL https://privateer.pro/install.sh | sh
|
|
107
99
|
```
|
|
108
100
|
|
|
109
|
-
**
|
|
101
|
+
**Requirements:** macOS or Linux, Node.js ≥ 22.19.0.
|
|
102
|
+
|
|
103
|
+
**From source:**
|
|
110
104
|
|
|
111
105
|
```bash
|
|
112
106
|
git clone https://github.com/privateer-agent/privateer-agent.git
|
|
113
107
|
cd privateer-agent
|
|
114
|
-
npm install
|
|
115
|
-
npm start
|
|
116
|
-
npm link # optional: put your local `privateer` on PATH
|
|
108
|
+
npm install
|
|
109
|
+
npm start # launches the interactive agent
|
|
117
110
|
```
|
|
118
111
|
|
|
119
112
|
## Configure a provider
|
|
120
113
|
|
|
121
|
-
Privateer reads credentials from environment variables or
|
|
122
|
-
|
|
123
|
-
**Env vars (quickest):**
|
|
114
|
+
Privateer reads credentials from environment variables (or sign in to an account and skip
|
|
115
|
+
keys entirely). One provider is enough to start:
|
|
124
116
|
|
|
125
117
|
```bash
|
|
126
118
|
export OPENROUTER_API_KEY=sk-or-... # gateway to ~everything
|
|
127
119
|
export ANTHROPIC_API_KEY=sk-ant-...
|
|
128
120
|
export OPENAI_API_KEY=sk-...
|
|
129
|
-
export
|
|
130
|
-
export
|
|
121
|
+
export GEMINI_API_KEY=AIza... # Google
|
|
122
|
+
export XAI_API_KEY=xai-... # xAI (Grok)
|
|
123
|
+
export GROQ_API_KEY=gsk_... # Groq
|
|
124
|
+
export DEEPSEEK_API_KEY=sk-... # DeepSeek
|
|
125
|
+
export OLLAMA_BASE_URL=http://localhost:11434/v1 # local, keyless
|
|
126
|
+
export NEAR_AI_API_KEY=... # verifiable TEE inference (cloud.near.ai)
|
|
127
|
+
export TINFOIL_API_KEY=... # verifiable TEE inference (tinfoil.sh)
|
|
128
|
+
export VENICE_API_KEY=vapi_... # no-retention inference
|
|
131
129
|
```
|
|
132
130
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
"defaultModel": "openrouter:anthropic/claude-opus-4.8",
|
|
138
|
-
"permissionMode": "default",
|
|
139
|
-
"providers": {
|
|
140
|
-
"openrouter": { "apiKey": "sk-or-..." },
|
|
141
|
-
"anthropic": { "apiKey": "sk-ant-..." }
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
```
|
|
131
|
+
Pick a model with **`/model`** (browse each configured provider's live catalog) or pass one
|
|
132
|
+
directly as `provider/model` — e.g. `openrouter/anthropic/claude-opus-4.8`,
|
|
133
|
+
`ollama/qwen3-coder`, `nearai/zai-org/GLM-5.1-FP8`. Any OpenAI-compatible server (LM Studio,
|
|
134
|
+
vLLM, llama.cpp) works as a custom provider — just give it a base URL.
|
|
145
135
|
|
|
146
136
|
Override the config location with `PRIVATEER_HOME`.
|
|
147
137
|
|
|
148
|
-
##
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
a turn is routed, the transcript shows a line like `↪ routed to gemini-2.5-flash ·
|
|
197
|
-
image input`.
|
|
198
|
-
|
|
199
|
-
**Hybrid auto-detect** (`"auto": true`, the default): if you reference, say, a PDF but
|
|
200
|
-
haven't set `router.document`, and your `defaultModel` can't read PDFs, Privateer
|
|
201
|
-
auto-selects a capable model from a configured provider. Set the route explicitly to
|
|
202
|
-
control exactly which model is used, or `"auto": false` to disable it (you'll get a
|
|
203
|
-
one-line warning when nothing can handle the modality).
|
|
204
|
-
|
|
205
|
-
## Data retention (ZDR)
|
|
206
|
-
|
|
207
|
-
When you route through **OpenRouter**, where your prompts end up depends on which upstream
|
|
208
|
-
endpoint serves the request — some retain data, some don't. Privateer surfaces that for the
|
|
209
|
-
**selected model** so you can see the posture before you send, and optionally enforce it.
|
|
210
|
-
|
|
211
|
-
**The status-bar shield.** A `⛉ ZDR` badge sits in the status line, colored against the
|
|
212
|
-
model you have selected:
|
|
213
|
-
|
|
214
|
-
| Badge | Meaning |
|
|
215
|
-
|---|---|
|
|
216
|
-
| 🟢 `⛉ ZDR` | The model has a zero-retention endpoint **and** enforcement is on — the request is pinned to it, so prompts can't be retained. |
|
|
217
|
-
| 🟡 `⛉ ZDR` | A zero-retention endpoint exists, but enforcement is off — a request *may* still land on an endpoint that retains prompts. |
|
|
218
|
-
| 🔴 `⛉ ZDR` | No zero-retention endpoint for this model, or it's blocked by your account's privacy settings — under enforcement the request is rejected outright. |
|
|
219
|
-
| `⛉ ZDR?` (dim) | Posture unknown — no OpenRouter key yet, still loading, or the lookup failed. |
|
|
220
|
-
|
|
221
|
-
The badge only appears for OpenRouter models; other providers show nothing. The posture is
|
|
222
|
-
derived from two authenticated OpenRouter endpoints — `/endpoints/zdr` (models with at least
|
|
223
|
-
one zero-retention endpoint) and `/models/user` (models your account's privacy settings
|
|
224
|
-
actually permit) — fetched once per account and re-evaluated synchronously as you switch
|
|
225
|
-
models. The same colors annotate every row in the `/model` picker, with a legend explaining
|
|
226
|
-
them.
|
|
227
|
-
|
|
228
|
-
**Enforcement.** Run **`/zdr`** to toggle enforcement (persisted as
|
|
229
|
-
`providers.openrouter.enforceZdr`). With it on, Privateer pins routing to zero-retention
|
|
230
|
-
endpoints (`provider.zdr` on every request), so yellow models go green — and any model
|
|
231
|
-
*without* a zero-retention endpoint is rejected rather than silently retained. Toggle it off
|
|
232
|
-
to let OpenRouter route freely. Enforcement applies to OpenRouter only; add an OpenRouter key
|
|
233
|
-
with `/login` first.
|
|
234
|
-
|
|
235
|
-
## Private inference (NEAR AI)
|
|
236
|
-
|
|
237
|
-
**NEAR AI Cloud** runs every model inside a **Trusted Execution Environment** — an Intel TDX
|
|
238
|
-
confidential VM paired with an NVIDIA confidential-computing GPU. Your prompts are encrypted
|
|
239
|
-
all the way into the enclave (TLS terminates *inside* the TEE, not at a load balancer), so
|
|
240
|
-
the model's inputs, weights, and outputs are invisible to the infrastructure provider, the
|
|
241
|
-
model provider, and NEAR itself. And it's not "trust us": each request can produce a
|
|
242
|
-
**cryptographic attestation** attesting that the inference happened on genuine TEE hardware,
|
|
243
|
-
signed by a key that never leaves the enclave and bound to a nonce you supply. (Privateer's
|
|
244
|
-
`/verify` does a pragmatic check of that report; full validation of the quote chains is done
|
|
245
|
-
with the NEAR Cloud Verifier — see `/verify` below.)
|
|
246
|
-
|
|
247
|
-
It's a drop-in OpenAI-compatible provider — pick a `nearai:*` model with `/model` (e.g.
|
|
248
|
-
`nearai:zai-org/GLM-5.1-FP8`) and everything else works as usual.
|
|
249
|
-
|
|
250
|
-
**The status-bar shield.** A `⛉ TEE` badge appears whenever a NEAR AI model is selected,
|
|
251
|
-
colored by the live attestation for that model:
|
|
252
|
-
|
|
253
|
-
| Badge | Meaning |
|
|
254
|
-
|---|---|
|
|
255
|
-
| 🟢 `⛉ TEE` | A fresh attestation came back bound to our nonce, with a TEE signing key and NVIDIA + Intel hardware evidence — confidential **and** verifiable. |
|
|
256
|
-
| 🟡 `⛉ TEE` | A report returned but couldn't be fully confirmed here (missing signing key, hardware marker, or nonce echo). |
|
|
257
|
-
| 🔴 `⛉ TEE` | No attestation material returned. |
|
|
258
|
-
| `⛉ TEE?` (dim) | Unknown — no NEAR AI key yet, still loading, or the lookup failed. |
|
|
259
|
-
|
|
260
|
-
**`/verify`.** Run it on a NEAR AI model to fetch the attestation on demand and print the
|
|
261
|
-
verdict, detected hardware, the enclave's signing address, and the nonce. Privateer does a
|
|
262
|
-
pragmatic freshness + presence check suited to a terminal; for full validation of the raw
|
|
263
|
-
NVIDIA/Intel quote chains, take the printed report to the
|
|
264
|
-
[NEAR AI Cloud Verifier](https://github.com/nearai/cloud-verifier).
|
|
265
|
-
|
|
266
|
-
## Privateer account (billed inference) — what it sees
|
|
267
|
-
|
|
268
|
-
Instead of bringing your own provider key, run **`/login`** to sign into a Privateer account
|
|
269
|
-
(an app-brokered device flow — you approve a short code in the Privateer app/web, so wallet
|
|
270
|
-
and email accounts work identically and no password or wallet key ever touches the terminal).
|
|
271
|
-
Inference then runs on Privateer's server and is billed to your subscription.
|
|
272
|
-
|
|
273
|
-
What that means for your data, precisely:
|
|
274
|
-
|
|
275
|
-
- **The server proxies your prompts; it does not store them.** Like the Privateer apps, the
|
|
276
|
-
account path sends your prompt to the server, which forwards it to the model provider and
|
|
277
|
-
streams the reply back. The only thing written server-side is **billing metadata** — model
|
|
278
|
-
id, token counts, cost — never prompt or response text, and nothing is logged in plaintext.
|
|
279
|
-
- **Same privacy guarantee as the apps: ZDR / TEE, not in-transit E2EE.** The server has to
|
|
280
|
-
read your prompt to run inference (true of every product, every path). The guarantee isn't
|
|
281
|
-
"nobody sees it" — it's "nobody *retains* it": OpenRouter routes are pinned to zero-retention
|
|
282
|
-
endpoints, and the account default is a **NEAR TEE** model where even the provider can't read
|
|
283
|
-
the prompt. Run **`/verify`** to check the live attestation — a pragmatic freshness + presence
|
|
284
|
-
check (signing key + hardware markers + your nonce echoed); for full cryptographic validation
|
|
285
|
-
of the raw quote chains, take the printed report to the NEAR AI Cloud Verifier (see above).
|
|
286
|
-
- **Your local transcript is plaintext on your machine.** Privateer's end-to-end encryption
|
|
287
|
-
protects data **at rest in Privateer's storage** — it does not (and cannot) encrypt the
|
|
288
|
-
conversation files this CLI keeps on your own disk under `~/.privateer/`. Treat them like any
|
|
289
|
-
local shell history.
|
|
290
|
-
- **Your session token is stored unencrypted on disk** at `~/.privateer/credentials.json`,
|
|
291
|
-
protected only by file permissions (`0600` — readable just by your user). It's a scoped
|
|
292
|
-
session — not your password or wallet/encryption keys — and it's long-lived: anyone who can
|
|
293
|
-
read that file (root, a backup, a compromised account) has a usable billed session until it's
|
|
294
|
-
revoked. It rotates on refresh with server-side reuse detection; revoke it any time from the
|
|
295
|
-
app (**Settings → Linked terminals**, which now lists individual terminals) or with **`/logout`**.
|
|
296
|
-
- **`/remote-access` streams this terminal's activity to your phone.** When you turn it on, the
|
|
297
|
-
app can drive this terminal: prompts come down, and the agent's replies **and tool input/output**
|
|
298
|
-
go up through the Privateer server relay so you can watch and approve actions remotely. Output is
|
|
299
|
-
size-truncated and run through a best-effort secret redactor before it leaves, but that's a safety
|
|
300
|
-
net, not a guarantee — terminal output can contain whatever a command prints. The relay is
|
|
301
|
-
live-only (nothing is archived) and carries no keys; the terminal label sent is a non-PII random
|
|
302
|
-
tag (no username/host/path). It's **off** until you run `/remote-access on`.
|
|
303
|
-
|
|
304
|
-
> **Only approve a code you generated yourself.** The login code authorizes *this* terminal to
|
|
305
|
-
> spend on your account. If someone sends you a code and asks you to approve it ("paste this to
|
|
306
|
-
> activate…"), **don't** — approving it hands *them* a billed session on *your* account. A code
|
|
307
|
-
> you didn't just create in your own terminal is an attack, not a convenience.
|
|
308
|
-
|
|
309
|
-
## Usage
|
|
310
|
-
|
|
311
|
-
```bash
|
|
312
|
-
privateer # interactive TUI with the default model
|
|
313
|
-
privateer -m openrouter:anthropic/claude-opus-4.8
|
|
314
|
-
privateer -c # resume the last session in this dir
|
|
315
|
-
privateer -p "summarize src/" # headless one-shot, prints to stdout
|
|
316
|
-
```
|
|
317
|
-
|
|
318
|
-
Run `/model` (no argument) to browse the models each configured provider actually
|
|
319
|
-
offers — the list is fetched live using the API key you entered, then filtered as you
|
|
320
|
-
type. Onboarding ends on the same picker so you choose your default model up front.
|
|
321
|
-
|
|
322
|
-
You can also pass a model string directly as `provider:model`:
|
|
323
|
-
|
|
324
|
-
| Example | |
|
|
325
|
-
|---|---|
|
|
326
|
-
| `openrouter:anthropic/claude-opus-4.8` | any model on OpenRouter |
|
|
327
|
-
| `anthropic:claude-opus-4-8` | direct Anthropic |
|
|
328
|
-
| `openai:gpt-5.5` | direct OpenAI |
|
|
329
|
-
| `ollama:qwen3-coder` | local model |
|
|
330
|
-
|
|
331
|
-
## The prompt
|
|
332
|
-
|
|
333
|
-
The input is modal — the first character chooses what happens:
|
|
334
|
-
|
|
335
|
-
| Prefix | Mode |
|
|
336
|
-
|---|---|
|
|
337
|
-
| _(text)_ | a normal prompt to the model |
|
|
338
|
-
| `/` | a slash command — opens an autocomplete menu |
|
|
339
|
-
| `@` | a file mention — fuzzy-completes paths from the cwd |
|
|
340
|
-
| `!` | run a shell command locally and show its output (no model turn) |
|
|
341
|
-
| `#` | append the rest of the line to `PRIVATEER.md` |
|
|
342
|
-
|
|
343
|
-
Also: **↑/↓** history, **ctrl-r** reverse history search, emacs line editing
|
|
344
|
-
(`ctrl-a/e/u/w`), `ctrl-l` to clear the screen, and **`\`+Enter** for a newline. Messages
|
|
345
|
-
typed while the agent is busy are queued and run in order. `/vim` toggles modal (vim)
|
|
346
|
-
editing. Reference an image file to attach it for vision-capable models — by `@`-mention
|
|
347
|
-
(`@screenshot.png`), or by pasting a path anywhere in the prompt. Absolute paths and paths
|
|
348
|
-
with spaces work too, quoted (`"/Users/me/My Shot.png"`) or backslash-escaped
|
|
349
|
-
(`/Users/me/My\ Shot.png`); a leading `/path/...` is treated as a file, not a command. Each
|
|
350
|
-
referenced image collapses to a short `[Image #1]` chip in the transcript (numbered across
|
|
351
|
-
the session) while the picture itself rides along to the model.
|
|
352
|
-
|
|
353
|
-
While the agent is working, press **Esc** to interrupt the turn (partial output is kept);
|
|
354
|
-
**Ctrl-C** quits.
|
|
355
|
-
|
|
356
|
-
## Slash commands
|
|
357
|
-
|
|
358
|
-
Built-ins (plus any custom commands you add):
|
|
359
|
-
|
|
360
|
-
| Command | |
|
|
361
|
-
|---|---|
|
|
362
|
-
| `/help` `/doctor` `/config` | help, diagnostics, resolved settings layers |
|
|
363
|
-
| `/model [spec]` `/provider` `/keys` | choose a model, list providers, manage API keys |
|
|
364
|
-
| `/login` `/logout` | sign a Privateer account in/out (see [Privateer account](#privateer-account-billed-inference--what-it-sees)) |
|
|
365
|
-
| `/remote-access [on\|off\|status]` | link this terminal to the Privateer app for phone approval (off by default) |
|
|
366
|
-
| `/permissions [mode]` `/cost` `/context` | permission mode, token usage, context window |
|
|
367
|
-
| `/init` `/memory` `/todo` | write/show `PRIVATEER.md`; show the task list |
|
|
368
|
-
| `/agents` `/mcp [logout]` `/hooks` | inspect sub-agents; MCP status / clear OAuth; hooks |
|
|
369
|
-
| `/skills [list\|info\|install\|remove]` | manage skills (see [Customize & extend](#customize--extend)) |
|
|
370
|
-
| `/routine [list\|pause\|resume\|rm\|run]` | manage scheduled routines |
|
|
371
|
-
| `/output-style [name]` `/vim` `/verbose` | persona, modal editing, full tool output |
|
|
372
|
-
| `/zdr` | toggle OpenRouter zero-data-retention enforcement (see [Data retention](#data-retention-zdr)) |
|
|
373
|
-
| `/verify` | fetch the NEAR AI TEE attestation for the current model (see [Private inference](#private-inference-near-ai)) |
|
|
374
|
-
| `/rewind` `/compact` `/clear` `/export` | restore a checkpoint, compact, clear, save transcript |
|
|
375
|
-
| `/resume` `/sessions` | pick up an earlier session in this directory |
|
|
376
|
-
| `/exit` | quit |
|
|
377
|
-
|
|
378
|
-
- `/model` — open a picker of each provider's live models (or `/model provider:id` to set one directly).
|
|
379
|
-
- `/init` — the agent explores the repo and writes a `PRIVATEER.md` for you
|
|
380
|
-
(`/init --stub` just drops an empty template, no model call).
|
|
381
|
-
- `/rewind` — pick an earlier checkpoint and restore the conversation, the files, or both.
|
|
382
|
-
- `/compact` — summarize older history to reclaim context (also happens automatically).
|
|
383
|
-
|
|
384
|
-
## Tools
|
|
385
|
-
|
|
386
|
-
`read` · `write` · `edit` · `glob` · `grep` · `bash` · `bash_output` · `kill_shell` ·
|
|
387
|
-
`todo` · `task` · `web_fetch` · `web_search` — plus any tools exposed by connected MCP servers.
|
|
388
|
-
|
|
389
|
-
The file/search/shell tools are pure-Node (no external binaries required). Mutating tools
|
|
390
|
-
(write/edit/bash) and network tools (web_fetch/web_search, MCP) go through the permission gate.
|
|
391
|
-
`todo` maintains the live task list; `task` delegates an investigation to a sub-agent that
|
|
392
|
-
returns a summary. `bash` can run detached with `run_in_background`; `bash_output` polls a
|
|
393
|
-
background shell's new output and `kill_shell` stops it.
|
|
394
|
-
|
|
395
|
-
## Customize & extend
|
|
396
|
-
|
|
397
|
-
Everything below is optional and lives under `.privateer/` (project) or `~/.privateer/`
|
|
398
|
-
(user); project files win. Settings merge across `config.json` → `settings.json` →
|
|
399
|
-
`settings.local.json` (run `/config` to see the resolved chain).
|
|
400
|
-
|
|
401
|
-
- **Custom commands** — `.privateer/commands/<name>.md`. The body is a prompt template
|
|
402
|
-
(`$ARGUMENTS`, `$1`…`$9`); optional frontmatter sets `description`/`argument-hint`. They
|
|
403
|
-
appear in `/help` and `/` autocomplete; subfolders namespace as `dir:name`.
|
|
404
|
-
- **Output styles** — `.privateer/output-styles/<name>.md` swap the agent's persona.
|
|
405
|
-
Switch with `/output-style <name>` (or `default`).
|
|
406
|
-
- **Sub-agents** — `.privateer/agents/<name>.md` with frontmatter (`description`, `tools`,
|
|
407
|
-
`model`). Invoke via the `task` tool's `subagent_type`; `/agents` lists them.
|
|
408
|
-
- **Skills** — `.privateer/skills/<name>/SKILL.md` (frontmatter `name`/`description` +
|
|
409
|
-
instruction body, plus any bundled `scripts/`/`references/` files). The format is
|
|
410
|
-
Claude Code-compatible, so published Agent Skills drop in unchanged. The agent sees a
|
|
411
|
-
catalog of names and descriptions and loads a skill's full instructions on demand via
|
|
412
|
-
the `skill` tool; `/skill-name` invokes one explicitly. Manage with `/skills`
|
|
413
|
-
(`list`, `info <name>`, `install <owner/repo[/path]> [--project] [--all] [--force]`,
|
|
414
|
-
`remove <name>`) — install fetches from GitHub with a shallow clone and never executes
|
|
415
|
-
anything it downloads.
|
|
416
|
-
- **Hooks** — a `hooks` section in `settings.json` runs shell commands on `PreToolUse`,
|
|
417
|
-
`PostToolUse`, `UserPromptSubmit`, and `Stop`. A hook blocks by exiting `2` or printing
|
|
418
|
-
`{"decision":"block"}`; `UserPromptSubmit` can inject `additionalContext`. `/hooks` lists them.
|
|
419
|
-
- **MCP servers** — declare them in `.privateer/mcp.json` (`{ "mcpServers": { … } }`).
|
|
420
|
-
Both **local stdio** servers (`{ "command", "args", "env" }`) and **remote HTTP** servers
|
|
421
|
-
(`{ "url", "headers?", "transport?" }`) are supported; remote defaults to Streamable HTTP
|
|
422
|
-
with a fallback to legacy SSE. Their tools are namespaced `server__tool` and gated like the
|
|
423
|
-
rest. Remote servers authenticate by a static `headers` bearer token, or — when none is set —
|
|
424
|
-
via **interactive OAuth** (PKCE + dynamic client registration): on a `401` Privateer opens your
|
|
425
|
-
browser, catches the redirect on a loopback port, and caches the tokens (owner-only) under
|
|
426
|
-
`~/.privateer/mcp-auth/`. `/mcp` shows each server's connection and auth state;
|
|
427
|
-
`/mcp logout [server]` clears saved OAuth.
|
|
428
|
-
|
|
429
|
-
```json
|
|
430
|
-
{
|
|
431
|
-
"mcpServers": {
|
|
432
|
-
"fs": { "command": "npx", "args": ["-y", "@modelcontextprotocol/server-filesystem", "."] },
|
|
433
|
-
"github": { "url": "https://api.githubcopilot.com/mcp/" },
|
|
434
|
-
"internal": { "url": "https://mcp.example.com/mcp", "headers": { "Authorization": "Bearer $TOKEN" } }
|
|
435
|
-
}
|
|
436
|
-
}
|
|
437
|
-
```
|
|
438
|
-
- **Routines** — saved tasks the scheduler daemon (`privateer daemon --detach`) runs
|
|
439
|
-
unattended, recurring (cron) or one-off. Ask the agent ("summarize world news every
|
|
440
|
-
morning") and approve; manage with `/routine` (list/pause/resume/rm/run). Runs use a safe
|
|
441
|
-
read/web toolset by default; a routine's `tools` list can also grant specific MCP tools
|
|
442
|
-
(`server__tool` or `server__*`) — flagged at approval, since they then run with no one
|
|
443
|
-
watching. See the [Sheet → WhatsApp recipe](docs/recipes/sheet-to-whatsapp.md) for a
|
|
444
|
-
full business automation built this way.
|
|
445
|
-
- **Status line** — set `statusLine` to a shell command; it receives session JSON on stdin
|
|
446
|
-
and its stdout becomes the status line.
|
|
138
|
+
## Private & verifiable inference
|
|
139
|
+
|
|
140
|
+
**NEAR AI Cloud** and **Tinfoil** run every model inside a **Trusted Execution Environment** —
|
|
141
|
+
a confidential VM where TLS terminates *inside* the enclave, so your prompt's inputs, weights,
|
|
142
|
+
and outputs are invisible to the infrastructure provider, the model provider, and the host
|
|
143
|
+
itself. It isn't "trust us": each request can produce a **cryptographic attestation** proving
|
|
144
|
+
the inference ran on genuine TEE hardware.
|
|
145
|
+
|
|
146
|
+
- A **status shield** colors the selected model's live posture — 🟢 verified, 🟡 returned but
|
|
147
|
+
unconfirmed, 🔴 no attestation material.
|
|
148
|
+
- **`/verify`** fetches the attestation on demand and prints the evidence. Privateer does a
|
|
149
|
+
pragmatic terminal-suited check; take the printed report to the
|
|
150
|
+
[NEAR AI Cloud Verifier](https://github.com/nearai/cloud-verifier) or the
|
|
151
|
+
[Tinfoil verifier](https://github.com/tinfoilsh/tinfoil-cli) for full quote-chain validation.
|
|
152
|
+
- **The posture is graded honestly.** A verified enclave (`cryptographic`), a pinned
|
|
153
|
+
zero-retention route (`observable`), and a provider's retention *promise* (`policy`) are
|
|
154
|
+
labeled distinctly — a claim never gets to read like a proof.
|
|
155
|
+
|
|
156
|
+
## The PII gate
|
|
157
|
+
|
|
158
|
+
Before any prompt is sent to a channel that *isn't* verified-private, Privateer scans it
|
|
159
|
+
**locally** for structured personal data — emails, phone numbers, SSNs, credit-card numbers
|
|
160
|
+
(Luhn-checked), IBANs (mod-97), IP and MAC addresses. If it finds any, it warns and offers to
|
|
161
|
+
**redact** or **send as-is** (or remember your choice for the session). Detection is
|
|
162
|
+
deterministic and on-device — no model ever sees the data in order to find it — and it's
|
|
163
|
+
skipped entirely on an attested TEE or on-device channel, which provably can't read your
|
|
164
|
+
prompt anyway. It's best-effort structured-PII detection, labeled as such — a safety net, not
|
|
165
|
+
a guarantee.
|
|
166
|
+
|
|
167
|
+
## Privateer account (billed inference)
|
|
168
|
+
|
|
169
|
+
Instead of bringing your own key, run **`/signin`** to sign into a Privateer account — an
|
|
170
|
+
app-brokered device flow where you approve a short code in the Privateer app, so wallet and
|
|
171
|
+
email accounts work identically and no password or key ever touches the terminal. Inference
|
|
172
|
+
is then billed to your subscription and defaults to a **NEAR TEE** model. Sign out any time
|
|
173
|
+
with `/signout`; manage linked terminals from the app.
|
|
174
|
+
|
|
175
|
+
> **Only approve a sign-in code you generated yourself.** The code authorizes *this* terminal
|
|
176
|
+
> to spend on your account. If someone sends you a code and asks you to approve it, don't —
|
|
177
|
+
> that hands *them* a billed session on *your* account.
|
|
178
|
+
|
|
179
|
+
## Approve from your phone
|
|
180
|
+
|
|
181
|
+
Turn on **`/remote-access`** (off by default) to link this terminal to the Privateer app. The
|
|
182
|
+
app can then drive the terminal — prompts come down, and each proposed action goes up for
|
|
183
|
+
**Allow/Deny** — while execution stays on your machine. The relay is live-only (nothing is
|
|
184
|
+
archived), carries no keys, and output is size-truncated and run through a best-effort secret
|
|
185
|
+
redactor before it leaves.
|
|
447
186
|
|
|
448
187
|
## Permission modes
|
|
449
188
|
|
|
@@ -451,40 +190,22 @@ Everything below is optional and lives under `.privateer/` (project) or `~/.priv
|
|
|
451
190
|
|---|---|
|
|
452
191
|
| `default` | prompt before edits and shell commands |
|
|
453
192
|
| `acceptEdits` | auto-approve file edits; still prompt for shell commands |
|
|
454
|
-
| `bypass` | no prompts (
|
|
455
|
-
| `plan` | read-only; the agent presents a plan, then you approve to
|
|
456
|
-
|
|
457
|
-
Out of the box the mode is **`acceptEdits`** (naming is a nod to convention: the mode
|
|
458
|
-
called `default` prompts on everything, but isn't the shipped default). Edits are still
|
|
459
|
-
checkpointed, so `/rewind` undoes them; prefer prompting on every edit? Run
|
|
460
|
-
`/permissions default` once — it persists. At an approval prompt: **y** allow once ·
|
|
461
|
-
**a** always · **n** deny. In plan mode, after the agent presents its plan: **a** approve
|
|
462
|
-
and exit plan mode · **k** keep planning.
|
|
193
|
+
| `bypass` | no prompts (destructive commands are *still* blocked) |
|
|
194
|
+
| `plan` | read-only; the agent presents a plan, then you approve to proceed |
|
|
463
195
|
|
|
464
|
-
|
|
196
|
+
Switch with **`/mode`**. Even in `bypass`, a danger filter blocks destructive shell commands,
|
|
197
|
+
and protected files (`.env`, shell rc files…) are guarded — the gate is never fully off.
|
|
465
198
|
|
|
466
|
-
|
|
467
|
-
context — conventions, architecture notes, anything it should always know.
|
|
199
|
+
## Extend it
|
|
468
200
|
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
- **
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
enforceable per request (`/zdr`); TEE inference is attestable (`/verify`). Most tools
|
|
478
|
-
leave this to the provider's terms-of-service page.
|
|
479
|
-
- **Phone approval.** `/remote-access` relays each proposed action to the Privateer app
|
|
480
|
-
for Allow/Deny while execution stays on your machine — useful for long agent runs you
|
|
481
|
-
want to supervise from anywhere.
|
|
482
|
-
- **Interop over ecosystem.** Skills use the Agent Skills format, so Claude Code skills
|
|
483
|
-
drop in unchanged; MCP covers tools. The goal is to reuse what exists, not grow a
|
|
484
|
-
parallel plugin world.
|
|
485
|
-
|
|
486
|
-
And, honestly, what it doesn't have: the maturity of the incumbents. It's a young
|
|
487
|
-
codebase — see [Caveats](#caveats) for the sharp edges we know about.
|
|
201
|
+
- **MCP servers** — declare them and their tools become first-class, gated like the rest
|
|
202
|
+
(local stdio, or remote HTTP with interactive OAuth).
|
|
203
|
+
- **Sub-agents** — delegate investigations to bounded parallel agents that run under the same
|
|
204
|
+
permission gate.
|
|
205
|
+
- **Routines** — saved tasks the daemon runs unattended; ask the agent to schedule work and
|
|
206
|
+
approve it once.
|
|
207
|
+
- **Web tools** — private-by-default web search/fetch with pluggable backends (self-hosted
|
|
208
|
+
SearXNG for fully private search).
|
|
488
209
|
|
|
489
210
|
## Develop
|
|
490
211
|
|
|
@@ -493,35 +214,6 @@ npm run typecheck
|
|
|
493
214
|
npm test
|
|
494
215
|
```
|
|
495
216
|
|
|
496
|
-
## Caveats
|
|
497
|
-
|
|
498
|
-
Privateer's agent core is built provider-agnostic from the ground up; a few areas are
|
|
499
|
-
deliberately simplified for now:
|
|
500
|
-
|
|
501
|
-
- **Prompt caching and extended thinking are Anthropic-only.** Ephemeral cache breakpoints
|
|
502
|
-
and the `thinkingBudget` setting apply to direct Anthropic models and OpenRouter routes to
|
|
503
|
-
`anthropic/*`. Other providers ignore them (a harmless no-op).
|
|
504
|
-
- **Checkpoints are in-memory.** `/rewind` is a within-session undo; snapshots live in memory
|
|
505
|
-
and aren't persisted across restarts.
|
|
506
|
-
- **Remote MCP OAuth uses a fixed loopback port** (`7777` by default; override with
|
|
507
|
-
`PRIVATEER_OAUTH_PORT`) so the redirect URI stays stable across runs. Set `PRIVATEER_NO_BROWSER=1`
|
|
508
|
-
in headless environments to skip the auto-launch and use the printed URL.
|
|
509
|
-
- **Image attachment assumes vision support.** Referenced images are sent as content parts;
|
|
510
|
-
non-vision models will return an error.
|
|
511
|
-
- **Compaction estimates context size** (~4 chars/token). The summary itself is
|
|
512
|
-
schema-guided (goals / decisions / files / open threads), with a plain-text fallback, and
|
|
513
|
-
the most recent messages are always kept verbatim.
|
|
514
|
-
- **`web_search` scrapes DuckDuckGo's keyless HTML endpoint.** It needs no API key but is
|
|
515
|
-
best-effort and can break if their markup changes. `web_fetch` is robust for known URLs.
|
|
516
|
-
- **Protected files** (`.env`, `.npmrc`, shell rc files, …) always prompt before edit — except
|
|
517
|
-
in `bypass` mode, which by definition skips all prompts.
|
|
518
|
-
|
|
519
|
-
## Docs
|
|
520
|
-
|
|
521
|
-
- [Architecture](docs/ARCHITECTURE.md) — how the provider layer, agent loop, tools, and permissions fit together
|
|
522
|
-
- [Recipe: Sheet → WhatsApp](docs/recipes/sheet-to-whatsapp.md) — an unattended routine + MCP servers messaging new spreadsheet rows
|
|
523
|
-
- [Brand assets](brand/README.md) — the logo and icon set
|
|
524
|
-
|
|
525
217
|
## License
|
|
526
218
|
|
|
527
219
|
[MIT](LICENSE) © Patrick
|