autopilot-ai 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/PLAN.md +59 -0
- package/README.md +457 -0
- package/bin/autopilot-sdk.mjs +3 -0
- package/bin/autopilot.mjs +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +33170 -0
- package/dist/index.js.map +1 -0
- package/dist/sdk/index.d.ts +743 -0
- package/dist/sdk/index.js +10550 -0
- package/dist/sdk/index.js.map +1 -0
- package/package.json +93 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Sina Meraji
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/PLAN.md
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# Implementation Plan: Web Search, GitHub Read-Only, Headless Browser
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
Add three new native tool categories to KimiFlare:
|
|
5
|
+
1. **Web Search** (`search_web`) — query-based web search without requiring a known URL
|
|
6
|
+
2. **GitHub Read-Only** (`github_read_pr`, `github_read_issue`, `github_read_code`) — structured GitHub API access, whitelisted in plan mode
|
|
7
|
+
3. **Headless Browser** (`browser_fetch`) — JS-rendered page extraction via Playwright
|
|
8
|
+
|
|
9
|
+
## Design Decisions
|
|
10
|
+
|
|
11
|
+
### Web Search
|
|
12
|
+
- **Provider**: DuckDuckGo HTML scraping (no API key required)
|
|
13
|
+
- **Fallback**: If DuckDuckGo blocks us, degrade gracefully with a clear error
|
|
14
|
+
- **Output**: List of results with title, URL, and snippet
|
|
15
|
+
- **Permission**: `needsPermission: false` (read-only, no side effects)
|
|
16
|
+
- **Plan mode**: Whitelisted (read-only)
|
|
17
|
+
|
|
18
|
+
### GitHub Read-Only
|
|
19
|
+
- **Auth**: Reuse existing `githubOAuthToken` from config
|
|
20
|
+
- **Tools**:
|
|
21
|
+
- `github_read_pr` — read a PR by owner/repo/number
|
|
22
|
+
- `github_read_issue` — read an issue by owner/repo/number
|
|
23
|
+
- `github_read_code` — read file contents from a repo at a specific ref
|
|
24
|
+
- **Permission**: `needsPermission: false` (read-only, no side effects)
|
|
25
|
+
- **Plan mode**: Whitelisted (explicitly read-only)
|
|
26
|
+
- **Why native tools vs gh CLI**: Native tools are always safe (no write ops), so they bypass permission prompts and work in plan mode
|
|
27
|
+
|
|
28
|
+
### Headless Browser
|
|
29
|
+
- **Engine**: Playwright (Chromium in headless mode)
|
|
30
|
+
- **Behavior**: Launch invisible browser, navigate, wait for load, extract text + screenshot option
|
|
31
|
+
- **Output**: Extracted page text (via readability-style extraction) + optional screenshot path
|
|
32
|
+
- **Permission**: `needsPermission: false` for text extraction, `needsPermission: true` for screenshots (files on disk)
|
|
33
|
+
- **Plan mode**: Text extraction whitelisted; screenshots blocked
|
|
34
|
+
- **Dependency**: `playwright` as optional peer dependency — tool gracefully errors if not installed
|
|
35
|
+
|
|
36
|
+
## Files to Create/Modify
|
|
37
|
+
|
|
38
|
+
### New files
|
|
39
|
+
- `src/tools/web-search.ts` — DuckDuckGo search implementation
|
|
40
|
+
- `src/tools/github.ts` — GitHub API read-only tools
|
|
41
|
+
- `src/tools/browser.ts` — Playwright headless browser tool
|
|
42
|
+
- `src/tools/web-search.test.ts` — tests for search
|
|
43
|
+
- `src/tools/github.test.ts` — tests for GitHub tools
|
|
44
|
+
- `src/tools/browser.test.ts` — tests for browser tool
|
|
45
|
+
|
|
46
|
+
### Modified files
|
|
47
|
+
- `src/tools/executor.ts` — register new tools in `ALL_TOOLS`
|
|
48
|
+
- `src/tools/reducer.ts` — add reduction rules for `search_web`, `github_read_*`, `browser_fetch`
|
|
49
|
+
- `src/mode.ts` — update `isBlockedInPlanMode` and `isReadOnlyBash` if needed
|
|
50
|
+
- `src/agent/system-prompt.ts` — mention new tools in static prefix (optional)
|
|
51
|
+
- `package.json` — add `playwright` to optional dependencies or devDependencies
|
|
52
|
+
|
|
53
|
+
## Implementation Order
|
|
54
|
+
1. Web search (simplest, no external deps)
|
|
55
|
+
2. GitHub read-only (reuses existing auth)
|
|
56
|
+
3. Headless browser (most complex, optional dep)
|
|
57
|
+
4. Reducer updates + mode updates
|
|
58
|
+
5. Tests
|
|
59
|
+
6. Typecheck + commit
|
package/README.md
ADDED
|
@@ -0,0 +1,457 @@
|
|
|
1
|
+
<h1 align="center">autopilot <sub>(formerly kimiflare)</sub></h1>
|
|
2
|
+
|
|
3
|
+
<p align="center">
|
|
4
|
+
<a href="https://www.npmjs.com/package/autopilot-ai"><img src="https://img.shields.io/npm/v/autopilot-ai?style=flat-square&color=cb3837" alt="npm version"></a>
|
|
5
|
+
<a href="https://www.npmjs.com/package/autopilot-ai"><img src="https://img.shields.io/npm/dm/autopilot-ai?style=flat-square&color=cb3837" alt="npm downloads"></a>
|
|
6
|
+
<a href="https://github.com/sinameraji/autopilot/blob/main/LICENSE"><img src="https://img.shields.io/github/license/sinameraji/autopilot?style=flat-square&color=2ea44f" alt="license"></a>
|
|
7
|
+
<img src="https://img.shields.io/badge/node-%3E%3D20-339933?style=flat-square&logo=nodedotjs&logoColor=white" alt="Node.js >= 20">
|
|
8
|
+
<img src="https://img.shields.io/badge/typescript-5.7-3178c6?style=flat-square&logo=typescript&logoColor=white" alt="TypeScript">
|
|
9
|
+
<a href="https://openrouter.ai"><img src="https://img.shields.io/badge/runs%20on-OpenRouter-6566f1?style=flat-square" alt="Runs on OpenRouter"></a>
|
|
10
|
+
</p>
|
|
11
|
+
|
|
12
|
+
<p align="center">
|
|
13
|
+
<strong>A terminal coding agent that runs any model on <a href="https://openrouter.ai">OpenRouter</a> with your own key.</strong><br>
|
|
14
|
+
One key, 400+ models, per-turn billed cost.
|
|
15
|
+
</p>
|
|
16
|
+
|
|
17
|
+
## How it works
|
|
18
|
+
|
|
19
|
+
KimiFlare sends every model call to **[OpenRouter](https://openrouter.ai)** using **your own OpenRouter API key** — bring-your-own-key, nothing proxied, nothing marked up. On first run you paste the key once (it's checked against OpenRouter before it's saved) and pick a model. That's the whole setup.
|
|
20
|
+
|
|
21
|
+
- **Any model, one key.** The model picker is OpenRouter's live catalog — Claude, GPT, Gemini, Grok, Qwen, GLM, Kimi, DeepSeek, free models and more — opening on the best & latest by benchmark score, with fuzzy search over everything. Switch any time with `/model`.
|
|
22
|
+
- **Real cost, per turn.** OpenRouter reports what each generation actually cost; the status bar shows it (a local estimate marked `≈$` only until the billed number arrives). `/cost` totals it by session, day, month and all time.
|
|
23
|
+
- **Reliable tool calling.** Requests only go to upstream providers that support every parameter autopilot sends (tools above all), and OpenRouter routes tool-calling traffic to the providers with the best tool-call success rates. The status bar shows which provider served the last turn.
|
|
24
|
+
- **Prompt caching that stays warm.** Each session pins to one upstream provider (OpenRouter sticky routing), so the long, stable prompt prefix keeps hitting the provider's cache across turns.
|
|
25
|
+
|
|
26
|
+
## What to remember
|
|
27
|
+
|
|
28
|
+
- **Up to 1M+ context** (model-dependent) — Read entire modules, large configs, and full stack traces without the model losing track.
|
|
29
|
+
- **Image understanding** — Drop image paths (PNG, JPG, WebP, GIF, BMP up to 5 MB) into any prompt. Great for UI reviews, diagrams, and screenshots.
|
|
30
|
+
- **Plan / Edit / Auto modes** — `plan` is a whitelist-only research mode: only read-only tools (read, glob, grep, web search, GitHub read-only, browser fetch) are allowed. Writes, edits, mutating bash, MCP tools, and LSP renames are all blocked. `edit` (default) prompts per mutating call. `auto` approves everything for trusted tasks.
|
|
31
|
+
- **Windows support** — OS-aware shell auto-detects `cmd.exe` / PowerShell on Windows, `bash` on Unix. The `bash` tool works out of the box on all platforms.
|
|
32
|
+
- **Message queuing** — Submit multiple messages while the agent is busy; they queue and auto-drain. Escape interrupts the current turn but preserves the queue.
|
|
33
|
+
- **Smart permission modal** — Denying a tool opens inline feedback so you can tell the agent what to do instead. Keyboard-native navigation (`↑/↓`, `j/k`, `Alt+1/2/3`).
|
|
34
|
+
- **Loop guardrails** — Agent hard-stops when all tools in a turn are blocked, preventing infinite token-burning cycles.
|
|
35
|
+
- **Persistent all-time cost history** — Append-only `history.jsonl` tracks daily usage forever, so `/cost` shows true all-time and monthly totals that survive across sessions and version updates.
|
|
36
|
+
- **LSP + MCP** — Semantic code intelligence (hover, go-to-definition, references, diagnostics) via Language Server Protocol. Extend with external tools via Model Context Protocol.
|
|
37
|
+
- **Local structured memory** — SQLite + embeddings cross-session memory. The agent recalls facts, instructions, and preferences across sessions via `remember`, `recall`, and `forget` tools.
|
|
38
|
+
- **Web search, GitHub, and headless browser** — Research the web, read GitHub repos, and fetch JavaScript-rendered pages without leaving your terminal.
|
|
39
|
+
|
|
40
|
+
## Recently shipped
|
|
41
|
+
|
|
42
|
+
- **OpenRouter as the model provider** — Every OpenRouter model, your own key, billed cost per turn. Replaces Cloudflare Workers AI / AI Gateway (see [Upgrading from Cloudflare](#upgrading-from-the-cloudflare-version)).
|
|
43
|
+
- **OS-aware shell with Windows support** — Auto-detects `cmd.exe`, PowerShell, or bash based on platform. Override with `KIMIFLARE_SHELL` or `/shell`.
|
|
44
|
+
- **Smart permission modal with inline feedback** — Deny a tool and immediately tell the agent what to do instead. Keyboard-native navigation with `↑/↓`, `j/k`, `Alt+1/2/3`.
|
|
45
|
+
- **True message queuing** — Enter queues messages while the agent is busy; Escape interrupts and auto-drains the queue.
|
|
46
|
+
- **Hard-stop loop guardrail** — Stops token-burning cycles when all tools in a turn are blocked.
|
|
47
|
+
- **Headless SDK** — Programmatic `createAgentSession` API and JSONL-over-stdio RPC mode for building on top of KimiFlare.
|
|
48
|
+
|
|
49
|
+
See the full changelog at [github.com/sinameraji/autopilot/releases](https://github.com/sinameraji/autopilot/releases).
|
|
50
|
+
|
|
51
|
+
## Quick start
|
|
52
|
+
|
|
53
|
+
```sh
|
|
54
|
+
npm install -g autopilot-ai
|
|
55
|
+
autopilot
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
On first run autopilot asks for your OpenRouter API key (create one at <https://openrouter.ai/keys>) and a model. That's it.
|
|
59
|
+
|
|
60
|
+
Or run without installing:
|
|
61
|
+
|
|
62
|
+
```sh
|
|
63
|
+
npx autopilot-ai
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
> **Coming from `kimiflare`?** The package was renamed. Run `npm uninstall -g kimiflare && npm install -g autopilot-ai` and use `autopilot` instead of `kimiflare`. Your settings, sessions, memory and cost history are kept (they stay in `~/.config/kimiflare` and `~/.local/share/kimiflare`), and `KIMIFLARE_*` environment variables still work.
|
|
67
|
+
|
|
68
|
+
Requires Node.js ≥ 20.
|
|
69
|
+
|
|
70
|
+
### Your OpenRouter key
|
|
71
|
+
|
|
72
|
+
Three ways to provide it — the first one found wins:
|
|
73
|
+
|
|
74
|
+
1. **Environment:** `OPENROUTER_API_KEY` (or `KIMIFLARE_OPENROUTER_KEY`). With this set, the setup screen never appears — the way to run kimiflare headless (CI, a VM, a container).
|
|
75
|
+
2. **Setup screen / CLI:** paste it on first run, or run `autopilot auth openrouter` (prompts without echo, validates, saves). Inside the TUI, `/key set <key>` replaces it.
|
|
76
|
+
3. **Config file:** `"openrouterApiKey": "sk-or-…"` in `~/.config/kimiflare/config.json` (created with mode 600).
|
|
77
|
+
|
|
78
|
+
`/key` shows which key is in use, what it has spent and how much credit is left. Model calls — including memory embeddings and small internal side-calls (summaries, memory extraction) — are all billed to this key.
|
|
79
|
+
|
|
80
|
+
A key with no credits can still use OpenRouter's **free models** (the "Free" section of `/model`, ids ending in `:free`), subject to OpenRouter's daily request cap.
|
|
81
|
+
|
|
82
|
+
### Upgrading from the Cloudflare version
|
|
83
|
+
|
|
84
|
+
Earlier kimiflare versions ran on Cloudflare Workers AI / AI Gateway. On the first launch after upgrading you'll be asked for an OpenRouter key once; after that:
|
|
85
|
+
|
|
86
|
+
- Your settings (theme, MCP/LSP servers, hooks, memory, sessions, cost history) carry over.
|
|
87
|
+
- Model ids are migrated (`@cf/moonshotai/kimi-k2.6` → `moonshotai/kimi-k2.6`, and so on), and the retired Cloudflare fields (OAuth login, gateway, Unified Billing, provider keys) are removed from `config.json`.
|
|
88
|
+
- Memory keeps working unchanged: embeddings use the same `bge-base-en-v1.5` model, now via OpenRouter.
|
|
89
|
+
- `/gateway`, `autopilot auth cloudflare`, `--cloud` and the Cloud-only commands are gone. `/multi-agent` (Commute) still deploys to your Cloudflare account and keeps using `CLOUDFLARE_ACCOUNT_ID` / `CLOUDFLARE_API_TOKEN` for that.
|
|
90
|
+
|
|
91
|
+
### Model
|
|
92
|
+
|
|
93
|
+
You pick the model on first run, and can switch any time with `/model`. The picker opens on the **best & latest** models — recent, tool-capable models ranked by the agentic and coding benchmark scores OpenRouter publishes (Artificial Analysis), at most two per lab — so it stays current as new models ship, with no list maintained in code. Start typing to fuzzy-search all of them (`sonet` finds Claude Sonnet, `gpt 6` the GPT-6 family). Or set one directly:
|
|
94
|
+
|
|
95
|
+
```sh
|
|
96
|
+
/model moonshotai/kimi-k3 # 1M context
|
|
97
|
+
/model anthropic/claude-sonnet-5
|
|
98
|
+
/model deepseek/deepseek-v4-flash
|
|
99
|
+
autopilot -m moonshotai/kimi-k2.7-code -p "..."
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Any OpenRouter model id works, including variants like `:free` and `:nitro`. Models OpenRouter lists without tool calling are hidden from the picker — a coding agent needs tools.
|
|
103
|
+
|
|
104
|
+
**Provider routing (optional).** OpenRouter serves most models through several upstream providers. autopilot always requires providers that support every parameter it sends, and otherwise leaves routing to OpenRouter (price-weighted, uptime-aware, tool-calling quality first, sticky per session for caching). To steer it, add an `openrouterProvider` object to the config file — any of OpenRouter's [provider preferences](https://openrouter.ai/docs/guides/routing/provider-selection):
|
|
105
|
+
|
|
106
|
+
```json
|
|
107
|
+
{ "openrouterProvider": { "ignore": ["SomeProvider"], "data_collection": "deny" } }
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Avoid `order` / `sort` unless you need them: they turn off sticky routing, which is what keeps the prompt cache warm.
|
|
111
|
+
|
|
112
|
+
### Custom gateway endpoint
|
|
113
|
+
|
|
114
|
+
Point every model call at your own OpenAI-compatible endpoint instead of OpenRouter — useful when a
|
|
115
|
+
host application (CI, an agents platform, a container) fronts model access with its own broker and
|
|
116
|
+
doesn't want to hand autopilot a raw provider key:
|
|
117
|
+
|
|
118
|
+
```sh
|
|
119
|
+
export KIMIFLARE_BASE_URL="https://your-broker.example.com/v1" # /chat/completions is appended
|
|
120
|
+
export KIMIFLARE_API_KEY="<bearer for that endpoint>" # optional; header omitted if unset
|
|
121
|
+
autopilot -p "..." # or --mode rpc — no OpenRouter key needed
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
The same pair can be persisted in `~/.config/kimiflare/config.json` as `baseUrl` / `apiKey`
|
|
125
|
+
(env vars win over the file, field by field). When a base URL is configured:
|
|
126
|
+
|
|
127
|
+
- Chat requests go to `<baseUrl>/chat/completions` and memory embeddings to `<baseUrl>/embeddings`,
|
|
128
|
+
with `Authorization: Bearer $KIMIFLARE_API_KEY` (no `Authorization` header at all when the key is
|
|
129
|
+
unset — e.g. a local llama.cpp/Ollama server).
|
|
130
|
+
- Model ids pass through in the request body unchanged; your endpoint owns provider dispatch.
|
|
131
|
+
- Cost is the local estimate only — your endpoint does its own metering.
|
|
132
|
+
|
|
133
|
+
### One-shot mode
|
|
134
|
+
|
|
135
|
+
```sh
|
|
136
|
+
autopilot -p "summarize PLAN.md" # stream answer to stdout
|
|
137
|
+
autopilot -p "..." --dangerously-allow-all # auto-approve mutating tools (for scripts)
|
|
138
|
+
autopilot -p "..." --reasoning # include chain-of-thought in stderr
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### Headless SDK
|
|
142
|
+
|
|
143
|
+
Use KimiFlare programmatically from your own application — no TUI required.
|
|
144
|
+
|
|
145
|
+
```ts
|
|
146
|
+
import { createAgentSession } from "autopilot-ai/sdk";
|
|
147
|
+
|
|
148
|
+
const { session } = await createAgentSession({
|
|
149
|
+
cwd: "/path/to/project",
|
|
150
|
+
config: {
|
|
151
|
+
openrouterApiKey: process.env.OPENROUTER_API_KEY,
|
|
152
|
+
model: "moonshotai/kimi-k2.7-code",
|
|
153
|
+
},
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
// Stream every event: text deltas, tool calls, tasks, usage
|
|
157
|
+
session.subscribe((event) => {
|
|
158
|
+
console.log(event.type, event);
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
// Send a prompt
|
|
162
|
+
await session.prompt("Refactor auth to JWT + Redis");
|
|
163
|
+
|
|
164
|
+
// Mid-flight correction while the agent is still running
|
|
165
|
+
await session.steer("Use Redis instead of in-memory store");
|
|
166
|
+
|
|
167
|
+
// After the turn finishes
|
|
168
|
+
await session.followUp("Also add unit tests");
|
|
169
|
+
|
|
170
|
+
// Clean up
|
|
171
|
+
session.dispose();
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
**Key features:**
|
|
175
|
+
- `subscribe()` — receive typed events (`text_delta`, `tool_call`, `tool_result`, `task_update`, `usage`, `warning`, `error`, `done`, etc.)
|
|
176
|
+
- `prompt()` / `steer()` / `followUp()` — full conversation lifecycle
|
|
177
|
+
- `pause()` / `resume()` — graceful preemption
|
|
178
|
+
- `getStatus()` / `getUsage()` — inspect session state
|
|
179
|
+
- Custom `permissionHandler` — decide programmatically whether to allow mutating tools
|
|
180
|
+
- Optional `memoryEnabled`, `lspEnabled`, `costAttribution` flags
|
|
181
|
+
|
|
182
|
+
#### SDK Authentication
|
|
183
|
+
|
|
184
|
+
The SDK needs an OpenRouter API key — or a [custom gateway endpoint](#custom-gateway-endpoint)
|
|
185
|
+
(`baseUrl` / `apiKey` in `config`, or `KIMIFLARE_BASE_URL` / `KIMIFLARE_API_KEY`), in which case no
|
|
186
|
+
OpenRouter key is required. Resolved in this priority order:
|
|
187
|
+
|
|
188
|
+
1. **Explicit `config` object** (`openrouterApiKey`) — recommended for apps
|
|
189
|
+
2. **Environment variables**: `OPENROUTER_API_KEY` / `KIMIFLARE_OPENROUTER_KEY`
|
|
190
|
+
3. **Config file**: `~/.config/kimiflare/config.json`
|
|
191
|
+
|
|
192
|
+
Pass `provider` in `createAgentSession` options to set OpenRouter provider-routing preferences for that session.
|
|
193
|
+
|
|
194
|
+
**For Electron / desktop apps**, we recommend storing the key in the OS keychain (e.g. Electron `safeStorage` or `keytar`) and passing it explicitly:
|
|
195
|
+
|
|
196
|
+
```ts
|
|
197
|
+
import { createAgentSession } from "autopilot-ai/sdk";
|
|
198
|
+
|
|
199
|
+
const openrouterApiKey = await keytar.getPassword("autopilot", "openrouter");
|
|
200
|
+
|
|
201
|
+
const { session } = await createAgentSession({
|
|
202
|
+
cwd: projectPath,
|
|
203
|
+
config: { openrouterApiKey },
|
|
204
|
+
});
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
#### RPC mode (subprocess)
|
|
208
|
+
|
|
209
|
+
If you need process isolation or a non-Node consumer, run KimiFlare in JSONL-over-stdio RPC mode:
|
|
210
|
+
|
|
211
|
+
```sh
|
|
212
|
+
node bin/autopilot.mjs --mode rpc
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
Give the subprocess `OPENROUTER_API_KEY` — or a [custom gateway endpoint](#custom-gateway-endpoint)
|
|
216
|
+
(`KIMIFLARE_BASE_URL` + `KIMIFLARE_API_KEY`), ideal for host apps that broker model access themselves.
|
|
217
|
+
|
|
218
|
+
```ts
|
|
219
|
+
import { spawn } from "node:child_process";
|
|
220
|
+
|
|
221
|
+
const proc = spawn("npx", ["autopilot-ai", "--mode", "rpc"], {
|
|
222
|
+
cwd: projectPath,
|
|
223
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
// Read events
|
|
227
|
+
proc.stdout.on("data", (chunk) => {
|
|
228
|
+
for (const line of chunk.toString().split("\n")) {
|
|
229
|
+
if (!line.trim()) continue;
|
|
230
|
+
const event = JSON.parse(line);
|
|
231
|
+
console.log(event.type, event);
|
|
232
|
+
}
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
// Send commands
|
|
236
|
+
proc.stdin.write(JSON.stringify({ type: "new_session" }) + "\n");
|
|
237
|
+
proc.stdin.write(JSON.stringify({ type: "prompt", message: "Hello" }) + "\n");
|
|
238
|
+
|
|
239
|
+
// Resolve a permission request
|
|
240
|
+
proc.stdin.write(
|
|
241
|
+
JSON.stringify({ type: "resolve_permission", requestId: "req_0", decision: "allow" }) + "\n"
|
|
242
|
+
);
|
|
243
|
+
|
|
244
|
+
// Resume a previous session after a process restart (the `new_session`
|
|
245
|
+
// response echoes back the sessionId to store for later)
|
|
246
|
+
proc.stdin.write(JSON.stringify({ type: "new_session", sessionId: "sdk-session-…" }) + "\n");
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
### Image understanding
|
|
250
|
+
|
|
251
|
+
```sh
|
|
252
|
+
autopilot
|
|
253
|
+
› fix the layout bug in this screenshot docs/bug.png
|
|
254
|
+
› convert this mockup design.png to Tailwind HTML
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
## Slash commands
|
|
258
|
+
|
|
259
|
+
| Command | Effect |
|
|
260
|
+
|---------|--------|
|
|
261
|
+
| `/mode edit\|plan\|auto` | Switch permission mode |
|
|
262
|
+
| `/shell auto\|bash\|cmd\|powershell` | Show or set the shell for the bash tool |
|
|
263
|
+
| `/thinking low\|medium\|high` | Reasoning effort (persists) |
|
|
264
|
+
| `/theme` | Interactive theme picker (`Ctrl+T`) |
|
|
265
|
+
| `/resume` | Pick a past conversation to restore |
|
|
266
|
+
| `/compact` | Summarize older turns to free context |
|
|
267
|
+
| `/init` | Scan repo and write `KIMI.md` project context |
|
|
268
|
+
| `/memory` | Show memory stats and search |
|
|
269
|
+
| `/mcp list` / `/mcp reload` | Manage MCP servers |
|
|
270
|
+
| `/reasoning` | Toggle chain-of-thought display |
|
|
271
|
+
| `/model` | Pick a model from OpenRouter's catalog (or `/model <id>`, `/model list [filter]`) |
|
|
272
|
+
| `/key` | Show your OpenRouter key's spend and credit (`/key set <key>`, `/key clear`) |
|
|
273
|
+
| `/cost` | Show OpenRouter-confirmed cost by session, day, month and all time |
|
|
274
|
+
| `/update` | Check for updates |
|
|
275
|
+
| `/help` | List all commands |
|
|
276
|
+
|
|
277
|
+
## Keyboard shortcuts
|
|
278
|
+
|
|
279
|
+
| Shortcut | Action |
|
|
280
|
+
|----------|--------|
|
|
281
|
+
| `Ctrl+C` / `Esc` | Interrupt current turn when busy; exit when idle |
|
|
282
|
+
| `Ctrl+R` | Toggle reasoning display |
|
|
283
|
+
| `Ctrl+O` | Toggle verbose tool output |
|
|
284
|
+
| `Ctrl+T` | Open theme picker |
|
|
285
|
+
| `Shift+Tab` | Cycle mode (edit → plan → auto) |
|
|
286
|
+
| `↑` / `↓` | Walk prompt history |
|
|
287
|
+
|
|
288
|
+
## Logs
|
|
289
|
+
|
|
290
|
+
KimiFlare writes structured JSON logs of agent-side activity (tool calls,
|
|
291
|
+
permission decisions, MCP/LSP lifecycle, session events, errors) to
|
|
292
|
+
`~/.config/kimiflare/logs/<date>.jsonl`, one file per day, with 7-day
|
|
293
|
+
retention pruned automatically at startup.
|
|
294
|
+
|
|
295
|
+
The logs deliberately exclude prompts and completions. To capture full
|
|
296
|
+
request/response payloads locally for debugging, run with
|
|
297
|
+
`KIMIFLARE_DUMP_LLM=1`; each generation is also visible in your
|
|
298
|
+
[OpenRouter activity log](https://openrouter.ai/activity).
|
|
299
|
+
|
|
300
|
+
```sh
|
|
301
|
+
autopilot logs path # today's file
|
|
302
|
+
autopilot logs dir # log directory
|
|
303
|
+
autopilot logs prune # delete files older than 7 days
|
|
304
|
+
|
|
305
|
+
# Tail this session's activity, formatted:
|
|
306
|
+
tail -f $(autopilot logs path) | jq
|
|
307
|
+
|
|
308
|
+
# Find the slowest tool calls in the last day:
|
|
309
|
+
jq -r 'select(.event == "tool:end") | "\(.data.duration_ms)\t\(.data.tool)"' \
|
|
310
|
+
$(autopilot logs path) | sort -rn | head
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
Disable the file sink entirely with `KIMIFLARE_LOG_SINK=off`. The
|
|
314
|
+
separate `KIMIFLARE_LOG_LEVEL` env var (default `off`) controls stderr
|
|
315
|
+
output — independent of the file sink.
|
|
316
|
+
|
|
317
|
+
### Shipping to an OpenTelemetry collector
|
|
318
|
+
|
|
319
|
+
If you set `KIMIFLARE_OTEL_ENDPOINT`, KimiFlare also ships each log
|
|
320
|
+
entry to that endpoint over [OTLP/HTTP](https://opentelemetry.io/docs/specs/otlp/)
|
|
321
|
+
so it lands in Datadog, Honeycomb, Grafana Loki, an internal collector,
|
|
322
|
+
or any other backend that speaks OTel. Batched every 5 s (or every
|
|
323
|
+
100 entries, whichever first) and best-effort — never blocks the agent
|
|
324
|
+
loop.
|
|
325
|
+
|
|
326
|
+
```sh
|
|
327
|
+
# Full path:
|
|
328
|
+
export KIMIFLARE_OTEL_ENDPOINT="https://otel.example.com/v1/logs"
|
|
329
|
+
# Or just the base URL (we auto-append /v1/logs):
|
|
330
|
+
export KIMIFLARE_OTEL_ENDPOINT="https://otel.example.com"
|
|
331
|
+
|
|
332
|
+
# Optional headers (comma-separated key=value pairs) — e.g. for auth:
|
|
333
|
+
export KIMIFLARE_OTEL_HEADERS="Authorization=Bearer xyz,X-Tenant=acme"
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
Each log entry maps to one OTel `LogRecord`. Correlation IDs
|
|
337
|
+
(`session_id`, `turn_id`, `request_id`) become record attributes,
|
|
338
|
+
`data.*` fields are flattened to attributes with type-preserving
|
|
339
|
+
encoding, and a `service.name=kimiflare` + `service.version` pair sits
|
|
340
|
+
on the resource.
|
|
341
|
+
|
|
342
|
+
## Hooks
|
|
343
|
+
|
|
344
|
+
KimiFlare can fire shell commands at five points in an agent turn,
|
|
345
|
+
configured per-project (`.kimiflare/settings.json`) or globally
|
|
346
|
+
(`~/.config/kimiflare/settings.json`):
|
|
347
|
+
|
|
348
|
+
| Event | Fires when | Veto? |
|
|
349
|
+
|--------------------|-------------------------------------------------|-------|
|
|
350
|
+
| `PreToolUse` | A tool call is about to run | Yes |
|
|
351
|
+
| `PostToolUse` | A tool call just finished | No |
|
|
352
|
+
| `UserPromptSubmit` | You hit Enter on a prompt | Yes |
|
|
353
|
+
| `Stop` | A turn ended cleanly | No |
|
|
354
|
+
| `PreCompact` | Auto-compaction is about to run | No |
|
|
355
|
+
|
|
356
|
+
Hooks receive the event payload as JSON on stdin **and** as
|
|
357
|
+
`KIMIFLARE_HOOK_*` env vars (for shell-one-liner ergonomics).
|
|
358
|
+
Non-zero exit on a veto event cancels the underlying action and
|
|
359
|
+
surfaces the hook's stdout as the rejection reason.
|
|
360
|
+
|
|
361
|
+
### Browse + enable from the TUI
|
|
362
|
+
|
|
363
|
+
```text
|
|
364
|
+
/hooks # list configured hooks
|
|
365
|
+
/hooks recommended # list starter hooks shipped with autopilot
|
|
366
|
+
/hooks enable stop-bell # enable one (writes to .kimiflare/settings.json)
|
|
367
|
+
/hooks enable stop-bell global # ...or the global file
|
|
368
|
+
/hooks disable stop-bell
|
|
369
|
+
/hooks path # print settings.json paths
|
|
370
|
+
/hooks reload # re-read settings.json after a manual edit
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
The recommended catalog includes terminal bells / macOS notifications
|
|
374
|
+
on `Stop`, secret-file guards on `PreToolUse` (e.g. block edits to
|
|
375
|
+
`*.env`), auto-format-with-prettier on `PostToolUse`, and a tool-call
|
|
376
|
+
audit log. All ship disabled — `/hooks recommended` lists them.
|
|
377
|
+
|
|
378
|
+
### Schema example
|
|
379
|
+
|
|
380
|
+
```json
|
|
381
|
+
{
|
|
382
|
+
"hooks": {
|
|
383
|
+
"PreToolUse": [
|
|
384
|
+
{
|
|
385
|
+
"id": "no-secrets",
|
|
386
|
+
"matcher": "^(edit|write)$",
|
|
387
|
+
"command": "case \"$KIMIFLARE_HOOK_PATH\" in *.env|*.pem) echo 'blocked'; exit 1;; esac"
|
|
388
|
+
}
|
|
389
|
+
],
|
|
390
|
+
"PostToolUse": [
|
|
391
|
+
{
|
|
392
|
+
"id": "format-ts",
|
|
393
|
+
"matcher": "^(edit|write)$",
|
|
394
|
+
"command": "npx --no-install prettier --write \"$KIMIFLARE_HOOK_PATH\" >/dev/null 2>&1 || true"
|
|
395
|
+
}
|
|
396
|
+
],
|
|
397
|
+
"Stop": [
|
|
398
|
+
{ "id": "bell", "command": "printf '\\a'" }
|
|
399
|
+
]
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
Per-hook fields:
|
|
405
|
+
- `command` (required) — the shell command.
|
|
406
|
+
- `matcher` (optional) — anchored regex matched against the tool name
|
|
407
|
+
for `PreToolUse` / `PostToolUse`. Ignored for other events.
|
|
408
|
+
- `id` (optional) — stable handle for `/hooks enable|disable`.
|
|
409
|
+
Auto-derived from `event + command` when omitted.
|
|
410
|
+
- `enabled` (default `true`) — set `false` to keep a hook in config
|
|
411
|
+
but skip it.
|
|
412
|
+
- `timeoutMs` (default `30000`) — hard kill if the hook hangs.
|
|
413
|
+
- `description` (optional) — shown by `/hooks list`.
|
|
414
|
+
|
|
415
|
+
Hooks are always-on infrastructure: they fire whether the TUI is open
|
|
416
|
+
or autopilot is running in `--print` mode. They also fire for tool
|
|
417
|
+
calls generated from inside the Code Mode sandbox (heavy-tier turns),
|
|
418
|
+
because hook firing lives on the `ToolExecutor` itself — every call
|
|
419
|
+
path uses the same plumbing.
|
|
420
|
+
|
|
421
|
+
When intent classification has assigned a tier, hook payloads include
|
|
422
|
+
it as `tier: "light" | "medium" | "heavy"` (on `UserPromptSubmit`,
|
|
423
|
+
`PreToolUse`, `PostToolUse`) and as `$KIMIFLARE_HOOK_TIER`. Useful for
|
|
424
|
+
"skip auto-format on light turns" or "audit every heavy-turn write."
|
|
425
|
+
|
|
426
|
+
SDK consumers opt in to hooks with `enableHooks: true` on
|
|
427
|
+
`createAgentSession`. Default is off because the SDK is a primitive,
|
|
428
|
+
not the TUI.
|
|
429
|
+
|
|
430
|
+
## Development
|
|
431
|
+
|
|
432
|
+
```sh
|
|
433
|
+
git clone https://github.com/sinameraji/autopilot
|
|
434
|
+
cd autopilot
|
|
435
|
+
npm install
|
|
436
|
+
npm run build
|
|
437
|
+
npm link
|
|
438
|
+
```
|
|
439
|
+
|
|
440
|
+
Scripts:
|
|
441
|
+
- `npm run build` — bundle with tsup
|
|
442
|
+
- `npm run dev` — run via tsx
|
|
443
|
+
- `npm run typecheck` — `tsc --noEmit`
|
|
444
|
+
- `npm test` — run tests
|
|
445
|
+
|
|
446
|
+
## Contributing
|
|
447
|
+
|
|
448
|
+
1. Fork the repository
|
|
449
|
+
2. Create a branch: `git checkout -b feat/your-feature`
|
|
450
|
+
3. Make your changes
|
|
451
|
+
4. Run `npm run typecheck` and `npm run build`
|
|
452
|
+
5. Commit with [Conventional Commits](https://www.conventionalcommits.org/)
|
|
453
|
+
6. Open a Pull Request
|
|
454
|
+
|
|
455
|
+
---
|
|
456
|
+
|
|
457
|
+
Built by [Sina Meraji](https://github.com/sinameraji) and [contributors](https://github.com/sinameraji/autopilot/graphs/contributors) · MIT License
|
package/dist/index.d.ts
ADDED