kiwimatecoder 0.1.0__py3-none-any.whl
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.
- kiwimatecoder/__init__.py +8 -0
- kiwimatecoder/__main__.py +12 -0
- kiwimatecoder/acp/__init__.py +13 -0
- kiwimatecoder/acp/protocol.py +115 -0
- kiwimatecoder/acp/server.py +823 -0
- kiwimatecoder/acp/stdio.py +32 -0
- kiwimatecoder/agent.py +1162 -0
- kiwimatecoder/ai.py +68 -0
- kiwimatecoder/audit.py +65 -0
- kiwimatecoder/browser.py +261 -0
- kiwimatecoder/catalog.py +445 -0
- kiwimatecoder/checkpoints.py +103 -0
- kiwimatecoder/client.py +820 -0
- kiwimatecoder/clipboard.py +99 -0
- kiwimatecoder/commands.py +6757 -0
- kiwimatecoder/config.py +5335 -0
- kiwimatecoder/diagnostics.py +295 -0
- kiwimatecoder/documents.py +299 -0
- kiwimatecoder/evals/__init__.py +39 -0
- kiwimatecoder/evals/cases.py +230 -0
- kiwimatecoder/evals/render.py +46 -0
- kiwimatecoder/evals/runner.py +319 -0
- kiwimatecoder/events.py +95 -0
- kiwimatecoder/forge.py +172 -0
- kiwimatecoder/git.py +164 -0
- kiwimatecoder/headless.py +255 -0
- kiwimatecoder/hooks.py +170 -0
- kiwimatecoder/hunks.py +260 -0
- kiwimatecoder/i18n.py +368 -0
- kiwimatecoder/images.py +195 -0
- kiwimatecoder/index/__init__.py +14 -0
- kiwimatecoder/index/builder.py +376 -0
- kiwimatecoder/index/embeddings.py +151 -0
- kiwimatecoder/index/search.py +247 -0
- kiwimatecoder/index/store.py +251 -0
- kiwimatecoder/instructions.py +83 -0
- kiwimatecoder/jobs.py +594 -0
- kiwimatecoder/lsp/__init__.py +56 -0
- kiwimatecoder/lsp/client.py +548 -0
- kiwimatecoder/lsp/manager.py +353 -0
- kiwimatecoder/lsp/protocol.py +79 -0
- kiwimatecoder/main.py +4258 -0
- kiwimatecoder/mcp/__init__.py +45 -0
- kiwimatecoder/mcp/client.py +385 -0
- kiwimatecoder/mcp/errors.py +7 -0
- kiwimatecoder/mcp/manager.py +253 -0
- kiwimatecoder/mcp/protocol.py +132 -0
- kiwimatecoder/media.py +904 -0
- kiwimatecoder/memory.py +141 -0
- kiwimatecoder/network.py +112 -0
- kiwimatecoder/notify.py +139 -0
- kiwimatecoder/permissions.py +171 -0
- kiwimatecoder/pickers.py +417 -0
- kiwimatecoder/plugins.py +245 -0
- kiwimatecoder/pricing.py +167 -0
- kiwimatecoder/prompts.py +213 -0
- kiwimatecoder/providers.py +342 -0
- kiwimatecoder/redaction.py +66 -0
- kiwimatecoder/remote.py +294 -0
- kiwimatecoder/repl.py +1388 -0
- kiwimatecoder/routing.py +65 -0
- kiwimatecoder/sandbox.py +169 -0
- kiwimatecoder/sdk.py +146 -0
- kiwimatecoder/session.py +574 -0
- kiwimatecoder/share.py +386 -0
- kiwimatecoder/shell.py +660 -0
- kiwimatecoder/skills.py +138 -0
- kiwimatecoder/sync.py +513 -0
- kiwimatecoder/team.py +249 -0
- kiwimatecoder/telemetry.py +392 -0
- kiwimatecoder/templates.py +108 -0
- kiwimatecoder/tools/__init__.py +190 -0
- kiwimatecoder/tools/ask.py +62 -0
- kiwimatecoder/tools/base.py +69 -0
- kiwimatecoder/tools/browser.py +261 -0
- kiwimatecoder/tools/edit_file.py +143 -0
- kiwimatecoder/tools/forge.py +207 -0
- kiwimatecoder/tools/git.py +158 -0
- kiwimatecoder/tools/image.py +300 -0
- kiwimatecoder/tools/io.py +346 -0
- kiwimatecoder/tools/list_dir.py +67 -0
- kiwimatecoder/tools/lsp.py +254 -0
- kiwimatecoder/tools/memory.py +115 -0
- kiwimatecoder/tools/paths.py +234 -0
- kiwimatecoder/tools/read_file.py +113 -0
- kiwimatecoder/tools/registry.py +91 -0
- kiwimatecoder/tools/run_bash.py +189 -0
- kiwimatecoder/tools/search.py +224 -0
- kiwimatecoder/tools/selection.py +108 -0
- kiwimatecoder/tools/shell.py +158 -0
- kiwimatecoder/tools/skill.py +46 -0
- kiwimatecoder/tools/task.py +61 -0
- kiwimatecoder/tools/todo.py +77 -0
- kiwimatecoder/tools/web.py +146 -0
- kiwimatecoder/tools/write_file.py +83 -0
- kiwimatecoder/ui.py +189 -0
- kiwimatecoder/updater.py +502 -0
- kiwimatecoder/web.py +499 -0
- kiwimatecoder-0.1.0.dist-info/METADATA +2016 -0
- kiwimatecoder-0.1.0.dist-info/RECORD +104 -0
- kiwimatecoder-0.1.0.dist-info/WHEEL +5 -0
- kiwimatecoder-0.1.0.dist-info/entry_points.txt +2 -0
- kiwimatecoder-0.1.0.dist-info/licenses/LICENSE +21 -0
- kiwimatecoder-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,2016 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: kiwimatecoder
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: AI-powered coding assistant CLI. Bring your own API key.
|
|
5
|
+
License: MIT License
|
|
6
|
+
|
|
7
|
+
Copyright (c) 2026 Kyle8933
|
|
8
|
+
|
|
9
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
10
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
11
|
+
in the Software without restriction, including without limitation the rights
|
|
12
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
13
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
14
|
+
furnished to do so, subject to the following conditions:
|
|
15
|
+
|
|
16
|
+
The above copyright notice and this permission notice shall be included in all
|
|
17
|
+
copies or substantial portions of the Software.
|
|
18
|
+
|
|
19
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
20
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
21
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
22
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
23
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
24
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
25
|
+
SOFTWARE.
|
|
26
|
+
|
|
27
|
+
Requires-Python: >=3.10
|
|
28
|
+
Description-Content-Type: text/markdown
|
|
29
|
+
License-File: LICENSE
|
|
30
|
+
Requires-Dist: typer>=0.12
|
|
31
|
+
Requires-Dist: rich>=13
|
|
32
|
+
Requires-Dist: httpx>=0.27
|
|
33
|
+
Requires-Dist: prompt_toolkit>=3.0.52
|
|
34
|
+
Provides-Extra: browser
|
|
35
|
+
Requires-Dist: playwright>=1.40; extra == "browser"
|
|
36
|
+
Provides-Extra: dev
|
|
37
|
+
Requires-Dist: pytest>=8; extra == "dev"
|
|
38
|
+
Requires-Dist: pytest-asyncio>=0.23; extra == "dev"
|
|
39
|
+
Requires-Dist: click>=8.0; extra == "dev"
|
|
40
|
+
Dynamic: license-file
|
|
41
|
+
|
|
42
|
+
# kiwimatecoder
|
|
43
|
+
|
|
44
|
+
An agentic AI coding assistant for your terminal. Run one command and drop into an
|
|
45
|
+
interactive session that can read, edit, and run code in your project — across the
|
|
46
|
+
model provider of your choice. Bring your own API key.
|
|
47
|
+
|
|
48
|
+
## Installation
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
pip install -e .
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
For a regular (non-editable) install:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
pip install .
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Installation options
|
|
61
|
+
|
|
62
|
+
**Install script** (no clone needed; installs from GitHub):
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
curl -fsSL https://raw.githubusercontent.com/Kyle8933/kiwimatecoder/main/scripts/install.sh | sh
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
The script checks for Python >= 3.10, prefers `pipx` when available (falling
|
|
69
|
+
back to `pip install --user`), verifies `kiwimatecoder --version`, and prints
|
|
70
|
+
PATH guidance when the console script is not yet visible. Append `-s <ref>` to
|
|
71
|
+
install a tag, branch, or commit, or set `KIWIMATECODER_REF`.
|
|
72
|
+
|
|
73
|
+
**Docker:**
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
docker build -t kiwimatecoder .
|
|
77
|
+
docker run --rm -it -v "$PWD:/workspace" -e OPENROUTER_API_KEY kiwimatecoder
|
|
78
|
+
docker run --rm -v "$PWD:/workspace" -e OPENROUTER_API_KEY kiwimatecoder \
|
|
79
|
+
-p "Summarize this repository" --model anthropic/claude-sonnet-5
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
The image is `python:3.12-slim`, installs the package, and runs as the
|
|
83
|
+
non-root `kiwimate` user with `/workspace` as the working directory. A fresh
|
|
84
|
+
container has no saved config, so no model is chosen: pass `--model` (see
|
|
85
|
+
[Choosing a model](#choosing-a-model)).
|
|
86
|
+
|
|
87
|
+
**Homebrew:** `packaging/homebrew/kiwimatecoder.rb` is a virtualenv formula
|
|
88
|
+
template pinned to a git tag. It is not published to a tap yet; fill in the
|
|
89
|
+
tag revision and generate the `resource` blocks as described in the file, then
|
|
90
|
+
install with `brew install --build-from-source ./packaging/homebrew/kiwimatecoder.rb`.
|
|
91
|
+
|
|
92
|
+
## Quick start
|
|
93
|
+
|
|
94
|
+
Add an API key for at least one provider, then launch the interactive session:
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
kiwimatecoder setup
|
|
98
|
+
kiwimatecoder
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
`kiwimatecoder setup` walks you through choosing a provider, saving its API
|
|
102
|
+
key, and choosing the model to use with it. There are no default models: after
|
|
103
|
+
the key is saved, setup shows the provider's model list (plus **Type a model
|
|
104
|
+
id…** for anything unlisted), and your pick is remembered for that provider.
|
|
105
|
+
You can also pass the arguments directly:
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
kiwimatecoder setup --provider openrouter
|
|
109
|
+
kiwimatecoder setup --provider openai --key sk-... --model gpt-5.6-sol # non-interactive
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Without a terminal (or if you cancel the picker) and no earlier choice, setup
|
|
113
|
+
prints `No model chosen yet` (a local server instead uses the first model it
|
|
114
|
+
lists); the REPL then asks for a model when it starts, or you can set one later
|
|
115
|
+
with `kiwimatecoder config model set <id>`. At launch the REPL also asks about
|
|
116
|
+
any fallback provider on the roster that has no model (failover skips those),
|
|
117
|
+
and `kiwimatecoder doctor` warns about them.
|
|
118
|
+
|
|
119
|
+
Running `kiwimatecoder` with no arguments opens the interactive REPL. It keeps
|
|
120
|
+
running until you exit. Type a request in plain language and KiwiMateCoder will
|
|
121
|
+
read files, search the codebase, propose edits, and run commands to carry it
|
|
122
|
+
out. For larger or ambiguous tasks, it starts with a short plan and gives you a
|
|
123
|
+
few concrete options so you can choose the scope and tradeoffs before it
|
|
124
|
+
proceeds.
|
|
125
|
+
|
|
126
|
+
```
|
|
127
|
+
kiwi (openrouter:anthropic/claude-sonnet-5 · ask) › add a docstring to main.py
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
- **Ctrl-C** cancels the current turn and returns you to the prompt; whatever
|
|
131
|
+
the model had already streamed is kept in the conversation so you can continue
|
|
132
|
+
from it.
|
|
133
|
+
- **Ctrl-D** exits the session.
|
|
134
|
+
- While the agent is working you can type ahead: press Enter to send a steering
|
|
135
|
+
message and the model picks it up on its next step, or type a slash command
|
|
136
|
+
(e.g. `/undo`) and it runs as soon as the turn finishes. Ctrl-C during the
|
|
137
|
+
turn cancels it.
|
|
138
|
+
- Your prompt history is saved; the up-arrow recalls commands from previous
|
|
139
|
+
sessions.
|
|
140
|
+
- Every session is auto-saved when you exit. Pick it back up with
|
|
141
|
+
`kiwimatecoder --continue` (same as `--resume last`), or from inside the REPL
|
|
142
|
+
with `/load last`.
|
|
143
|
+
- Type `/` to open the slash-command menu. It filters as you keep typing.
|
|
144
|
+
- Run `/model`, `/provider`, or `/mode` without an argument to open a
|
|
145
|
+
keyboard-driven selector. `/provider` is a checklist: check every provider you
|
|
146
|
+
want on the failover roster. The first checked provider is the primary; the
|
|
147
|
+
rest are tried in order if the primary fails. Experimental providers
|
|
148
|
+
(currently KiwiMate) appear in their own **Experimental** box at the top of
|
|
149
|
+
the list. After you confirm, you choose a model for every provider on the
|
|
150
|
+
roster that does not have one yet. `/provider <id>` replaces the roster with
|
|
151
|
+
that single provider (and asks for its model if none is chosen). Arrow keys
|
|
152
|
+
move, Enter selects, and Ctrl-C returns to the prompt without changing
|
|
153
|
+
anything.
|
|
154
|
+
- Opening `/model` checks the provider for models released since you last looked,
|
|
155
|
+
and drops any it has retired. `/model refresh` forces the check. The model you
|
|
156
|
+
pick is saved as that provider's model for the next session. Each provider
|
|
157
|
+
remembers its own model, so switching the primary with `/provider` uses the
|
|
158
|
+
model chosen for the new primary instead of carrying a vendor-specific id
|
|
159
|
+
across providers. `/config model reset` forgets the choice: pick another with
|
|
160
|
+
`/model` (local servers fall back to the first model they list).
|
|
161
|
+
- `/model search <term>` searches the provider's full catalog by name and opens
|
|
162
|
+
the selector on the matches — useful when a model is older than the newest few
|
|
163
|
+
that `/model` lists.
|
|
164
|
+
- Use `/mode plan` when you only want investigation and options, with no edits or
|
|
165
|
+
shell commands.
|
|
166
|
+
|
|
167
|
+
## Permission modes
|
|
168
|
+
|
|
169
|
+
The agent can edit files and run shell commands. A permission mode controls how much
|
|
170
|
+
it can do without asking, and you can switch it at any time with `/mode`:
|
|
171
|
+
|
|
172
|
+
| Mode | Behavior |
|
|
173
|
+
|------|----------|
|
|
174
|
+
| `ask` (default) | Reads run freely; every file write/edit or shell command shows a preview/diff and waits for your approval. |
|
|
175
|
+
| `auto-accept` | Actions run without prompting. |
|
|
176
|
+
| `plan` | Read-only: the agent can inspect and explain, but cannot write or run anything. |
|
|
177
|
+
|
|
178
|
+
At an approval prompt, answer `a` (always) to approve that tool for the rest of
|
|
179
|
+
the session **and future sessions**. Persisted approvals survive restarts and
|
|
180
|
+
provider switches; manage them with `/config permissions` or
|
|
181
|
+
`config permissions list|remove|clear`. When a diff spans multiple hunks, answer
|
|
182
|
+
`h` to choose which hunks to apply (e.g. `1,3`, `1-2`, `all`, or `none`).
|
|
183
|
+
|
|
184
|
+
Every mutating action is checkpointed before it runs. Restore the last change
|
|
185
|
+
with `/undo`, rewind several steps with `/undo 3`, and list them with
|
|
186
|
+
`/checkpoints`.
|
|
187
|
+
|
|
188
|
+
Reads, writes, edits, listings and searches are sandboxed to the workspace root (via symlink-aware path resolution). `run_bash` commands execute with the workspace root as their cwd but are otherwise unrestricted (subject to approval/mode); use them for git, tests, builds, etc.
|
|
189
|
+
|
|
190
|
+
### Command rules
|
|
191
|
+
|
|
192
|
+
Auto-approve trusted commands and hard-block dangerous ones with regex rules
|
|
193
|
+
(deny rules block even in `auto-accept` mode):
|
|
194
|
+
|
|
195
|
+
```text
|
|
196
|
+
/config commands allow ^pytest\b
|
|
197
|
+
/config commands deny rm\s+-rf
|
|
198
|
+
/config commands list
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### Dry run and trusted workspace
|
|
202
|
+
|
|
203
|
+
`/dry-run` previews every mutating tool call (diffs and shell commands) without
|
|
204
|
+
executing anything or prompting. `/config trust on` lets read-only tools read
|
|
205
|
+
paths outside the workspace root; writes stay sandboxed.
|
|
206
|
+
|
|
207
|
+
## Slash commands
|
|
208
|
+
|
|
209
|
+
| Command | Description |
|
|
210
|
+
|---------|-------------|
|
|
211
|
+
| `/help` | Show available commands. |
|
|
212
|
+
| `/exit`, `/quit` | Leave the session. |
|
|
213
|
+
| `/clear` | Clear the conversation history. |
|
|
214
|
+
| `/model [name\|refresh\|list\|search <term>]` | Interactively choose a model (the list is refreshed from the provider), set one by name, refresh/show the list, or search the full catalog by name. The choice is remembered for that provider. |
|
|
215
|
+
| `/provider [id]` | Choose a failover roster (checklist; experimental providers sit in their own box at the top), or replace it with one provider by id. Asks for a model for each provider that has none. |
|
|
216
|
+
| `/mode [ask\|auto-accept\|plan]` | Interactively choose, or directly set, the permission mode. |
|
|
217
|
+
| `/dry-run [on\|off\|toggle]` | Preview mutating actions without running them. |
|
|
218
|
+
| `/undo [count]`, `/checkpoints` | Restore files changed by recent tools, or list checkpoints. |
|
|
219
|
+
| `/todos` | Show the agent's task list. |
|
|
220
|
+
| `/templates` | List custom prompt templates discovered in the workspace and user command directories. |
|
|
221
|
+
| `/compact [budget]` | Trim older history to fit a token budget. |
|
|
222
|
+
| `/save`, `/load`, `/sessions`, `/fork [name]`, `/export [path]` | Save, resume, branch, or export sessions as Markdown. |
|
|
223
|
+
| `/share [gist] [--include-tool-output]`, `/share import <path> [--name NAME]` | Share a redacted session bundle as a local file or a secret GitHub gist, or import one as a saved session. |
|
|
224
|
+
| `/sync [status\|push\|pull]` | Show or sync saved sessions across machines through a shared folder (opt-in). |
|
|
225
|
+
| `/tools` | List available tools. |
|
|
226
|
+
| `/files` | List files changed this session. |
|
|
227
|
+
| `/context [list\|add\|remove\|clear]` | Pin files to include as context on every turn. |
|
|
228
|
+
| `/image model [list\|refresh\|search <term>\|<id>]`, `/image [--size WxH] [--model id] <prompt>` | Generate an image with the configured media provider and attach it to your next message (opt-in; see [Image and video generation](#image-and-video-generation)). |
|
|
229
|
+
| `/video model [list\|refresh\|search <term>\|<id>]`, `/video [--duration s] [--size 720p] [--model id] [--image path] <prompt>`, `/video resume <job-id>` | Generate a short video (billed per second; takes minutes), or fetch a job that was still rendering. |
|
|
230
|
+
| `/media [list [count]\|provider [id]]` | Show whether image and video generation are ready, list recently generated files, or switch the media provider. |
|
|
231
|
+
| `/memory [list\|add\|add-user\|clear]` | Show or edit persistent project and user memory. |
|
|
232
|
+
| `/index [status\|build\|clear]` | Show, refresh, or delete the local codebase index used by semantic search. |
|
|
233
|
+
| `/jobs [list\|show <id>\|cancel <id>\|tick\|run <prompt>]` | List or manage detached background agent jobs; `tick` starts due scheduled runs. |
|
|
234
|
+
| `/config` | Show or change providers, keys, models, filters, permissions, command rules, sampling, styles, themes, output modes, accessibility, verify, and budgets. |
|
|
235
|
+
| `/mcp [list\|reload]` | List configured MCP servers, their status, and registered tools; `reload` reconnects every server. |
|
|
236
|
+
| `/cost` | Show token usage, context gauge, and estimated USD cost for this session (per-model pricing). |
|
|
237
|
+
| `/doctor` | Run environment, config, provider, and workspace diagnostics. |
|
|
238
|
+
|
|
239
|
+
Examples:
|
|
240
|
+
|
|
241
|
+
```text
|
|
242
|
+
/context add README.md kiwimatecoder/*.py
|
|
243
|
+
/undo 2
|
|
244
|
+
/export review.md
|
|
245
|
+
/fork experiment
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
Config examples:
|
|
249
|
+
|
|
250
|
+
```text
|
|
251
|
+
/config
|
|
252
|
+
/config provider add local "Local Models" http://localhost:1234/v1 local-code LOCAL_API_KEY
|
|
253
|
+
/config provider edit local name="Local Models 2" model=local-fast
|
|
254
|
+
/config key set local <YOUR_KEY>
|
|
255
|
+
/config provider use local
|
|
256
|
+
/config model set anthropic/claude-sonnet-5 openrouter
|
|
257
|
+
/config model reset openrouter
|
|
258
|
+
/config models allow local-code local-fast
|
|
259
|
+
/config models deny noisy-model
|
|
260
|
+
/config models refresh
|
|
261
|
+
/config mode set plan
|
|
262
|
+
/config permissions list
|
|
263
|
+
/config permissions remove run_bash
|
|
264
|
+
/config commands allow ^pytest\b
|
|
265
|
+
/config commands deny rm\s+-rf
|
|
266
|
+
/config sampling set temperature=0.2 max_tokens=4096
|
|
267
|
+
/config sampling reset
|
|
268
|
+
/config style set concise
|
|
269
|
+
/config ui theme ocean
|
|
270
|
+
/config ui output compact
|
|
271
|
+
/config ui ascii on
|
|
272
|
+
/config prompt set "Prefer functional style; never use classes."
|
|
273
|
+
/config prompt clear
|
|
274
|
+
/config verify set "pytest -q"
|
|
275
|
+
/config budget tokens 500000
|
|
276
|
+
/config budget cost 5.00
|
|
277
|
+
/config trust on
|
|
278
|
+
/config remote host devbox
|
|
279
|
+
/config remote user kiwi
|
|
280
|
+
/config remote workspace /srv/app
|
|
281
|
+
/config remote enable on
|
|
282
|
+
/config browser enable on
|
|
283
|
+
/config browser headless off
|
|
284
|
+
/config browser timeout 20000
|
|
285
|
+
/config provider remove local
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
Running bare `/config` opens an interactive menu. Picking an entry lets you
|
|
289
|
+
change that setting: toggles and fixed choices (theme, locale, log level, …) are
|
|
290
|
+
picked from a list, free-form values (a proxy URL, an image size, a regex) are
|
|
291
|
+
typed, and each list shows the current value. Sections with several independent
|
|
292
|
+
settings, such as **Media** or **UI**, return to their list after each change
|
|
293
|
+
until you pick **Done** (Ctrl-C also leaves; at a typed prompt, Ctrl-C or an
|
|
294
|
+
empty line cancels just that entry). **Keys** works the same way: choose a
|
|
295
|
+
provider, then set (type a new key, which is not shown as you type) or remove
|
|
296
|
+
it. Only **Show** and **help** just print. Every entry also works as a typed
|
|
297
|
+
command as shown above, and `/config key set` / `/config key list` always show
|
|
298
|
+
which file or environment variable the active key comes from.
|
|
299
|
+
|
|
300
|
+
## Tools
|
|
301
|
+
|
|
302
|
+
The assistant has these capabilities, all scoped to the workspace:
|
|
303
|
+
|
|
304
|
+
- `read_file`, `list_dir`, `search` (grep + glob + semantic) — read-only,
|
|
305
|
+
always allowed; batches of read-only calls run in parallel.
|
|
306
|
+
- `view_image` — attach a workspace image (`.png`, `.jpg`, `.jpeg`, `.gif`,
|
|
307
|
+
`.webp`) so a vision-capable model can see it (see below).
|
|
308
|
+
- `generate_image`, `generate_video` — create an image or a short video through the
|
|
309
|
+
configured media provider and save it under `.kiwimatecoder/media/` (opt-in and
|
|
310
|
+
approval-gated because they cost money; see below).
|
|
311
|
+
- `write_file`, `edit_file` — create/modify files (approval-gated; each is
|
|
312
|
+
checkpointed first so `/undo` can restore it).
|
|
313
|
+
- `run_bash` — run shell commands (approval-gated, subject to command rules).
|
|
314
|
+
- `shell` — run a command in a persistent shell that remembers `cd` and exported
|
|
315
|
+
environment state between calls (approval-gated; see below).
|
|
316
|
+
- `shell_jobs` — start, list, read, or kill detached background commands
|
|
317
|
+
(approval-gated; see below).
|
|
318
|
+
- `update_todos` — keep the visible task list in sync with multi-step work.
|
|
319
|
+
- `task` — delegate a focused investigation to a subagent with its own context
|
|
320
|
+
(approval-gated; see below).
|
|
321
|
+
- `ask_user` — ask a clarifying question with optional choices (interactive
|
|
322
|
+
sessions only).
|
|
323
|
+
- `web_fetch`, `web_search` — read a page or search the web; read-only, and
|
|
324
|
+
local/private addresses are blocked by default (see below).
|
|
325
|
+
- `browser` — drive an optional headless Chromium page (screenshot, click,
|
|
326
|
+
type, evaluate) when Playwright is installed and browser automation is
|
|
327
|
+
enabled (approval-gated; see below).
|
|
328
|
+
- `remember`, `recall` — persist and read durable facts across sessions (see
|
|
329
|
+
below).
|
|
330
|
+
- `git`, `git_write` — inspect status/diff/log and stage, unstage, commit, or
|
|
331
|
+
create a branch (see below).
|
|
332
|
+
- `forge`, `forge_write` — list/view or create pull requests/merge requests
|
|
333
|
+
and issues through the `gh`/`glab` CLI (see below).
|
|
334
|
+
- `read_clipboard`, `write_clipboard` — read the system clipboard or copy text
|
|
335
|
+
to it (see below).
|
|
336
|
+
- `http_get`, `http_request` — exercise an HTTP API and inspect the response
|
|
337
|
+
(see below).
|
|
338
|
+
- `lsp_diagnostics`, `lsp_definition`, `lsp_references` — language-server
|
|
339
|
+
diagnostics and navigation, when enabled (see below).
|
|
340
|
+
|
|
341
|
+
## Persistent shell
|
|
342
|
+
|
|
343
|
+
`run_bash` starts a fresh process per call, so `cd` and exported environment
|
|
344
|
+
variables never survive between commands. The `shell` tool instead drives one
|
|
345
|
+
long-lived shell per session (`/bin/sh` on POSIX, Git Bash on Windows; install
|
|
346
|
+
Git for Windows, or turn it off with `config shell persistent off`) so state
|
|
347
|
+
sticks:
|
|
348
|
+
|
|
349
|
+
```text
|
|
350
|
+
shell: cd backend
|
|
351
|
+
shell: source .venv/bin/activate
|
|
352
|
+
shell: pytest -q # runs inside backend with the venv active
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
- The shell starts in the session workspace root. Output (stdout + stderr
|
|
356
|
+
combined) is capped at 30 KB with a truncation note, and every call reports
|
|
357
|
+
the exit code.
|
|
358
|
+
- A command that exceeds the timeout (default 120 s) is killed and the shell is
|
|
359
|
+
restarted, so a hung command can never wedge the session.
|
|
360
|
+
- `shell_jobs` runs commands detached from the shell and captures their output
|
|
361
|
+
under `~/.kiwimatecoder/jobs/shell/`. `action: list` shows tracked jobs,
|
|
362
|
+
`action: output` reads one, and `action: kill` terminates it. At most
|
|
363
|
+
`shell.max_jobs` (default 8) run at once.
|
|
364
|
+
- Settings: `/config shell [show|persistent on|off|timeout <s>|max-jobs <n>]`
|
|
365
|
+
in the REPL, or `kiwimatecoder config shell ...` from the shell.
|
|
366
|
+
- Exiting the session terminates the persistent shell and every tracked
|
|
367
|
+
background job. `run_bash` is unchanged and still the right tool for
|
|
368
|
+
one-shot commands.
|
|
369
|
+
|
|
370
|
+
## Command sandboxing
|
|
371
|
+
|
|
372
|
+
On macOS and Linux you can execute `run_bash` (and the persistent shell and its
|
|
373
|
+
background jobs) through an OS-level sandbox. It is **off by default**:
|
|
374
|
+
|
|
375
|
+
```bash
|
|
376
|
+
kiwimatecoder config sandbox show
|
|
377
|
+
kiwimatecoder config sandbox enable on
|
|
378
|
+
kiwimatecoder config sandbox network off # block network access
|
|
379
|
+
kiwimatecoder config sandbox add-path ~/shared # extra writable directory
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
The REPL equivalent is `/config sandbox [show|enable on|off|network on|off|
|
|
383
|
+
add-path <path>|remove-path <path>|clear-paths]`.
|
|
384
|
+
|
|
385
|
+
- **macOS** uses seatbelt via `sandbox-exec`: `process*` is allowed, reads are
|
|
386
|
+
broadly allowed, and writes are limited to the workspace, `/tmp`, and
|
|
387
|
+
`extra_writable`.
|
|
388
|
+
- **Linux** uses bubblewrap (`bwrap`): `/` is mounted read-only, the workspace
|
|
389
|
+
is read-write, `/tmp` is a private tmpfs, and `--unshare-net` is added when
|
|
390
|
+
the network toggle is off. Install the `bubblewrap` package to use it.
|
|
391
|
+
- Windows has no supported backend; enabling it there falls back to running
|
|
392
|
+
unsandboxed with a warning in the tool output.
|
|
393
|
+
- When the sandbox is enabled, the approval preview shows the wrapped command
|
|
394
|
+
and the network mode. If the backend is missing or fails to start, the tool
|
|
395
|
+
warns and runs the command unsandboxed rather than failing.
|
|
396
|
+
- Config lives in the `sandbox` section:
|
|
397
|
+
`{"enabled": false, "network": true, "extra_writable": []}`.
|
|
398
|
+
|
|
399
|
+
> **Limitations:** the sandbox is a damage-limiter for ordinary commands, not a
|
|
400
|
+
> security boundary against a hostile model or malicious code. Reads stay
|
|
401
|
+
> broad, the sandbox runs with your user's privileges (no user namespaces or
|
|
402
|
+
> credential isolation on macOS), and an unavailable backend silently degrades
|
|
403
|
+
> to an unsandboxed shell with only a warning. Read access to API keys stored
|
|
404
|
+
> on disk is not blocked, so use `--mode plan` or command rules when that
|
|
405
|
+
> matters.
|
|
406
|
+
|
|
407
|
+
## Remote and devcontainer execution
|
|
408
|
+
|
|
409
|
+
Shell commands can run on another machine over SSH or inside a
|
|
410
|
+
devcontainer/Docker container. `run_bash`, the persistent `shell`, and
|
|
411
|
+
`shell_jobs` all execute remotely when it is configured; the approval preview
|
|
412
|
+
shows the wrapper and tool output includes a `[remote]` note. It is **off by
|
|
413
|
+
default**:
|
|
414
|
+
|
|
415
|
+
```bash
|
|
416
|
+
kiwimatecoder config remote show
|
|
417
|
+
kiwimatecoder config remote host devbox # ssh [user@]host
|
|
418
|
+
kiwimatecoder config remote user kiwi # optional
|
|
419
|
+
kiwimatecoder config remote port 2222 # optional (default 22)
|
|
420
|
+
kiwimatecoder config remote identity ~/.ssh/id_ed25519 # optional
|
|
421
|
+
kiwimatecoder config remote workspace /srv/app # cd before running
|
|
422
|
+
kiwimatecoder config remote devcontainer auto # auto|off|container name
|
|
423
|
+
kiwimatecoder config remote enable on
|
|
424
|
+
```
|
|
425
|
+
|
|
426
|
+
The REPL equivalent is `/config remote [show|enable on|off|host <h>|user <u>|
|
|
427
|
+
port <n>|identity <path>|workspace <path>|devcontainer <auto|off|name>]`.
|
|
428
|
+
|
|
429
|
+
When `devcontainer` is `auto` (the default), the first usable route wins:
|
|
430
|
+
|
|
431
|
+
1. a `.devcontainer/devcontainer.json` in the workspace **and** the
|
|
432
|
+
`devcontainer` CLI: `devcontainer exec --workspace-folder <ws> sh -lc ...`;
|
|
433
|
+
2. that detected container through `docker exec -w <workspaceFolder>
|
|
434
|
+
<name> ...`;
|
|
435
|
+
3. SSH when `remote.host` is set: `ssh -o BatchMode=yes [-p <port>]
|
|
436
|
+
[-i <identity>] [user@]host -- sh -lc ...`, with
|
|
437
|
+
`cd <remote.workspace> && <command>` when a remote workspace is set;
|
|
438
|
+
4. local execution with a warning in the tool output.
|
|
439
|
+
|
|
440
|
+
Set `devcontainer off` to skip detection, or name a container explicitly to
|
|
441
|
+
force `docker exec`. Remote wrapping happens first and a remote command is not
|
|
442
|
+
additionally wrapped in a local sandbox. If `ssh`, `docker`, or `devcontainer`
|
|
443
|
+
is missing, the command runs locally and the output carries the warning.
|
|
444
|
+
|
|
445
|
+
- Config lives in the `remote` section:
|
|
446
|
+
`{"enabled": false, "host": "", "user": "", "port": 22, "identity": "",
|
|
447
|
+
"workspace": "", "devcontainer": "auto"}`. `identity` must point at an
|
|
448
|
+
existing key file, and enabling remote execution requires a host (or an
|
|
449
|
+
explicit container name).
|
|
450
|
+
- The persistent shell starts through the same wrapper, so `cd` and exported
|
|
451
|
+
variables persist on the remote side. SSH uses agent/key auth only
|
|
452
|
+
(`BatchMode=yes`); there is no password prompt.
|
|
453
|
+
|
|
454
|
+
> **Limitations:** only commands run remotely. File tools (`read_file`,
|
|
455
|
+
> `write_file`, `edit_file`, `search`, ...) still read the **locally**
|
|
456
|
+
> accessible workspace, so point them at the remote tree with sshfs, a bind
|
|
457
|
+
> mount, or a synced checkout. A full SFTP-backed file layer is deliberately
|
|
458
|
+
> not shipped: a half-working remote filesystem would silently split reads and
|
|
459
|
+
> writes between two machines. Detached agent jobs (`/jobs`) also run locally
|
|
460
|
+
> against that same local view. SSH host keys and identity files are the
|
|
461
|
+
> user's responsibility; remote command approval and command rules work
|
|
462
|
+
> exactly as they do locally.
|
|
463
|
+
|
|
464
|
+
## Web access
|
|
465
|
+
|
|
466
|
+
`web_search` searches the web with the DuckDuckGo HTML endpoint (no API key)
|
|
467
|
+
and returns titles, URLs, and snippets. `web_fetch` downloads a page,
|
|
468
|
+
follows redirects, converts HTML to readable text, and summarizes binary
|
|
469
|
+
responses instead of dumping them. Both are read-only tools, so they run
|
|
470
|
+
without approval and stay available in plan mode, and both descriptions tell
|
|
471
|
+
the model to cite the URLs it relies on.
|
|
472
|
+
|
|
473
|
+
- Response size is capped with a truncation note; defaults are 50,000
|
|
474
|
+
characters and a 20-second timeout.
|
|
475
|
+
- `localhost`, loopback/private/link-local IPs, and `*.local` hosts are
|
|
476
|
+
refused by default. Enable them with `/config web allow-local on` (or
|
|
477
|
+
`kiwimatecoder config web allow-local on`) when you are working against a
|
|
478
|
+
local dev server.
|
|
479
|
+
- Settings live under `/config web show|max-chars <n>|timeout <s>|allow-local <on|off>`
|
|
480
|
+
in the REPL, or `kiwimatecoder config web ...` from the shell.
|
|
481
|
+
- DuckDuckGo parses the public HTML page, so result extraction is best-effort
|
|
482
|
+
and may need updating if that page's markup changes; `web_fetch` is
|
|
483
|
+
unaffected.
|
|
484
|
+
|
|
485
|
+
## Proxy, custom CA, and offline mode
|
|
486
|
+
|
|
487
|
+
Every outbound request — chat streaming, model catalogs, `web_fetch`/
|
|
488
|
+
`web_search`, and embeddings — honors the `network` settings in
|
|
489
|
+
`~/.kiwimatecoder/config.json`:
|
|
490
|
+
|
|
491
|
+
```json
|
|
492
|
+
{
|
|
493
|
+
"network": {
|
|
494
|
+
"proxy": "http://proxy.corp:8080",
|
|
495
|
+
"ca_bundle": "/etc/ssl/certs/corp-ca.pem",
|
|
496
|
+
"offline": false
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
```
|
|
500
|
+
|
|
501
|
+
Set them from the REPL with `/config network ...` or from the shell with
|
|
502
|
+
`kiwimatecoder config network ...`:
|
|
503
|
+
|
|
504
|
+
```bash
|
|
505
|
+
kiwimatecoder config network show
|
|
506
|
+
kiwimatecoder config network proxy http://proxy.corp:8080 # or: clear
|
|
507
|
+
kiwimatecoder config network ca /etc/ssl/certs/corp-ca.pem # or: clear
|
|
508
|
+
kiwimatecoder config network offline on # or: off
|
|
509
|
+
```
|
|
510
|
+
|
|
511
|
+
- `proxy` routes all requests through an HTTP(S) proxy (`proxy`/`verify` are
|
|
512
|
+
passed to the underlying `httpx` clients).
|
|
513
|
+
- `ca_bundle` points at a PEM file used instead of the system trust store for
|
|
514
|
+
TLS verification — for corporate MITM proxies or self-signed CAs. The file
|
|
515
|
+
must exist when set.
|
|
516
|
+
- `offline on` is air-gapped mode: cloud chat, model catalogs, web tools, and
|
|
517
|
+
embeddings are refused with an "offline mode is enabled" error before any
|
|
518
|
+
request is made. **Local providers keep working** — `ollama`, `lmstudio`,
|
|
519
|
+
`unsloth`, and custom providers on `localhost`/`*.local` are still reachable
|
|
520
|
+
for chat, catalog, and embedding calls. `web_fetch`/`web_search` always
|
|
521
|
+
refuse offline because they only reach the public internet.
|
|
522
|
+
|
|
523
|
+
## Browser automation
|
|
524
|
+
|
|
525
|
+
The `browser` tool drives a headless Chromium page through Playwright when you
|
|
526
|
+
opt in. Playwright is not installed by default, and the tool stays hidden until
|
|
527
|
+
browser automation is enabled:
|
|
528
|
+
|
|
529
|
+
```bash
|
|
530
|
+
pip install 'kiwimatecoder[browser]'
|
|
531
|
+
playwright install chromium
|
|
532
|
+
kiwimatecoder config browser enable on
|
|
533
|
+
```
|
|
534
|
+
|
|
535
|
+
Without the extra, the tool returns a clear install hint instead of failing;
|
|
536
|
+
the base install keeps the same dependency set.
|
|
537
|
+
|
|
538
|
+
- The tool is approval-gated because a page can submit forms or trigger
|
|
539
|
+
downloads. In `ask` mode the preview shows `browser <action> <url|selector>`
|
|
540
|
+
(scripts are redacted and capped). It is not advertised while disabled, and
|
|
541
|
+
plan mode only advertises read-only tools.
|
|
542
|
+
- `open` accepts only `http(s)` URLs and refuses `localhost`, loopback/private
|
|
543
|
+
IPs, and `*.local` hosts unless `/config web allow-local on` is set. It
|
|
544
|
+
reports the final URL after redirects and the page title.
|
|
545
|
+
- `text` returns visible page text capped at ~30,000 characters with a
|
|
546
|
+
truncation note. `click`/`type` take a CSS selector, and `evaluate` runs
|
|
547
|
+
JavaScript and returns a capped JSON-ish result.
|
|
548
|
+
- `screenshot` saves a PNG to
|
|
549
|
+
`<workspace>/.kiwimatecoder/screenshots/<timestamp>.png` and attaches it to
|
|
550
|
+
the next request, so a vision-capable model sees it exactly like a
|
|
551
|
+
`view_image` attachment. The `vision` per-turn count and size limits apply.
|
|
552
|
+
- One page is shared by successive tool calls in a session; `close` (and
|
|
553
|
+
leaving the REPL) shuts Chromium down. `timeout_ms` can override the
|
|
554
|
+
configured action timeout per call.
|
|
555
|
+
- Settings live under `/config browser [show|enable on|off|headless on|off|timeout <ms>]`
|
|
556
|
+
in the REPL, or `kiwimatecoder config browser ...` from the shell (defaults:
|
|
557
|
+
off, headless on, 15,000 ms; timeout range 1s–120s). Changing a setting
|
|
558
|
+
closes the live page so the next call starts with the new values.
|
|
559
|
+
|
|
560
|
+
```text
|
|
561
|
+
Open https://example.com/docs and summarize the visible text.
|
|
562
|
+
Screenshot the pricing page and tell me what stands out.
|
|
563
|
+
Fill the search box with "playwright" and click Search.
|
|
564
|
+
```
|
|
565
|
+
|
|
566
|
+
## Git and forge tools
|
|
567
|
+
|
|
568
|
+
The agent can inspect and change git state through dedicated tools instead of
|
|
569
|
+
dropping to `run_bash`:
|
|
570
|
+
|
|
571
|
+
- `git` (read-only) — `status`, `diff` (staged or not, optionally against a
|
|
572
|
+
ref), `log` (1–100 commits), `show <ref>`, and `branches`.
|
|
573
|
+
- `git_write` (approval-gated) — `stage`, `unstage`, `commit` (a non-empty
|
|
574
|
+
message is required), and `checkout_branch` (creates a new branch). The
|
|
575
|
+
approval prompt shows the exact `git ...` command line.
|
|
576
|
+
- `forge` (read-only) — `pr_list`, `pr_view`, `issue_list`, and `issue_view`
|
|
577
|
+
for the forge detected from the `origin` remote.
|
|
578
|
+
- `forge_write` (approval-gated) — `pr_create` and `issue_create`.
|
|
579
|
+
|
|
580
|
+
Forge integration goes through the official CLI (`gh` for GitHub, `glab` for
|
|
581
|
+
GitLab), so your existing CLI login is used and no token is read or stored by
|
|
582
|
+
KiwiMateCoder. The matching CLI must be installed and authenticated; on
|
|
583
|
+
GitLab, pull requests are handled as merge requests (`glab mr ...`).
|
|
584
|
+
|
|
585
|
+
Intentionally out of scope: `push`, `reset`, `clean`, and any forge
|
|
586
|
+
merge/close/delete command. Those stay manual, or go through `run_bash` where
|
|
587
|
+
the command rules and approval prompt apply.
|
|
588
|
+
|
|
589
|
+
## Clipboard and HTTP tools
|
|
590
|
+
|
|
591
|
+
Clipboard access uses the platform's standard tool, discovered on `PATH` and
|
|
592
|
+
run without a shell: `pbpaste`/`pbcopy` on macOS, `wl-paste`/`wl-copy`
|
|
593
|
+
(preferred) or `xclip` on Linux, and PowerShell's `Get-Clipboard`/
|
|
594
|
+
`Set-Clipboard` on Windows. If none is installed the tool returns a clear
|
|
595
|
+
install hint instead of failing.
|
|
596
|
+
|
|
597
|
+
- `read_clipboard` is read-only, so it runs without approval.
|
|
598
|
+
- `write_clipboard` is approval-gated and the preview shows the redacted text
|
|
599
|
+
(clipped to ~200 characters).
|
|
600
|
+
|
|
601
|
+
`http_get` and `http_request` exercise HTTP APIs and print the status line,
|
|
602
|
+
selected response headers, and the body (JSON is pretty-printed, bodies are
|
|
603
|
+
truncated with a note). 4xx/5xx responses are returned for inspection rather
|
|
604
|
+
than raised, and ``httpx`` errors are converted to friendly messages.
|
|
605
|
+
|
|
606
|
+
- `http_get(url, headers?)` is read-only.
|
|
607
|
+
- `http_request(method, url, headers?, body?, json?, timeout?)` is
|
|
608
|
+
approval-gated because it can change remote state. Methods are GET, POST,
|
|
609
|
+
PUT, PATCH, and DELETE; `body` (raw text) and `json` are mutually exclusive.
|
|
610
|
+
- Both reuse the `web` settings: response size and timeout come from
|
|
611
|
+
`/config web max-chars` / `/config web timeout`, and local/private addresses
|
|
612
|
+
stay blocked unless `/config web allow-local on`.
|
|
613
|
+
|
|
614
|
+
```text
|
|
615
|
+
Read what's on my clipboard and save it to notes.txt.
|
|
616
|
+
Copy the test command to my clipboard.
|
|
617
|
+
GET https://api.github.com/repos/psf/requests and summarize the JSON.
|
|
618
|
+
POST https://httpbin.org/post with json {"hello": "world"}.
|
|
619
|
+
```
|
|
620
|
+
|
|
621
|
+
## Images
|
|
622
|
+
|
|
623
|
+
Attach images to a message three ways, all sharing the same size and count
|
|
624
|
+
limits:
|
|
625
|
+
|
|
626
|
+
- Type `@path/to/image.png` in a prompt. Existing image files under the
|
|
627
|
+
workspace are attached and removed from the text (a lone `@image.png` sends
|
|
628
|
+
"Please analyze the attached image(s)."). Paths that are missing, outside the
|
|
629
|
+
workspace, or not images are left in the text untouched.
|
|
630
|
+
- Paste or drag an image into the terminal. Most terminals insert the file path
|
|
631
|
+
at the cursor; `@`-mention extraction then attaches it on send.
|
|
632
|
+
- Let the model call the `view_image` tool when it needs to look at a file.
|
|
633
|
+
|
|
634
|
+
Each image is validated (extension and magic bytes), base64-encoded, and sent
|
|
635
|
+
to the model as an image part on the next request. Both OpenAI-compatible and
|
|
636
|
+
native Anthropic providers are supported. Limits live under
|
|
637
|
+
`/config vision [show|max-bytes <n>|max-images <n>]` (defaults: 5 MB per image,
|
|
638
|
+
4 images per turn); oversized or invalid images produce a clear message instead
|
|
639
|
+
of a failed request.
|
|
640
|
+
|
|
641
|
+
### Image and video generation
|
|
642
|
+
|
|
643
|
+
Generate images and short videos with your provider's media API and keep them in
|
|
644
|
+
the workspace. Generation is **opt-in** and approval-gated because it costs
|
|
645
|
+
money:
|
|
646
|
+
|
|
647
|
+
```text
|
|
648
|
+
/config media enable on
|
|
649
|
+
/config media provider openai
|
|
650
|
+
/image model list # pick an image model (or: /image model <id>)
|
|
651
|
+
/config media size 1024x1024
|
|
652
|
+
/image a red fox reading a book
|
|
653
|
+
```
|
|
654
|
+
|
|
655
|
+
Media models are chosen **per provider**, and there is no default: ids and prices
|
|
656
|
+
change quickly, so you pick one yourself. `/image model` shows the current image
|
|
657
|
+
model for the media provider; `/image model list` lists that provider's image
|
|
658
|
+
models (a picker in an interactive session, a table otherwise), `/image model
|
|
659
|
+
refresh` re-fetches the list, `/image model search <term>` filters it, and
|
|
660
|
+
`/image model <id>` sets an id directly (a single word: anything else is treated
|
|
661
|
+
as a mistyped prompt). `/video model` takes the same arguments for video.
|
|
662
|
+
`/media provider` shows the providers with their models (a picker when
|
|
663
|
+
interactive); `/media provider <id>` switches the provider the media tools use
|
|
664
|
+
and, interactively, offers to choose any missing models. Each provider remembers
|
|
665
|
+
its own image and video model, so switching providers does not lose your choice.
|
|
666
|
+
Because `model` is a subcommand, a prompt that starts with the word
|
|
667
|
+
`model` needs `--` first (`/image -- model railway in the snow`).
|
|
668
|
+
|
|
669
|
+
`/image [--size WxH] [--model <id>] <prompt>` saves a PNG under
|
|
670
|
+
`.kiwimatecoder/media/` and queues it for the next request. Options come before
|
|
671
|
+
the prompt, which is taken verbatim (quotes included); use `--` if a prompt
|
|
672
|
+
starts with dashes. The same generation is available to the model as the
|
|
673
|
+
`generate_image` tool: it asks for approval first, with a preview showing the
|
|
674
|
+
provider, model, size, and prompt. Responses are accepted as
|
|
675
|
+
`data[0].b64_json` or `data[0].url` (URL downloads are capped at 20 MB and
|
|
676
|
+
honor offline mode and the local-address guard). OpenAI-compatible providers
|
|
677
|
+
are called at `/images/generations`; OpenRouter at `/images`.
|
|
678
|
+
|
|
679
|
+
Video uses the same switch and provider but its own model, which you choose
|
|
680
|
+
yourself (there is no default: ids and prices change quickly and a clip is billed
|
|
681
|
+
per second):
|
|
682
|
+
|
|
683
|
+
```text
|
|
684
|
+
/media provider openrouter
|
|
685
|
+
/video model list # pick a video model (or: /video model <id>)
|
|
686
|
+
/config media duration 5 # seconds
|
|
687
|
+
/config media video-size 720p # or 1280x720; "default" clears it
|
|
688
|
+
/video a paper boat drifting down a rainy street
|
|
689
|
+
/video --duration 8 --size 1080p --image start.png the boat starts to sail
|
|
690
|
+
```
|
|
691
|
+
|
|
692
|
+
`/video [--duration <s>] [--size <WxH|720p>] [--model <id>] [--image <path>]
|
|
693
|
+
<prompt>` submits an asynchronous job, shows live status while it renders
|
|
694
|
+
(usually a few minutes), and streams the finished file to
|
|
695
|
+
`.kiwimatecoder/media/` with a 500 MB cap. `--image` animates a workspace image
|
|
696
|
+
as the first frame (OpenRouter models). Press Ctrl+C to stop waiting: the job
|
|
697
|
+
keeps running (and billing) on the provider, and `/video resume <job-id>` fetches
|
|
698
|
+
it later without paying twice. Polling is bounded to 15 minutes and tolerates
|
|
699
|
+
brief network errors; the API key is only ever sent to the provider's own host,
|
|
700
|
+
never to a download CDN. The model can call the approval-gated `generate_video`
|
|
701
|
+
tool (its preview states the per-second billing); after a timeout it resumes with
|
|
702
|
+
`resume_job_id` rather than regenerating.
|
|
703
|
+
|
|
704
|
+
Two wire formats are spoken, chosen from the provider's host: OpenRouter
|
|
705
|
+
(`duration`, `resolution`/`size`, `frame_images`, `unsigned_urls`) and the OpenAI
|
|
706
|
+
Videos API (`seconds`, `size`, multipart form, `/videos/<id>/content`). The OpenAI
|
|
707
|
+
format is covered by mocked-transport tests only; please report anything a live
|
|
708
|
+
endpoint rejects.
|
|
709
|
+
|
|
710
|
+
`/media` shows whether image and video generation are ready (and what is missing:
|
|
711
|
+
disabled, offline, no API key, no model chosen) and lists the most recent files;
|
|
712
|
+
reference an image from the list with `@<path>` to attach it again. Provider auth,
|
|
713
|
+
API versioning (Azure-style `?api-version=`), proxy, and custom CA settings all
|
|
714
|
+
come from the normal config. Configure it from the shell with
|
|
715
|
+
`config media show|enable on|off|model <id|none> [--provider <id>]|provider <id>|size <WxH>|video-model
|
|
716
|
+
<id|none> [--provider <id>]|duration <seconds>|video-size <size>|output-dir <path>`
|
|
717
|
+
(inside the REPL, `/config media model <id|none> [provider]` and `/config media
|
|
718
|
+
video-model <id|none> [provider]` take the provider as an optional trailing word;
|
|
719
|
+
`none`, `clear`, `default` or `-` clears the model for that provider).
|
|
720
|
+
|
|
721
|
+
## Notebooks, PDFs, and docx
|
|
722
|
+
|
|
723
|
+
`read_file` extracts structured documents to text automatically, so the model
|
|
724
|
+
can read them without extra tooling:
|
|
725
|
+
|
|
726
|
+
- **Jupyter notebooks** (`.ipynb`) render as `## Cell N (type)` sections with
|
|
727
|
+
cell sources plus text and stream outputs; image outputs are summarized as
|
|
728
|
+
`[image/png output, N bytes]`.
|
|
729
|
+
- **Word documents** (`.docx`) are unzipped and `word/document.xml` is stripped
|
|
730
|
+
to text with paragraph and line breaks preserved.
|
|
731
|
+
- **PDFs** (`.pdf`) use the `pdftotext` CLI (from Poppler) when installed for
|
|
732
|
+
reliable extraction. When it is missing, a conservative stdlib fallback
|
|
733
|
+
inflates FlateDecode streams and reads text from `BT`/`ET` blocks; if nothing
|
|
734
|
+
is parseable the result explains how to install `pdftotext` instead of
|
|
735
|
+
failing.
|
|
736
|
+
|
|
737
|
+
Document output is capped at ~200 KB with a truncation note, and `offset`/
|
|
738
|
+
`limit` are ignored for documents (they apply to plain text files only).
|
|
739
|
+
Malformed documents always return a clear message rather than raising.
|
|
740
|
+
|
|
741
|
+
## Providers
|
|
742
|
+
|
|
743
|
+
KiwiMateCoder ships a built-in registry of providers. Switch live with `/provider`,
|
|
744
|
+
or set the persistent primary from the shell with `config provider use <id>`. An
|
|
745
|
+
API key can be saved interactively with `kiwimatecoder setup`, directly with
|
|
746
|
+
`config key set <provider> <key>`, or via the provider's environment variable.
|
|
747
|
+
You can also add OpenAI-compatible custom providers with `config provider add`.
|
|
748
|
+
|
|
749
|
+
| Provider id | Key env var | Notes |
|
|
750
|
+
|-------------|-------------|-------|
|
|
751
|
+
| `kiwimate` **(experimental)** | `KIWIMATE_API_KEY` | [kiwimate.net](https://kiwimate.net); keys start with `sk-km-`. Chat only — no tool use yet (see below). |
|
|
752
|
+
| `openai` | `OPENAI_API_KEY` | |
|
|
753
|
+
| `anthropic` | `ANTHROPIC_API_KEY` | Native Messages API. |
|
|
754
|
+
| `google` | `GEMINI_API_KEY` | |
|
|
755
|
+
| `xai` | `XAI_API_KEY` | |
|
|
756
|
+
| `mistral` | `MISTRAL_API_KEY` | |
|
|
757
|
+
| `deepseek` | `DEEPSEEK_API_KEY` | |
|
|
758
|
+
| `qwen` | `DASHSCOPE_API_KEY` | |
|
|
759
|
+
| `moonshot` | `MOONSHOT_API_KEY` | |
|
|
760
|
+
| `openrouter` | `OPENROUTER_API_KEY` | The provider used until you pick another. |
|
|
761
|
+
| `azure` | `AZURE_OPENAI_API_KEY` | Placeholder endpoint; the model is your deployment name. |
|
|
762
|
+
| `bedrock` | `AWS_BEARER_TOKEN_BEDROCK` | Placeholder endpoint. |
|
|
763
|
+
| `groq` | `GROQ_API_KEY` | |
|
|
764
|
+
| `together` | `TOGETHER_API_KEY` | |
|
|
765
|
+
| `fireworks` | `FIREWORKS_API_KEY` | |
|
|
766
|
+
| `cerebras` | `CEREBRAS_API_KEY` | |
|
|
767
|
+
| `deepinfra` | `DEEPINFRA_API_KEY` | |
|
|
768
|
+
| `ollama` | `OLLAMA_API_KEY` (optional) | Local. |
|
|
769
|
+
| `lmstudio` | `LMSTUDIO_API_KEY` (optional) | Local. |
|
|
770
|
+
| `unsloth` | `UNSLOTH_API_KEY` (required) | Local. |
|
|
771
|
+
|
|
772
|
+
### Choosing a model
|
|
773
|
+
|
|
774
|
+
There are no default models. You choose the model to use with each provider
|
|
775
|
+
when you add it, and the choice is remembered per provider:
|
|
776
|
+
|
|
777
|
+
- `kiwimatecoder setup` asks you to pick one from the provider's list after it
|
|
778
|
+
saves the key (or pass `--model <id>` to skip the picker).
|
|
779
|
+
- `/provider` asks for a model for each provider you add to the roster.
|
|
780
|
+
- Custom providers take the model as the fourth argument of
|
|
781
|
+
`config provider add <id> <name> <base_url> <model>`; change it with
|
|
782
|
+
`config provider edit <id> --model <id>` or `/config provider edit <id> model=<id>`.
|
|
783
|
+
- `config model set <id> [--provider <id>]` or `/config model set <model>
|
|
784
|
+
[provider]` changes the model for the active (or named) provider, and
|
|
785
|
+
`config model reset [--provider <id>]` / `/config model reset [provider]`
|
|
786
|
+
forgets it. `config provider list` shows each provider's chosen model.
|
|
787
|
+
|
|
788
|
+
The interactive REPL asks for a model at launch when the primary has none. A
|
|
789
|
+
fallback provider without a chosen model is skipped (with a note) during
|
|
790
|
+
failover. Headless runs never prompt: `kiwimatecoder -p`, `ask`, and `jobs run`
|
|
791
|
+
exit `1` with `No model chosen for <provider>…` when neither `--model` nor a
|
|
792
|
+
chosen model is available (`eval run` reports the same message as invalid
|
|
793
|
+
input, exit `2`). Local servers are the one exception — with nothing chosen,
|
|
794
|
+
the session uses the first model the running server lists.
|
|
795
|
+
|
|
796
|
+
Groq, Together, Fireworks, Cerebras, and DeepInfra work out of the box once
|
|
797
|
+
their API key is set — they speak the standard OpenAI-compatible protocol.
|
|
798
|
+
|
|
799
|
+
### KiwiMate (experimental)
|
|
800
|
+
|
|
801
|
+
`kiwimate` is KiwiMate's own OpenAI-compatible API from
|
|
802
|
+
[kiwimate.net](https://kiwimate.net). It is listed first in every provider
|
|
803
|
+
picker, in its own **Experimental** box, and marked `(experimental)` in
|
|
804
|
+
`config provider list`. Create a key at `kiwimate.net/developers/console` (it
|
|
805
|
+
starts with `sk-km-`), then run `kiwimatecoder setup --provider kiwimate` (or
|
|
806
|
+
set `KIWIMATE_API_KEY`, then `config provider use kiwimate` and `config model
|
|
807
|
+
set <id>`). Setup offers the endpoint's models, falling back to the suggested
|
|
808
|
+
`kiwimate-mini-1-0`, `kiwimate-small-1-0`, `kiwimate-medium-1-0`, and
|
|
809
|
+
`kiwimate-large-1-0`, and reminds you that the provider is experimental.
|
|
810
|
+
|
|
811
|
+
The endpoint is limited for now:
|
|
812
|
+
|
|
813
|
+
- **Chat only, no tool use yet.** KiwiMateCoder sends it no tool schemas, so
|
|
814
|
+
with KiwiMate as the provider the agent cannot read or edit files or run
|
|
815
|
+
commands. Tool calls and results already in the conversation are flattened
|
|
816
|
+
into plain text when you switch to it mid-session.
|
|
817
|
+
- **Replies are capped at about 1,024 tokens.** The REPL prints `The reply was
|
|
818
|
+
cut off at the provider's output limit.` when that happens.
|
|
819
|
+
- **System prompts are ignored by the endpoint**, so project instructions
|
|
820
|
+
(`AGENTS.md`), memory, output styles, and custom prompts do not reach the
|
|
821
|
+
model. Only the last 20 non-system messages of the conversation are
|
|
822
|
+
forwarded to it.
|
|
823
|
+
|
|
824
|
+
`azure` and `bedrock` ship **placeholder** endpoints because the endpoint is
|
|
825
|
+
account-specific (`https://<resource>.openai.azure.com/openai/v1` and
|
|
826
|
+
`https://bedrock-runtime.<region>.amazonaws.com/openai/v1`). Point them at your
|
|
827
|
+
own resource by adding a custom provider (built-in entries cannot be edited):
|
|
828
|
+
|
|
829
|
+
```bash
|
|
830
|
+
kiwimatecoder config provider add my-azure "My Azure" \
|
|
831
|
+
https://my-resource.openai.azure.com/openai/v1 my-deployment \
|
|
832
|
+
--key-env AZURE_OPENAI_API_KEY --key-header api-key --key-prefix "" \
|
|
833
|
+
--api-version 2024-10-21
|
|
834
|
+
kiwimatecoder config key set my-azure <key>
|
|
835
|
+
|
|
836
|
+
kiwimatecoder config provider add bedrock-eu "Bedrock (eu-central-1)" \
|
|
837
|
+
https://bedrock-runtime.eu-central-1.amazonaws.com/openai/v1 \
|
|
838
|
+
openai.gpt-5.6-sol --key-env AWS_BEARER_TOKEN_BEDROCK
|
|
839
|
+
```
|
|
840
|
+
|
|
841
|
+
Azure OpenAI authenticates with an `api-key` header (no `Bearer` prefix) and
|
|
842
|
+
versions its API with `?api-version=`; both are configurable per custom provider
|
|
843
|
+
(`--key-header`, `--key-prefix`, `--api-version`, or the slash equivalents).
|
|
844
|
+
AWS Bedrock's OpenAI-compatible endpoint accepts a bearer token only: SigV4/IAM
|
|
845
|
+
signing, Azure managed identity, Google Vertex AI (project-specific endpoint,
|
|
846
|
+
OAuth2-only auth), and interactive OAuth/device-code flows are not implemented
|
|
847
|
+
(deferred; see ROADMAP).
|
|
848
|
+
|
|
849
|
+
Each built-in provider still ships a short list of suggested model ids, used
|
|
850
|
+
only to fill the pickers when its live listing is unavailable — none of them is
|
|
851
|
+
used unless you choose it. The live catalog below is what `/model` actually
|
|
852
|
+
offers once the provider can be queried (see **Needs a key** below).
|
|
853
|
+
|
|
854
|
+
The `anthropic` provider talks to Anthropic's native Messages API, including
|
|
855
|
+
streaming tool calls and native model listing. Custom providers can opt into the
|
|
856
|
+
same path with `config provider edit <id> --compat anthropic` (or
|
|
857
|
+
`/config provider edit <id> compat=anthropic`); everything else speaks the
|
|
858
|
+
OpenAI-compatible chat+tools protocol.
|
|
859
|
+
|
|
860
|
+
### Local providers (Ollama, LM Studio & Unsloth)
|
|
861
|
+
|
|
862
|
+
The `ollama`, `lmstudio`, and `unsloth` providers talk to model servers on your
|
|
863
|
+
own machine. Make sure the server is running ([Ollama](https://ollama.com) on
|
|
864
|
+
`http://localhost:11434`, [LM Studio](https://lmstudio.ai)'s local server on
|
|
865
|
+
`http://localhost:1234`, or [Unsloth](https://unsloth.ai)'s Studio API on
|
|
866
|
+
`http://localhost:8888`), then:
|
|
867
|
+
|
|
868
|
+
```text
|
|
869
|
+
/provider ollama
|
|
870
|
+
```
|
|
871
|
+
|
|
872
|
+
That's it for Ollama and LM Studio — no API key needed. You can choose a model
|
|
873
|
+
like any other provider (`kiwimatecoder setup` offers the server's models when
|
|
874
|
+
it is running, and `/model` lists them); until you do, the session uses the
|
|
875
|
+
first model the server lists. `kiwimatecoder setup` detects which local servers
|
|
876
|
+
are running and marks them in the picker. Tool calling depends on the model you
|
|
877
|
+
pick, so choose a tool-capable family (Llama 3.1+, Qwen 3, DeepSeek, ...).
|
|
878
|
+
|
|
879
|
+
`unsloth` works the same way but **requires a key**: Unsloth enforces auth even
|
|
880
|
+
on localhost. Create one in Unsloth under Settings → API (it starts with
|
|
881
|
+
`sk-unsloth-`), run `kiwimatecoder setup --provider unsloth` to save it, and
|
|
882
|
+
load a GGUF model in Unsloth before chatting. Tip: start Unsloth's server with
|
|
883
|
+
`--disable-tools` when an external agent drives it — otherwise Unsloth's own
|
|
884
|
+
server-side tools swallow the agent's tool calls.
|
|
885
|
+
|
|
886
|
+
A key only matters if your server enforces auth (e.g. LM Studio's server token,
|
|
887
|
+
or Ollama behind an authenticating proxy) — set `OLLAMA_API_KEY` /
|
|
888
|
+
`LMSTUDIO_API_KEY` or `config key set ollama <key>` in that case. Running on a
|
|
889
|
+
different port or another machine? Add it as a custom provider instead, with
|
|
890
|
+
the model to use as the fourth argument:
|
|
891
|
+
`/config provider add mybox "My Box" http://mybox.local:11434/v1 llama3.1:8b` —
|
|
892
|
+
any `localhost`/`*.local` provider is treated as keyless automatically.
|
|
893
|
+
|
|
894
|
+
## Model catalogs
|
|
895
|
+
|
|
896
|
+
Model ids drift constantly, so the list `/model` offers is fetched from the
|
|
897
|
+
provider itself rather than being frozen into the release.
|
|
898
|
+
|
|
899
|
+
- **Newest first.** Opening `/model` (or running `/model refresh`) calls the
|
|
900
|
+
provider's `/models` endpoint and offers what it serves today, ordered by
|
|
901
|
+
release date, with your current model pinned first. Search
|
|
902
|
+
(`/model search <term>`) bypasses this newest-first cap and scans the whole
|
|
903
|
+
catalog by name.
|
|
904
|
+
- **Deprecated ids disappear.** Anything the provider no longer lists is dropped
|
|
905
|
+
from the catalog, and `/model refresh` prints what was removed. If your current
|
|
906
|
+
model is one of them, it says so.
|
|
907
|
+
- **Only usable models.** Embedding, image, audio, moderation, and non
|
|
908
|
+
tool-calling models are filtered out — the agent loop needs text chat plus tool
|
|
909
|
+
calls (chat-only providers such as KiwiMate keep models without tool support).
|
|
910
|
+
The newest 60 are offered; any other id still works if you type it.
|
|
911
|
+
- **Cached for a day.** Results are stored in `~/.kiwimatecoder/model_cache.json`
|
|
912
|
+
and reused for 24 hours, so the selector stays instant and tab completion never
|
|
913
|
+
touches the network. A failed fetch falls back to the cached list, then to the
|
|
914
|
+
built-in suggestions, and is not retried automatically for 30 minutes.
|
|
915
|
+
- **Needs a key.** A cloud provider is only queried once it has an API key
|
|
916
|
+
configured; keyless local servers (`ollama`, `lmstudio`, and any custom
|
|
917
|
+
provider on `localhost` or a `*.local` host) are queried without one —
|
|
918
|
+
`unsloth`, which enforces auth locally, is queried once its key is set.
|
|
919
|
+
|
|
920
|
+
From the shell, `kiwimatecoder config models show [--provider <id>]` and
|
|
921
|
+
`kiwimatecoder config models refresh [--provider <id>]` show or refresh the same
|
|
922
|
+
catalog.
|
|
923
|
+
|
|
924
|
+
The suggested model tuples in `kiwimatecoder/providers.py` are only the offline
|
|
925
|
+
fallback for the pickers (never a default), and custom providers can list
|
|
926
|
+
theirs via a `"models"` array in `~/.kiwimatecoder/config.json`. `/config models
|
|
927
|
+
allow|deny` reshapes what is offered on top of whichever catalog is in use, and
|
|
928
|
+
`/model <name>` or `config model set <name>` accepts any id, listed or not.
|
|
929
|
+
|
|
930
|
+
## One-shot mode
|
|
931
|
+
|
|
932
|
+
For a quick question without entering the REPL:
|
|
933
|
+
|
|
934
|
+
```bash
|
|
935
|
+
kiwimatecoder ask "how do I reverse a list in python?"
|
|
936
|
+
kiwimatecoder ask "review this file" --file app.py --provider openai --model gpt-5.6-sol
|
|
937
|
+
```
|
|
938
|
+
|
|
939
|
+
`ask` uses the model chosen for the provider unless `--model` is passed, and
|
|
940
|
+
exits `1` with `No model chosen for <provider>…` when there is neither.
|
|
941
|
+
|
|
942
|
+
## Headless mode
|
|
943
|
+
|
|
944
|
+
Run one agentic turn without entering the REPL — useful for scripts and CI:
|
|
945
|
+
|
|
946
|
+
```bash
|
|
947
|
+
kiwimatecoder -p "Summarize the changes in the working tree."
|
|
948
|
+
echo "Explain src/app.py" | kiwimatecoder -p -
|
|
949
|
+
kiwimatecoder -p "Summarize the changes." --provider openai --model gpt-5.6-sol
|
|
950
|
+
```
|
|
951
|
+
|
|
952
|
+
The prompt is the value of `-p/--print`; `-p -` reads it from stdin. The run
|
|
953
|
+
uses the model chosen for the provider (`kiwimatecoder setup` or `config model
|
|
954
|
+
set`); pass `--model` to override it, or when none is chosen — headless runs
|
|
955
|
+
never prompt for one. Flags:
|
|
956
|
+
|
|
957
|
+
| Flag | Meaning |
|
|
958
|
+
| --- | --- |
|
|
959
|
+
| `--output-format text\|json\|stream-json` | `text` streams assistant text to stdout (default); `json` prints one JSON object at the end; `stream-json` prints one compact JSON object per event, ending with a `result` line. |
|
|
960
|
+
| `--mode ask\|auto-accept\|plan` | Permission mode for this run (default: the configured mode). |
|
|
961
|
+
| `--yes` | Treat approvals as granted (auto-accept) — never prompts. |
|
|
962
|
+
| `--max-turns N` | Hard cap on tool-loop iterations (default 30). |
|
|
963
|
+
| `--provider`, `--model` | Provider/model overrides for this run. `--provider` makes that provider the primary, ahead of the configured roster; `--model` is required when no model is chosen for it. |
|
|
964
|
+
| `--workspace PATH` | Workspace root (default: current directory). |
|
|
965
|
+
| `--quiet` | Suppress tool/progress lines on stderr in text mode. |
|
|
966
|
+
|
|
967
|
+
Tool and progress lines go to **stderr**; only assistant text (text mode) or
|
|
968
|
+
JSON (json/stream-json modes) goes to **stdout**. Headless runs never prompt:
|
|
969
|
+
actions that would need approval are denied with a note on stderr unless
|
|
970
|
+
`--yes` or `--mode auto-accept` is used.
|
|
971
|
+
|
|
972
|
+
Exit codes: `0` success, `1` runtime failure (missing key or model — `No model
|
|
973
|
+
chosen for <provider>…` on stderr — provider error, turn cap without a final
|
|
974
|
+
answer), `2` invalid usage (bad format, mode, provider, or workspace).
|
|
975
|
+
|
|
976
|
+
CI example (a fresh runner has no saved config, so pass `--model`):
|
|
977
|
+
|
|
978
|
+
```yaml
|
|
979
|
+
- name: Review the diff
|
|
980
|
+
run: |
|
|
981
|
+
kiwimatecoder -p "Review the staged diff and list risks." \
|
|
982
|
+
--model anthropic/claude-sonnet-5 \
|
|
983
|
+
--output-format json --max-turns 10 > review.json
|
|
984
|
+
cat review.json
|
|
985
|
+
```
|
|
986
|
+
|
|
987
|
+
More recipes (ready-made GitHub Actions workflows, exit-code gating, and
|
|
988
|
+
pre-commit setup) live in [docs/ci.md](docs/ci.md).
|
|
989
|
+
|
|
990
|
+
## Shell completions and man page
|
|
991
|
+
|
|
992
|
+
Typer ships shell completion for bash, zsh, fish, and PowerShell:
|
|
993
|
+
|
|
994
|
+
```bash
|
|
995
|
+
kiwimatecoder --install-completion # detect and install for your shell
|
|
996
|
+
kiwimatecoder --show-completion bash # print the script to stdout instead
|
|
997
|
+
```
|
|
998
|
+
|
|
999
|
+
A troff man page is committed at `docs/kiwimatecoder.1`; view it with `man
|
|
1000
|
+
./docs/kiwimatecoder.1` (on Linux, `man -l docs/kiwimatecoder.1`). Regenerate it
|
|
1001
|
+
from the Typer command tree after changing the CLI:
|
|
1002
|
+
|
|
1003
|
+
```bash
|
|
1004
|
+
python scripts/generate_man.py # rewrite the man page
|
|
1005
|
+
python scripts/generate_man.py --check # fail when the committed file is stale
|
|
1006
|
+
```
|
|
1007
|
+
|
|
1008
|
+
Interactive sessions need a real terminal. When stdin is not a TTY (a pipe, a
|
|
1009
|
+
CI job, cron), the bare command — and `--resume`/`--continue` — exits with code
|
|
1010
|
+
`2` and a note pointing at headless mode instead of starting prompt_toolkit.
|
|
1011
|
+
Use `kiwimatecoder -p "..."` or `echo "..." | kiwimatecoder -p -`.
|
|
1012
|
+
|
|
1013
|
+
## Python SDK
|
|
1014
|
+
|
|
1015
|
+
Embed the agent in a Python program with `kiwimatecoder.sdk`:
|
|
1016
|
+
|
|
1017
|
+
```python
|
|
1018
|
+
from kiwimatecoder.sdk import run_agent_sync
|
|
1019
|
+
|
|
1020
|
+
result = run_agent_sync(
|
|
1021
|
+
"Summarize README.md in three bullets.",
|
|
1022
|
+
workspace=".",
|
|
1023
|
+
mode="plan",
|
|
1024
|
+
model="anthropic/claude-sonnet-5", # omit to use the provider's chosen model
|
|
1025
|
+
)
|
|
1026
|
+
|
|
1027
|
+
if result.success:
|
|
1028
|
+
print(result.text)
|
|
1029
|
+
print(result.usage, result.cost_usd) # tokens and estimated USD (or None)
|
|
1030
|
+
```
|
|
1031
|
+
|
|
1032
|
+
Without `model=`, the run uses the model chosen for the provider. When there
|
|
1033
|
+
is none, `run_agent`/`run_agent_sync` raise
|
|
1034
|
+
`kiwimatecoder.config.ModelNotChosenError` (a `ValueError`) before contacting
|
|
1035
|
+
the provider.
|
|
1036
|
+
|
|
1037
|
+
`RunResult` carries `text`, `usage` (`prompt_tokens`/`completion_tokens`),
|
|
1038
|
+
`cost_usd`, `provider`, `model`, `mode`, `tools_used`, `messages`, `success`,
|
|
1039
|
+
and `error`. Pass `on_event` to observe the same events as stream-JSON
|
|
1040
|
+
(`text_delta`, `tool_start`, `tool_end`, `usage`, `done`), `confirm` to
|
|
1041
|
+
approve actions, and `console` to receive the agent's tool/progress output.
|
|
1042
|
+
Approvals are denied by default. From async code use `await run_agent(...)`;
|
|
1043
|
+
`run_agent_sync` raises a clear error if called inside a running loop.
|
|
1044
|
+
|
|
1045
|
+
## Editor integration (ACP)
|
|
1046
|
+
|
|
1047
|
+
KiwiMateCoder can run as an [Agent Client Protocol](https://agentclientprotocol.com)
|
|
1048
|
+
(ACP) agent over stdio, so an ACP-capable editor can drive it:
|
|
1049
|
+
|
|
1050
|
+
```bash
|
|
1051
|
+
kiwimatecoder acp [--workspace PATH]
|
|
1052
|
+
```
|
|
1053
|
+
|
|
1054
|
+
A Zed-style agent configuration (`settings.json`) looks like:
|
|
1055
|
+
|
|
1056
|
+
```json
|
|
1057
|
+
{
|
|
1058
|
+
"agent": {
|
|
1059
|
+
"command": "kiwimatecoder",
|
|
1060
|
+
"args": ["acp"]
|
|
1061
|
+
}
|
|
1062
|
+
}
|
|
1063
|
+
```
|
|
1064
|
+
|
|
1065
|
+
The server speaks JSON-RPC 2.0 over newline-delimited JSON on stdin/stdout;
|
|
1066
|
+
the only thing ever written to stdout is protocol traffic. Implemented subset:
|
|
1067
|
+
|
|
1068
|
+
- `initialize` handshake with agent capabilities and version info.
|
|
1069
|
+
- `session/new` creates one conversation rooted at the client's `cwd`,
|
|
1070
|
+
using the **configured** permission mode (never an assumed auto-accept).
|
|
1071
|
+
- `session/prompt` runs one agent turn, streaming assistant text chunks and
|
|
1072
|
+
tool-call progress as `session/update` notifications; the response carries
|
|
1073
|
+
`end_turn`, `cancelled`, `refusal`, or `max_tokens`.
|
|
1074
|
+
- `session/cancel` cancels the running turn; partial assistant text is kept.
|
|
1075
|
+
- `session/request_permission` bridges every write/command approval to the
|
|
1076
|
+
editor when the session runs in `ask` mode. Approving with "always"
|
|
1077
|
+
persists the tool allowlist; a cancelled or unanswered request (default
|
|
1078
|
+
timeout 300s, `config acp timeout <s>`) is denied exactly like a normal
|
|
1079
|
+
denial.
|
|
1080
|
+
|
|
1081
|
+
This is a focused subset: terminal and MCP client capabilities advertised by
|
|
1082
|
+
the editor are not wired through (MCP servers still come from KiwiMateCoder
|
|
1083
|
+
config), `loadSession` is not supported, image prompt parts are ignored with a
|
|
1084
|
+
note to the model, and the file tools operate on the local filesystem. When
|
|
1085
|
+
the client advertises `fs.readTextFile`/`fs.writeTextFile`, the server exposes
|
|
1086
|
+
`read_text_file`/`write_text_file` helpers that delegate to
|
|
1087
|
+
`fs/read_text_file`/`fs/write_text_file`; otherwise those helpers use the
|
|
1088
|
+
local filesystem.
|
|
1089
|
+
|
|
1090
|
+
## Background jobs
|
|
1091
|
+
|
|
1092
|
+
Run an agent task detached from your terminal, then check on it later:
|
|
1093
|
+
|
|
1094
|
+
```bash
|
|
1095
|
+
kiwimatecoder jobs run "Add type hints to kiwimatecoder/jobs.py and run mypy."
|
|
1096
|
+
kiwimatecoder jobs run "Fix the failing test." --provider openai --model gpt-5.6-sol
|
|
1097
|
+
kiwimatecoder jobs list
|
|
1098
|
+
kiwimatecoder jobs show <id>
|
|
1099
|
+
kiwimatecoder jobs output <id>
|
|
1100
|
+
kiwimatecoder jobs cancel <id>
|
|
1101
|
+
kiwimatecoder jobs clear # finished jobs only; --all includes running
|
|
1102
|
+
```
|
|
1103
|
+
|
|
1104
|
+
Each job is one headless run (`python -m kiwimatecoder -p ... --output-format
|
|
1105
|
+
json`) recorded as JSON under `~/.kiwimatecoder/jobs/<id>.json` with its combined
|
|
1106
|
+
output at `~/.kiwimatecoder/jobs/<id>.log`. Records survive restarts; `jobs list`
|
|
1107
|
+
refreshes running jobs from their process and parsed result, and corruption in
|
|
1108
|
+
one record never hides the others. A job uses the model chosen for its provider
|
|
1109
|
+
unless `--model` is passed; `jobs run` and `jobs schedule` check this before
|
|
1110
|
+
starting anything and exit `1` with `No model chosen for <provider>…` when
|
|
1111
|
+
there is neither.
|
|
1112
|
+
|
|
1113
|
+
> **Warning:** `jobs run` defaults to `--mode auto-accept`, so an unattended job
|
|
1114
|
+
> can edit files and run commands without asking. Pass `--mode ask` (approvals
|
|
1115
|
+
> are then denied, since nothing can prompt) or `--mode plan` (read-only) to
|
|
1116
|
+
> constrain a job, and only point jobs at workspaces you trust.
|
|
1117
|
+
|
|
1118
|
+
Inside a session, `/jobs [list|show <id>|cancel <id>|tick]` does the same, and
|
|
1119
|
+
`/jobs run <prompt>` starts a job in the session's workspace (still
|
|
1120
|
+
`auto-accept`). Jobs are marked `running`, `succeeded`, `failed`, or
|
|
1121
|
+
`cancelled`; `cancelled` covers an explicit `jobs cancel`.
|
|
1122
|
+
|
|
1123
|
+
### Scheduling
|
|
1124
|
+
|
|
1125
|
+
Scheduling is pull-based — there is no daemon and no platform cron integration.
|
|
1126
|
+
`jobs schedule "<prompt>" --every <seconds>` starts a run immediately and stores
|
|
1127
|
+
the interval plus a `next_run_at` timestamp; every later invocation of
|
|
1128
|
+
`kiwimatecoder jobs tick` (or `/jobs tick`) starts any run that is due. A job
|
|
1129
|
+
that is still running is skipped, so runs never overlap. A due job that cannot
|
|
1130
|
+
start (its workspace is gone, its provider was removed, or no model is chosen)
|
|
1131
|
+
is left in place and reported as `Skipped <id>: <reason>`; `jobs tick` then
|
|
1132
|
+
exits `1`. Wire `jobs tick` to your own scheduler, for example:
|
|
1133
|
+
|
|
1134
|
+
```cron
|
|
1135
|
+
*/5 * * * * kiwimatecoder jobs tick
|
|
1136
|
+
```
|
|
1137
|
+
|
|
1138
|
+
## Update
|
|
1139
|
+
|
|
1140
|
+
Update the CLI from the same Python environment:
|
|
1141
|
+
|
|
1142
|
+
```bash
|
|
1143
|
+
kiwimatecoder update
|
|
1144
|
+
```
|
|
1145
|
+
|
|
1146
|
+
or with a flag:
|
|
1147
|
+
|
|
1148
|
+
```bash
|
|
1149
|
+
kiwimatecoder --update
|
|
1150
|
+
```
|
|
1151
|
+
|
|
1152
|
+
(The older `-update` form still works but is deprecated.) Check the installed
|
|
1153
|
+
version before/after with:
|
|
1154
|
+
|
|
1155
|
+
```bash
|
|
1156
|
+
kiwimatecoder --version
|
|
1157
|
+
```
|
|
1158
|
+
|
|
1159
|
+
When KiwiMateCoder is running from a Git checkout, the updater first fetches
|
|
1160
|
+
`origin` and compares the local `HEAD` to `origin/<branch>`:
|
|
1161
|
+
|
|
1162
|
+
- **Already up to date** — prints `Already on the latest version (commit <sha>).`
|
|
1163
|
+
and exits without pulling or reinstalling.
|
|
1164
|
+
- **Behind** — prints `Updating from <old-sha> (N commit(s) behind origin/<branch>)…`,
|
|
1165
|
+
runs `git pull --ff-only`, reinstalls the checkout with
|
|
1166
|
+
`pip install --upgrade -e <path>`, and reports `Updated <old-sha> → <new-sha>.`
|
|
1167
|
+
|
|
1168
|
+
KiwiMateCoder is not published to PyPI, so for packaged (non-Git) installs the
|
|
1169
|
+
fallback runs
|
|
1170
|
+
`pip install --upgrade --force-reinstall git+https://github.com/Kyle8933/kiwimatecoder.git`.
|
|
1171
|
+
|
|
1172
|
+
### Updating and pinning versions
|
|
1173
|
+
|
|
1174
|
+
Pin a branch, tag, or commit with `--ref`:
|
|
1175
|
+
|
|
1176
|
+
```bash
|
|
1177
|
+
kiwimatecoder update --ref v0.1.0 # tag
|
|
1178
|
+
kiwimatecoder update --ref main # branch
|
|
1179
|
+
kiwimatecoder update --ref 1a2b3c4 # commit
|
|
1180
|
+
```
|
|
1181
|
+
|
|
1182
|
+
In a Git checkout the updater fetches `origin` and then puts the checkout on
|
|
1183
|
+
the ref: the current branch is fast-forwarded with `git pull --ff-only` (local
|
|
1184
|
+
commits are never merged unexpectedly), while every other ref is a plain
|
|
1185
|
+
`git checkout` followed by `pip install --upgrade -e <path>`. The command
|
|
1186
|
+
prints the old and new commit SHAs. For packaged installs it reinstalls
|
|
1187
|
+
`git+https://github.com/Kyle8933/kiwimatecoder.git@<ref>`.
|
|
1188
|
+
|
|
1189
|
+
To roll back, pin an older tag or commit the same way; `kiwimatecoder --version`
|
|
1190
|
+
shows the installed version. Generate a software bill of materials for the
|
|
1191
|
+
installed environment with:
|
|
1192
|
+
|
|
1193
|
+
```bash
|
|
1194
|
+
python scripts/generate_sbom.py --output sbom.json
|
|
1195
|
+
```
|
|
1196
|
+
|
|
1197
|
+
It is stdlib-only, emits CycloneDX-shaped JSON with the package and direct
|
|
1198
|
+
dependency versions, and is uploaded as a CI artifact by the `sbom` job.
|
|
1199
|
+
|
|
1200
|
+
|
|
1201
|
+
## Project instructions
|
|
1202
|
+
|
|
1203
|
+
Drop an `AGENTS.md` (or `CLAUDE.md`, `.kiwimatecoder/AGENTS.md`,
|
|
1204
|
+
`.kiwimatecoder/instructions.md`) at the workspace root and its contents are
|
|
1205
|
+
loaded into the system prompt on every turn — build commands, style rules,
|
|
1206
|
+
testing conventions. Files are capped at 32KB each and 48KB total.
|
|
1207
|
+
|
|
1208
|
+
## Memory
|
|
1209
|
+
|
|
1210
|
+
The agent can remember durable facts about you and your projects across
|
|
1211
|
+
sessions. Memory is plain Markdown, one `- fact` bullet per line, in two
|
|
1212
|
+
scopes:
|
|
1213
|
+
|
|
1214
|
+
- **Project** — `<workspace>/.kiwimatecoder/memory.md`; travels with the
|
|
1215
|
+
repository and applies only there.
|
|
1216
|
+
- **User** — `~/.kiwimatecoder/memory.md`; shared across every workspace.
|
|
1217
|
+
|
|
1218
|
+
The model writes with the approval-gated `remember` tool (`scope=project` or
|
|
1219
|
+
`scope=user`) and reads with the read-only `recall` tool. Active facts are
|
|
1220
|
+
loaded into the system prompt on every turn, capped at 16KB by default so a
|
|
1221
|
+
pathological file cannot crowd out the conversation.
|
|
1222
|
+
|
|
1223
|
+
Manage memory directly with `/memory`:
|
|
1224
|
+
|
|
1225
|
+
```text
|
|
1226
|
+
/memory # show both files and their facts
|
|
1227
|
+
/memory add The build uses uv, not pip
|
|
1228
|
+
/memory add-user I prefer concise answers
|
|
1229
|
+
/memory clear project
|
|
1230
|
+
/memory clear user
|
|
1231
|
+
```
|
|
1232
|
+
|
|
1233
|
+
Settings live under `kiwimatecoder config memory show|max-bytes <n>|enable on|off`.
|
|
1234
|
+
Never store secrets or API keys in memory — the prompt section says so
|
|
1235
|
+
explicitly, and the `remember` preview runs the same secret redaction as audit
|
|
1236
|
+
output.
|
|
1237
|
+
|
|
1238
|
+
## Custom commands and prompt templates
|
|
1239
|
+
|
|
1240
|
+
Drop a Markdown file in `<workspace>/.kiwimatecoder/commands/` (or
|
|
1241
|
+
`~/.kiwimatecoder/commands/`) and its filename becomes a slash command. The
|
|
1242
|
+
body is the prompt sent as a normal user turn; `$ARGUMENTS` is replaced with
|
|
1243
|
+
whatever you type after the command, and the arguments are appended when the
|
|
1244
|
+
token is absent. Workspace templates win over user templates with the same
|
|
1245
|
+
name, and built-in commands always win over templates. `/templates` lists what
|
|
1246
|
+
was discovered; `/help` adds a Custom commands group.
|
|
1247
|
+
|
|
1248
|
+
```text
|
|
1249
|
+
# .kiwimatecoder/commands/review.md
|
|
1250
|
+
# Review the current diff
|
|
1251
|
+
Review $ARGUMENTS for bugs, security issues, and missing tests.
|
|
1252
|
+
|
|
1253
|
+
/review src/app.py
|
|
1254
|
+
```
|
|
1255
|
+
|
|
1256
|
+
## Agent Skills
|
|
1257
|
+
|
|
1258
|
+
Skills are Markdown instruction bundles the model loads only when a task
|
|
1259
|
+
matches, so they cost no tokens on turns that do not use them. Each skill is a
|
|
1260
|
+
directory containing `SKILL.md`:
|
|
1261
|
+
|
|
1262
|
+
```text
|
|
1263
|
+
<workspace>/.kiwimatecoder/skills/pdf/SKILL.md # project skill
|
|
1264
|
+
~/.kiwimatecoder/skills/pdf/SKILL.md # personal skill
|
|
1265
|
+
```
|
|
1266
|
+
|
|
1267
|
+
The system prompt lists each skill's name and first line only; the model calls
|
|
1268
|
+
the read-only `load_skill` tool to pull the full body (capped at 32KB).
|
|
1269
|
+
Workspace skills shadow user skills with the same name.
|
|
1270
|
+
|
|
1271
|
+
## Plugins
|
|
1272
|
+
|
|
1273
|
+
Plugins are Python files with a `register(api)` entry point that can add tools,
|
|
1274
|
+
slash commands, and event subscribers without forking the CLI:
|
|
1275
|
+
|
|
1276
|
+
```python
|
|
1277
|
+
from kiwimatecoder.tools.base import FunctionTool, ToolResult
|
|
1278
|
+
|
|
1279
|
+
def register(api):
|
|
1280
|
+
api.register_tool(FunctionTool(
|
|
1281
|
+
name="word_count",
|
|
1282
|
+
description="Count words in a file.",
|
|
1283
|
+
parameters={
|
|
1284
|
+
"type": "object",
|
|
1285
|
+
"properties": {"path": {"type": "string"}},
|
|
1286
|
+
"required": ["path"],
|
|
1287
|
+
},
|
|
1288
|
+
func=lambda args, session: ToolResult(content="..."),
|
|
1289
|
+
))
|
|
1290
|
+
api.register_command("hello", lambda arg, session, console: "continue")
|
|
1291
|
+
api.subscribe("post_tool", lambda event: None)
|
|
1292
|
+
```
|
|
1293
|
+
|
|
1294
|
+
User plugins load from `~/.kiwimatecoder/plugins/*.py`. Project plugins in
|
|
1295
|
+
`<workspace>/.kiwimatecoder/plugins/*.py` are **disabled by default** — cloning
|
|
1296
|
+
a repository must never execute code just because the CLI started in it. Opt in
|
|
1297
|
+
with `"plugins": {"allow_project": true}` in `~/.kiwimatecoder/config.json`, and
|
|
1298
|
+
skip individual plugins with `"plugins": {"disabled": ["name"]}`. A plugin that
|
|
1299
|
+
fails to import or register is reported as a dim warning and skipped; it never
|
|
1300
|
+
prevents startup.
|
|
1301
|
+
|
|
1302
|
+
## MCP servers
|
|
1303
|
+
|
|
1304
|
+
MCP (Model Context Protocol) servers extend the agent with tools it discovers
|
|
1305
|
+
at session start. Configure them under `mcp_servers` in
|
|
1306
|
+
`~/.kiwimatecoder/config.json` — each entry is either a stdio subprocess or an
|
|
1307
|
+
HTTP endpoint:
|
|
1308
|
+
|
|
1309
|
+
```json
|
|
1310
|
+
{
|
|
1311
|
+
"mcp_servers": {
|
|
1312
|
+
"files": {
|
|
1313
|
+
"command": "npx",
|
|
1314
|
+
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"],
|
|
1315
|
+
"env": {"SOME_TOKEN": "..."},
|
|
1316
|
+
"disabled": false
|
|
1317
|
+
},
|
|
1318
|
+
"remote": {
|
|
1319
|
+
"url": "https://mcp.example.com/mcp",
|
|
1320
|
+
"headers": {"Authorization": "Bearer sk-..."},
|
|
1321
|
+
"disabled": false
|
|
1322
|
+
}
|
|
1323
|
+
}
|
|
1324
|
+
}
|
|
1325
|
+
```
|
|
1326
|
+
|
|
1327
|
+
From the shell, `kiwimatecoder config mcp add <name>` writes the same entries
|
|
1328
|
+
(set exactly one of `--command` or `--url`):
|
|
1329
|
+
|
|
1330
|
+
```bash
|
|
1331
|
+
kiwimatecoder config mcp add files --command npx --args "-y @modelcontextprotocol/server-filesystem /tmp"
|
|
1332
|
+
kiwimatecoder config mcp add remote --url https://mcp.example.com/mcp -H "Authorization: Bearer sk-..."
|
|
1333
|
+
kiwimatecoder config mcp list
|
|
1334
|
+
kiwimatecoder config mcp remove remote
|
|
1335
|
+
```
|
|
1336
|
+
|
|
1337
|
+
In the REPL, `/mcp list` shows every configured server, its status (connected,
|
|
1338
|
+
disabled, or the failure reason), its resources count, and the registered tools.
|
|
1339
|
+
`/mcp reload` reconnects each enabled server and re-registers its tools without
|
|
1340
|
+
restarting the session.
|
|
1341
|
+
|
|
1342
|
+
Each server tool is registered as `mcp__<server>__<tool>` (both parts sanitized
|
|
1343
|
+
to `[A-Za-z0-9_]`), with the server's JSON Schema used for arguments. Tools that
|
|
1344
|
+
declare `annotations.readOnlyHint` run without approval; every other MCP tool
|
|
1345
|
+
prompts for approval in `ask` mode, exactly like `write_file` or `run_bash`.
|
|
1346
|
+
A server that fails to start or initialize is reported as a dim warning and
|
|
1347
|
+
skipped — it never blocks startup. Connections close when the session exits.
|
|
1348
|
+
|
|
1349
|
+
Authentication is whatever headers (HTTP) or environment variables (stdio) you
|
|
1350
|
+
configure. Interactive OAuth is not implemented yet; see ROADMAP.md.
|
|
1351
|
+
|
|
1352
|
+
## Language server diagnostics
|
|
1353
|
+
|
|
1354
|
+
When enabled, KiwiMateCoder can talk to language servers for compiler-grade
|
|
1355
|
+
diagnostics and navigation. It is **opt-in** and off by default; no server
|
|
1356
|
+
process starts until the feature is enabled and a matching file is queried.
|
|
1357
|
+
|
|
1358
|
+
- `lsp_diagnostics` — errors and warnings for one file, or for the five most
|
|
1359
|
+
recently touched files when no path is given.
|
|
1360
|
+
- `lsp_definition` / `lsp_references` — where a symbol is defined, and every
|
|
1361
|
+
place it is used. Positions are 1-based line and column numbers.
|
|
1362
|
+
|
|
1363
|
+
Built-in presets start automatically when their command is on `PATH`:
|
|
1364
|
+
|
|
1365
|
+
| Language | Command | Extensions |
|
|
1366
|
+
|----------|---------|------------|
|
|
1367
|
+
| python | `pyright-langserver --stdio` | `.py`, `.pyi` |
|
|
1368
|
+
| typescript | `typescript-language-server --stdio` | `.ts`, `.tsx`, `.js`, `.jsx` |
|
|
1369
|
+
| go | `gopls` | `.go` |
|
|
1370
|
+
| rust | `rust-analyzer` | `.rs` |
|
|
1371
|
+
| c/cpp | `clangd` | `.c`, `.h`, `.cpp`, `.hpp` |
|
|
1372
|
+
|
|
1373
|
+
After a successful `write_file`/`edit_file`, diagnostics for the edited file
|
|
1374
|
+
are appended to the tool result as `LSP:` lines (capped at ten) when
|
|
1375
|
+
`diagnostics_after_edits` is on. A timeout or missing server appends nothing,
|
|
1376
|
+
so LSP can never fail a turn or delay it beyond the configured timeout.
|
|
1377
|
+
|
|
1378
|
+
Enable it in-session with `/lsp on`, or from the shell:
|
|
1379
|
+
|
|
1380
|
+
```bash
|
|
1381
|
+
kiwimatecoder config lsp enable on # on | off
|
|
1382
|
+
kiwimatecoder config lsp after-edits on # on | off
|
|
1383
|
+
kiwimatecoder config lsp show
|
|
1384
|
+
```
|
|
1385
|
+
|
|
1386
|
+
Use `/lsp status` to see whether LSP is on, which server commands are
|
|
1387
|
+
installed, and which clients are running; `/lsp restart` stops running servers
|
|
1388
|
+
so they start fresh on next use. Settings live under `lsp` in
|
|
1389
|
+
`~/.kiwimatecoder/config.json`; add your own server or override a preset:
|
|
1390
|
+
|
|
1391
|
+
```json
|
|
1392
|
+
{
|
|
1393
|
+
"lsp": {
|
|
1394
|
+
"enabled": true,
|
|
1395
|
+
"timeout": 10.0,
|
|
1396
|
+
"diagnostics_after_edits": true,
|
|
1397
|
+
"servers": {
|
|
1398
|
+
"python": {
|
|
1399
|
+
"command": "basedpyright-langserver",
|
|
1400
|
+
"args": ["--stdio"],
|
|
1401
|
+
"extensions": [".py", ".pyi"]
|
|
1402
|
+
}
|
|
1403
|
+
}
|
|
1404
|
+
}
|
|
1405
|
+
}
|
|
1406
|
+
```
|
|
1407
|
+
|
|
1408
|
+
## Codebase index and semantic search
|
|
1409
|
+
|
|
1410
|
+
`search` gains a third mode: `mode='semantic'` ranks files against a
|
|
1411
|
+
natural-language query using a local, persistent index instead of a regex, and
|
|
1412
|
+
returns paths, line numbers, and source snippets. The agent chooses it for
|
|
1413
|
+
questions like "where is authentication handled?", and grep/glob keep working
|
|
1414
|
+
exactly as before.
|
|
1415
|
+
|
|
1416
|
+
The index is built automatically the first time semantic search runs, then
|
|
1417
|
+
refreshed incrementally: only files whose size or modification time changed
|
|
1418
|
+
are re-tokenized, deleted files are dropped, and `.gitignore` plus the default
|
|
1419
|
+
skip directories (`node_modules`, `venv`, `__pycache__`, …) are respected.
|
|
1420
|
+
Binary files, files larger than the byte cap, and anything beyond the file cap
|
|
1421
|
+
are skipped. It is a cache: the store lives at
|
|
1422
|
+
`~/.kiwimatecoder/index/<hash-of-workspace>.json` and `clear` simply deletes it.
|
|
1423
|
+
|
|
1424
|
+
```text
|
|
1425
|
+
/index # status: files, terms, store size, stale count, embeddings
|
|
1426
|
+
/index build # refresh incrementally; prints added/updated/removed
|
|
1427
|
+
/index clear # delete the store for this workspace
|
|
1428
|
+
```
|
|
1429
|
+
|
|
1430
|
+
Ranking uses BM25 over file term frequencies, so there are no API calls and
|
|
1431
|
+
semantic search works out of the box. Settings live under the `index` key:
|
|
1432
|
+
|
|
1433
|
+
```json
|
|
1434
|
+
{
|
|
1435
|
+
"index": {
|
|
1436
|
+
"enabled": true,
|
|
1437
|
+
"max_files": 5000,
|
|
1438
|
+
"max_file_bytes": 262144,
|
|
1439
|
+
"embeddings": { "provider": "", "model": "", "batch_size": 32 }
|
|
1440
|
+
}
|
|
1441
|
+
}
|
|
1442
|
+
```
|
|
1443
|
+
|
|
1444
|
+
Embeddings are optional and **OpenAI-compatible only**: set a provider id and
|
|
1445
|
+
an embedding model (the provider must serve `POST /embeddings` and its API key
|
|
1446
|
+
is read from the same config/env as chat) to additionally store chunk vectors.
|
|
1447
|
+
When vectors exist, search blends the lexical and vector scores; if the
|
|
1448
|
+
embedding provider is unavailable or errors for any reason, search silently
|
|
1449
|
+
falls back to lexical ranking. Embeddings are never required to use the
|
|
1450
|
+
feature.
|
|
1451
|
+
|
|
1452
|
+
```bash
|
|
1453
|
+
kiwimatecoder config index show
|
|
1454
|
+
kiwimatecoder config index embed-provider openai
|
|
1455
|
+
kiwimatecoder config index embed-model text-embedding-3-small
|
|
1456
|
+
kiwimatecoder config index embed-provider none # turn embeddings off
|
|
1457
|
+
kiwimatecoder config index clear
|
|
1458
|
+
```
|
|
1459
|
+
|
|
1460
|
+
## Subagents
|
|
1461
|
+
|
|
1462
|
+
The `task` tool delegates a focused, self-contained investigation to a
|
|
1463
|
+
subagent that runs in its own context with the same workspace, provider, and
|
|
1464
|
+
tools. The subagent's intermediate tool output stays out of the parent
|
|
1465
|
+
conversation; it returns a final report (plus a step/token count) as the tool
|
|
1466
|
+
result. Use it for broad searches or self-contained questions that would
|
|
1467
|
+
otherwise flood the main context.
|
|
1468
|
+
|
|
1469
|
+
- Spawning a subagent is approval-gated like a command because the subagent can
|
|
1470
|
+
write files and run commands. Its own actions still go through the normal
|
|
1471
|
+
permission gate (including plan mode and command rules), and its edits are
|
|
1472
|
+
checkpointed so `/undo` covers them.
|
|
1473
|
+
- Subagents cannot spawn nested subagents and cannot use `ask_user`; put every
|
|
1474
|
+
decision they need in the prompt.
|
|
1475
|
+
- A subagent shares the parent's remaining token budget and stops at the
|
|
1476
|
+
configured step limit, returning a partial report with a note when either cap
|
|
1477
|
+
is hit. While subagents are disabled, `task` is not advertised at all.
|
|
1478
|
+
|
|
1479
|
+
```json
|
|
1480
|
+
{
|
|
1481
|
+
"subagents": {
|
|
1482
|
+
"enabled": true,
|
|
1483
|
+
"max_steps": 20,
|
|
1484
|
+
"model": ""
|
|
1485
|
+
}
|
|
1486
|
+
}
|
|
1487
|
+
```
|
|
1488
|
+
|
|
1489
|
+
```bash
|
|
1490
|
+
kiwimatecoder config subagents show
|
|
1491
|
+
kiwimatecoder config subagents enable on
|
|
1492
|
+
kiwimatecoder config subagents max-steps 10
|
|
1493
|
+
kiwimatecoder config subagents model gpt-5-mini
|
|
1494
|
+
```
|
|
1495
|
+
|
|
1496
|
+
Or in the REPL: `/config subagents [show|enable on|off|max-steps <n>]`.
|
|
1497
|
+
|
|
1498
|
+
## Sampling and output styles
|
|
1499
|
+
|
|
1500
|
+
Sampling parameters apply to every provider and are sent when set:
|
|
1501
|
+
|
|
1502
|
+
```bash
|
|
1503
|
+
kiwimatecoder config sampling set temperature=0.2 top_p=0.9 max_tokens=4096 reasoning_effort=medium
|
|
1504
|
+
kiwimatecoder config sampling show
|
|
1505
|
+
kiwimatecoder config sampling reset
|
|
1506
|
+
```
|
|
1507
|
+
|
|
1508
|
+
Output styles shape the agent's replies: `default`, `concise`, `explanatory`,
|
|
1509
|
+
or `code`. Set one with `config style set <name>` (or `/config style set`). For
|
|
1510
|
+
a fully custom instruction, add a system-prompt suffix with
|
|
1511
|
+
`config prompt set "<text>"` and remove it with `config prompt clear`.
|
|
1512
|
+
|
|
1513
|
+
## Themes, output modes, and accessibility
|
|
1514
|
+
|
|
1515
|
+
Control color independently of your terminal, pick a theme, tune how much the
|
|
1516
|
+
agent prints, and switch to ASCII glyphs for screen readers and limited
|
|
1517
|
+
terminals:
|
|
1518
|
+
|
|
1519
|
+
```bash
|
|
1520
|
+
kiwimatecoder config ui show
|
|
1521
|
+
kiwimatecoder config ui color never # auto | always | never
|
|
1522
|
+
kiwimatecoder config ui theme ocean # default | ocean | magenta | mono
|
|
1523
|
+
kiwimatecoder config ui output compact # normal | compact | verbose
|
|
1524
|
+
kiwimatecoder config ui ascii on # on | off
|
|
1525
|
+
kiwimatecoder config ui spinner off # auto | on | off
|
|
1526
|
+
```
|
|
1527
|
+
|
|
1528
|
+
The same settings are available in-session with `/config ui ...`. Values live
|
|
1529
|
+
under the `ui` key in `~/.kiwimatecoder/config.json`:
|
|
1530
|
+
|
|
1531
|
+
```json
|
|
1532
|
+
{
|
|
1533
|
+
"ui": {
|
|
1534
|
+
"theme": "ocean",
|
|
1535
|
+
"color": "auto",
|
|
1536
|
+
"output_mode": "normal",
|
|
1537
|
+
"ascii": false,
|
|
1538
|
+
"locale": "en",
|
|
1539
|
+
"keybindings": "emacs",
|
|
1540
|
+
"notify": "off",
|
|
1541
|
+
"notify_after_seconds": 20,
|
|
1542
|
+
"spinner": "auto"
|
|
1543
|
+
}
|
|
1544
|
+
}
|
|
1545
|
+
```
|
|
1546
|
+
|
|
1547
|
+
Color precedence: an explicit `ui.color` of `always`/`never` wins; otherwise
|
|
1548
|
+
`NO_COLOR` set to anything non-empty disables color, then `FORCE_COLOR` set to
|
|
1549
|
+
anything non-empty enables it. With `auto` and neither variable exported, Rich
|
|
1550
|
+
still detects a pipe or log file and stays plain.
|
|
1551
|
+
|
|
1552
|
+
Output modes shape the tool log. `normal` prints a line per tool with a success
|
|
1553
|
+
or failure marker. `compact` hides successful tool lines while keeping failures,
|
|
1554
|
+
the thinking status, and the final answer. `verbose` adds a redacted argument
|
|
1555
|
+
block (secrets replaced, capped at ~500 characters) before each tool runs and
|
|
1556
|
+
the result size after.
|
|
1557
|
+
|
|
1558
|
+
ASCII mode replaces the check, cross, blocked, folder, and bullet glyphs with
|
|
1559
|
+
plain text (`[ok]`, `[fail]`, `[blocked]`, no folder prefix, `-`) and the CLI
|
|
1560
|
+
confirmations follow suit. Color, theme, ASCII, and output-mode changes apply
|
|
1561
|
+
to the next session.
|
|
1562
|
+
|
|
1563
|
+
Animated status spinners can be disabled for screen readers, tmux capture, or
|
|
1564
|
+
quiet terminals with `config ui spinner off` (or `/config ui spinner off`).
|
|
1565
|
+
For a fully plain single run, the global `--plain` flag forces ASCII glyphs, no
|
|
1566
|
+
color, compact tool output, and no spinner without persisting anything:
|
|
1567
|
+
|
|
1568
|
+
```bash
|
|
1569
|
+
kiwimatecoder --plain
|
|
1570
|
+
kiwimatecoder --plain -p "Summarize this repository"
|
|
1571
|
+
```
|
|
1572
|
+
|
|
1573
|
+
The full audit — what works today, what does not, and the concrete follow-ups
|
|
1574
|
+
— is in [docs/accessibility.md](docs/accessibility.md).
|
|
1575
|
+
|
|
1576
|
+
### Language and locale
|
|
1577
|
+
|
|
1578
|
+
A representative subset of user-facing strings is translated: the banner hint,
|
|
1579
|
+
prompt and approval labels, common errors, `/help` group titles, and key CLI
|
|
1580
|
+
messages. Pick the language from `ui.locale`, the `KIWIMATECODER_LANG`
|
|
1581
|
+
environment variable, or English (in that precedence order):
|
|
1582
|
+
|
|
1583
|
+
```bash
|
|
1584
|
+
kiwimatecoder config ui locale de # en | de | es
|
|
1585
|
+
KIWIMATECODER_LANG=es kiwimatecoder # per-run override
|
|
1586
|
+
```
|
|
1587
|
+
|
|
1588
|
+
The migration is incremental: untranslated strings stay in English, and a
|
|
1589
|
+
locale that is missing a key falls back to English and then to the key itself.
|
|
1590
|
+
`/config ui locale <en|de|es>` switches the language for the current session
|
|
1591
|
+
immediately.
|
|
1592
|
+
|
|
1593
|
+
### Keybindings and notifications
|
|
1594
|
+
|
|
1595
|
+
The prompt is Emacs-style by default; switch to Vim mode with
|
|
1596
|
+
`config ui keybindings vim` (or `/config ui keybindings vim`). Vim mode keeps
|
|
1597
|
+
the same completion and Alt+Enter bindings and adds modal editing.
|
|
1598
|
+
|
|
1599
|
+
`ui.notify` can ring the terminal bell (`bell`) or send a desktop notification
|
|
1600
|
+
(`desktop`: OSC 9 when stderr is a TTY, otherwise `osascript` on macOS or
|
|
1601
|
+
`notify-send` on Linux) when a turn takes at least `ui.notify_after_seconds`
|
|
1602
|
+
seconds (default 20; `0` notifies after every turn):
|
|
1603
|
+
|
|
1604
|
+
```bash
|
|
1605
|
+
kiwimatecoder config ui notify bell
|
|
1606
|
+
kiwimatecoder config ui notify-after 30
|
|
1607
|
+
```
|
|
1608
|
+
|
|
1609
|
+
### `@`-mentions
|
|
1610
|
+
|
|
1611
|
+
Typing `@` offers workspace file-path completions (gitignored files are
|
|
1612
|
+
skipped). A sent line containing `@path/to/file` attaches that text file as a
|
|
1613
|
+
`[mentioned files]` context block ahead of the message — at most 5 files per
|
|
1614
|
+
turn, 64 KB each, with truncation markers. Image paths (`@shot.png`) use the
|
|
1615
|
+
image-attachment path instead, so pasting or dragging an image into the
|
|
1616
|
+
terminal works as before.
|
|
1617
|
+
|
|
1618
|
+
## Model routing
|
|
1619
|
+
|
|
1620
|
+
Route short, plain requests to a cheaper model while keeping the session model
|
|
1621
|
+
for real work. Configure it under `model_routing` in
|
|
1622
|
+
`~/.kiwimatecoder/config.json`:
|
|
1623
|
+
|
|
1624
|
+
```json
|
|
1625
|
+
{
|
|
1626
|
+
"model_routing": {
|
|
1627
|
+
"enabled": true,
|
|
1628
|
+
"simple_model": "gpt-5-mini",
|
|
1629
|
+
"simple_max_chars": 200,
|
|
1630
|
+
"exclude_keywords": ["refactor", "implement", "debug", "test"]
|
|
1631
|
+
}
|
|
1632
|
+
}
|
|
1633
|
+
```
|
|
1634
|
+
|
|
1635
|
+
A turn is routed when routing is enabled, `simple_model` is set, the message is
|
|
1636
|
+
at most `simple_max_chars` long, and it contains no code fence, file path,
|
|
1637
|
+
slash command, or exclude keyword (whole-word, case-insensitive). The override
|
|
1638
|
+
applies to the primary provider only — fallback providers keep their own
|
|
1639
|
+
models — and the session's model is never changed.
|
|
1640
|
+
|
|
1641
|
+
## Prompt caching
|
|
1642
|
+
|
|
1643
|
+
Native Anthropic providers support prompt caching. Enable it with
|
|
1644
|
+
`kiwimatecoder config cache on` (or `/config cache on`): requests then send the
|
|
1645
|
+
system prompt as a cacheable content block and mark the last tool definition as
|
|
1646
|
+
an ephemeral cache breakpoint, cutting latency and input cost when the same
|
|
1647
|
+
system prompt and tools repeat across turns. The toggle only changes native
|
|
1648
|
+
Anthropic payloads — OpenAI-compatible providers cache automatically, so their
|
|
1649
|
+
requests are byte-for-byte identical either way.
|
|
1650
|
+
|
|
1651
|
+
## Auto-verify
|
|
1652
|
+
|
|
1653
|
+
Point the agent at your test/lint command and it runs automatically after any
|
|
1654
|
+
successful file edit, feeding the output back so it can fix failures:
|
|
1655
|
+
|
|
1656
|
+
```bash
|
|
1657
|
+
kiwimatecoder config verify set "pytest -q"
|
|
1658
|
+
kiwimatecoder config verify show
|
|
1659
|
+
kiwimatecoder config verify clear
|
|
1660
|
+
```
|
|
1661
|
+
|
|
1662
|
+
## Budgets
|
|
1663
|
+
|
|
1664
|
+
Cap a session's spend by tokens, cost, or both. The agent warns at 80% and
|
|
1665
|
+
stops starting new turns once a limit is reached:
|
|
1666
|
+
|
|
1667
|
+
```bash
|
|
1668
|
+
kiwimatecoder config budget tokens 500000
|
|
1669
|
+
kiwimatecoder config budget cost 5.00
|
|
1670
|
+
kiwimatecoder config budget show
|
|
1671
|
+
kiwimatecoder config budget clear
|
|
1672
|
+
```
|
|
1673
|
+
|
|
1674
|
+
A token limit is a whole number from 1 to 1,000,000,000,000,000; use `clear`
|
|
1675
|
+
for no limit.
|
|
1676
|
+
|
|
1677
|
+
## Audit log
|
|
1678
|
+
|
|
1679
|
+
Every tool decision (allowed, denied, dry-run, auto-verify) is appended to
|
|
1680
|
+
`~/.kiwimatecoder/audit.log` as one JSON line per action. Secrets are redacted
|
|
1681
|
+
before writing; the file is owner-only and safe to delete.
|
|
1682
|
+
|
|
1683
|
+
A `pre_tool` hook that exits non-zero blocks the action and is recorded with
|
|
1684
|
+
the `hook_blocked` decision.
|
|
1685
|
+
|
|
1686
|
+
## Telemetry and debug logging
|
|
1687
|
+
|
|
1688
|
+
Telemetry is **opt-in, local-only, and off by default**. When enabled, events
|
|
1689
|
+
from the lifecycle bus (`session_start`, `session_end`, `pre_tool`,
|
|
1690
|
+
`post_tool`), provider errors and retries, and (at the `debug` level) provider
|
|
1691
|
+
HTTP metadata (method/host/status/duration only — never bodies or headers) are
|
|
1692
|
+
appended as one compact JSON object per line to
|
|
1693
|
+
`~/.kiwimatecoder/logs/kiwimatecoder.log`. Secret-looking strings are redacted
|
|
1694
|
+
with the same rules as the audit log, the file is owner-only, and it rotates to
|
|
1695
|
+
`.log.1` once it would grow past `max_log_bytes`:
|
|
1696
|
+
|
|
1697
|
+
```bash
|
|
1698
|
+
kiwimatecoder config telemetry enable on
|
|
1699
|
+
kiwimatecoder config telemetry level info # off | error | info | debug
|
|
1700
|
+
kiwimatecoder config telemetry show
|
|
1701
|
+
```
|
|
1702
|
+
|
|
1703
|
+
Slash equivalents: `/config telemetry show|enable on|off|level <lvl>`. Log
|
|
1704
|
+
files are never uploaded anywhere. Crash bundles (`crash-<timestamp>.json`
|
|
1705
|
+
containing a redacted traceback, version, platform, and recent log lines) are
|
|
1706
|
+
written only while telemetry is enabled at a level other than `off`, and
|
|
1707
|
+
`/doctor` lists the level, log path, and crash-report count.
|
|
1708
|
+
|
|
1709
|
+
Set `KIWIMATECODER_DEBUG=1` to force the `debug` level for one run without
|
|
1710
|
+
changing config (handy for diagnosing a stubborn provider or proxy issue).
|
|
1711
|
+
|
|
1712
|
+
An OTLP exporter is not implemented yet; see the roadmap (5.2 follow-up).
|
|
1713
|
+
|
|
1714
|
+
## Lifecycle hooks
|
|
1715
|
+
|
|
1716
|
+
Run your own shell commands when the agent reaches a lifecycle event. Hooks
|
|
1717
|
+
live under the `hooks` key in `~/.kiwimatecoder/config.json` (a project
|
|
1718
|
+
`.kiwimatecoder.json` may add them too). Each event maps to a list of commands
|
|
1719
|
+
run with the session workspace as their working directory:
|
|
1720
|
+
|
|
1721
|
+
```json
|
|
1722
|
+
{
|
|
1723
|
+
"hooks": {
|
|
1724
|
+
"session_start": ["echo session started in $KIWI_WORKSPACE"],
|
|
1725
|
+
"session_end": ["echo session ended"],
|
|
1726
|
+
"pre_tool": ["test \"$KIWI_TOOL_NAME\" != \"run_bash\" || ./scripts/safety-check.sh"],
|
|
1727
|
+
"post_tool": ["echo \"$KIWI_TOOL_NAME\" exited ok=$KIWI_TOOL_OK\" >> .kiwi-hooks.log"]
|
|
1728
|
+
}
|
|
1729
|
+
}
|
|
1730
|
+
```
|
|
1731
|
+
|
|
1732
|
+
Events are `session_start`, `session_end`, `pre_tool`, and `post_tool`. Hooks
|
|
1733
|
+
receive `KIWI_EVENT` and `KIWI_WORKSPACE`, plus `KIWI_TOOL_NAME`,
|
|
1734
|
+
`KIWI_TOOL_OK` (`true`/`false`), `KIWI_TOOL_ARGS` (JSON; secrets redacted), and
|
|
1735
|
+
`KIWI_TOOL_DURATION_MS` for tool events. A non-zero exit from a `pre_tool` hook
|
|
1736
|
+
blocks the tool call; every hook times out after 60 seconds and never crashes
|
|
1737
|
+
the agent. Commands run through the platform shell (`/bin/sh` on POSIX,
|
|
1738
|
+
`cmd.exe` on Windows), so write them in that shell's syntax; the examples above
|
|
1739
|
+
are POSIX. `/config` does not manage hooks yet — edit the JSON directly.
|
|
1740
|
+
|
|
1741
|
+
## Configuration
|
|
1742
|
+
|
|
1743
|
+
Global settings live in `~/.kiwimatecoder/config.json` (provider keys, the
|
|
1744
|
+
default provider, the model chosen for each provider under `provider_models`,
|
|
1745
|
+
default mode, sampling, output style, theme/color/output/ASCII preferences,
|
|
1746
|
+
custom prompt, and persisted tool approvals). The original single-key
|
|
1747
|
+
`~/.kiwimatecoder/config` format is read automatically, so existing setups keep
|
|
1748
|
+
working. Config files from before per-provider models (version 2 or older) are
|
|
1749
|
+
migrated on load: a model saved with `config model set` becomes the primary provider's
|
|
1750
|
+
choice, and a custom provider's `default_model` becomes its chosen model.
|
|
1751
|
+
Built-in providers that never had a model chosen ask for one. A custom provider
|
|
1752
|
+
whose id is now built in (a hand-made `kiwimate`) is renamed to
|
|
1753
|
+
`kiwimate-custom`, keeping its stored key, model, filter, and the profiles that
|
|
1754
|
+
used it; if it read its key from `KIWIMATE_API_KEY`, it now reads
|
|
1755
|
+
`KIWIMATE_CUSTOM_API_KEY` so the built-in and the custom provider never share a
|
|
1756
|
+
key.
|
|
1757
|
+
|
|
1758
|
+
A project can pin its own settings in `.kiwimatecoder.json` at the repository
|
|
1759
|
+
root (or wherever `KIWIMATECODER_PROJECT_CONFIG` points). Project values
|
|
1760
|
+
override global config — useful for pinning a provider, model, mode, sampling,
|
|
1761
|
+
or permissions per repository. A pinned `selected_model` applies to the primary
|
|
1762
|
+
provider only and wins over the model chosen for it. API keys are never read
|
|
1763
|
+
from project files.
|
|
1764
|
+
|
|
1765
|
+
A shared **team policy** file can be layered on top of both (see
|
|
1766
|
+
[Team policies and session sharing](#team-policies-and-session-sharing)); it is
|
|
1767
|
+
configured only in the global config, so a cloned repository can never disable
|
|
1768
|
+
or redirect it.
|
|
1769
|
+
|
|
1770
|
+
Fetched model catalogs are cached separately in
|
|
1771
|
+
`~/.kiwimatecoder/model_cache.json`. It holds no secrets and can be deleted at
|
|
1772
|
+
any time; the next `/model` rebuilds it.
|
|
1773
|
+
|
|
1774
|
+
Prompt history lives in `~/.kiwimatecoder/history` and session autosaves in
|
|
1775
|
+
`~/.kiwimatecoder/sessions/last.json`. Both can be deleted at any time.
|
|
1776
|
+
|
|
1777
|
+
Run `kiwimatecoder doctor` (or `/doctor`) to check config paths, key status,
|
|
1778
|
+
provider reachability, the model catalog, whether a model is chosen, and the
|
|
1779
|
+
workspace.
|
|
1780
|
+
|
|
1781
|
+
## Profiles
|
|
1782
|
+
|
|
1783
|
+
Profiles are named presets of global settings: provider, model, mode, sampling,
|
|
1784
|
+
output style, custom system prompt, verify command, budget, trusted workspace,
|
|
1785
|
+
command rules, and persisted `always` approvals. Capture the current effective
|
|
1786
|
+
settings, then re-apply them anywhere:
|
|
1787
|
+
|
|
1788
|
+
```bash
|
|
1789
|
+
kiwimatecoder config profile save work
|
|
1790
|
+
kiwimatecoder config profile list
|
|
1791
|
+
kiwimatecoder config profile show work
|
|
1792
|
+
kiwimatecoder config profile use work # writes the preset into config
|
|
1793
|
+
kiwimatecoder config profile remove work
|
|
1794
|
+
```
|
|
1795
|
+
|
|
1796
|
+
Launch once with a profile without persisting it with `kiwimatecoder --profile
|
|
1797
|
+
work`. On a fresh session the provider, model, mode, and other session-level
|
|
1798
|
+
settings come from the profile; with `--resume`/`--continue` only the mode and
|
|
1799
|
+
model are overlaid so the restored conversation keeps its provider. Sampling
|
|
1800
|
+
and budget are global settings, so use `config profile use` to apply those.
|
|
1801
|
+
The REPL equivalent is `/config profile list|show|save|use|remove`.
|
|
1802
|
+
|
|
1803
|
+
## Cross-machine session sync
|
|
1804
|
+
|
|
1805
|
+
Sync saved sessions across machines through a folder you already share (Dropbox,
|
|
1806
|
+
iCloud Drive, a network mount, or a git checkout). There is no server component
|
|
1807
|
+
and nothing is sent anywhere: the feature is off by default and only reads and
|
|
1808
|
+
writes the folder you point it at.
|
|
1809
|
+
|
|
1810
|
+
Enable it with an existing directory:
|
|
1811
|
+
|
|
1812
|
+
```bash
|
|
1813
|
+
kiwimatecoder sync enable ~/Dropbox/kiwimatecoder
|
|
1814
|
+
```
|
|
1815
|
+
|
|
1816
|
+
or edit `~/.kiwimatecoder/config.json` directly:
|
|
1817
|
+
|
|
1818
|
+
```json
|
|
1819
|
+
{
|
|
1820
|
+
"sync": {
|
|
1821
|
+
"enabled": true,
|
|
1822
|
+
"path": "~/Dropbox/kiwimatecoder",
|
|
1823
|
+
"machine": "laptop",
|
|
1824
|
+
"include_autosave": false
|
|
1825
|
+
}
|
|
1826
|
+
}
|
|
1827
|
+
```
|
|
1828
|
+
|
|
1829
|
+
The folder gets a `kiwimatecoder-sessions/` subdirectory holding the session
|
|
1830
|
+
JSON files plus a `manifest.json` index. `machine` defaults to a slug of the
|
|
1831
|
+
hostname; set it explicitly when two machines would otherwise share a name.
|
|
1832
|
+
|
|
1833
|
+
```bash
|
|
1834
|
+
kiwimatecoder sync status # local/remote counts, pending changes, conflicts
|
|
1835
|
+
kiwimatecoder sync push # copy local sessions into the shared folder
|
|
1836
|
+
kiwimatecoder sync pull # copy newer shared sessions into the local store
|
|
1837
|
+
kiwimatecoder sync disable # opt out; the shared folder is left alone
|
|
1838
|
+
```
|
|
1839
|
+
|
|
1840
|
+
The same actions are available in the REPL as `/sync [status|push|pull]`.
|
|
1841
|
+
Everything mirrors the local session store except the implicit `last.json`
|
|
1842
|
+
autosave, which is skipped by default (`include_autosave: true` opts in) because
|
|
1843
|
+
it changes on every exit. Unreadable or corrupt files are skipped and reported,
|
|
1844
|
+
never fatal.
|
|
1845
|
+
|
|
1846
|
+
**Conflicts.** Each machine remembers what it last pushed or pulled. On the next
|
|
1847
|
+
`push`, a shared file that changed elsewhere *and* whose local copy also changed
|
|
1848
|
+
is kept as both: the shared copy stays put and the local copy is uploaded as
|
|
1849
|
+
`<name>__<machine>.json`. Every other difference is last-write-wins by the
|
|
1850
|
+
session's `saved_at` timestamp. `pull` uses the same rule but renames the
|
|
1851
|
+
incoming file to `<name>__<remote-machine>.json` instead of overwriting the
|
|
1852
|
+
local one. Pass `--force` to `push`/`pull` to make the local copy (push) or the
|
|
1853
|
+
shared copy (pull) win unconditionally.
|
|
1854
|
+
|
|
1855
|
+
## Team policies and session sharing
|
|
1856
|
+
|
|
1857
|
+
### Shared team policies
|
|
1858
|
+
|
|
1859
|
+
A team can publish a shared policy JSON file (same shape as
|
|
1860
|
+
`.kiwimatecoder.json`) that is layered **on top of** global and project config,
|
|
1861
|
+
so policy values win. There is no server component and no identity provider:
|
|
1862
|
+
the file is read from the local path you configure, and a cloned repository can
|
|
1863
|
+
never disable or redirect it because `team` settings are taken from the global
|
|
1864
|
+
config only.
|
|
1865
|
+
|
|
1866
|
+
Point the global config at the shared file:
|
|
1867
|
+
|
|
1868
|
+
```bash
|
|
1869
|
+
kiwimatecoder config team set-policy ~/team/kiwimatecoder-policy.json
|
|
1870
|
+
kiwimatecoder config team enforce on
|
|
1871
|
+
kiwimatecoder config team show
|
|
1872
|
+
```
|
|
1873
|
+
|
|
1874
|
+
or edit `~/.kiwimatecoder/config.json` directly:
|
|
1875
|
+
|
|
1876
|
+
```json
|
|
1877
|
+
{
|
|
1878
|
+
"team": {
|
|
1879
|
+
"policy_path": "/Users/you/team/kiwimatecoder-policy.json",
|
|
1880
|
+
"enforce": true
|
|
1881
|
+
}
|
|
1882
|
+
}
|
|
1883
|
+
```
|
|
1884
|
+
|
|
1885
|
+
The policy file may only control these keys: `default_mode`,
|
|
1886
|
+
`selected_provider`, `active_providers`, `selected_model`,
|
|
1887
|
+
`model_filters`, `command_rules`, `tool_permissions`, `sampling`, `trusted_workspace`,
|
|
1888
|
+
`output_style`, `system_prompt`, `verify_command`, `budget`, `mcp_servers`,
|
|
1889
|
+
`plugins`, `subagents`, `sandbox`, `remote`, and `network`. `keys`, `version`,
|
|
1890
|
+
and `team` are ignored, so a policy can never carry API keys or weaken its own
|
|
1891
|
+
enforcement. Unknown keys are reported as warnings. The per-provider model
|
|
1892
|
+
choices (`provider_models`) are deliberately not a policy key — an enforced
|
|
1893
|
+
policy would replace every provider's choice at once — so a team pins the
|
|
1894
|
+
primary provider's model with `selected_model`.
|
|
1895
|
+
|
|
1896
|
+
- **Advisory** (`enforce: false`): policy values override global and project
|
|
1897
|
+
values, but project config still fills in any key the policy does not set.
|
|
1898
|
+
- **Enforced** (`enforce: true`): each policy key replaces the merged value
|
|
1899
|
+
wholesale, and project values for policy keys the policy does not define are
|
|
1900
|
+
ignored, so a repository cannot widen or weaken the policy namespace.
|
|
1901
|
+
|
|
1902
|
+
A missing or corrupt policy file never blocks startup: it is skipped and
|
|
1903
|
+
reported by `kiwimatecoder config validate`, `kiwimatecoder doctor`, and
|
|
1904
|
+
`/config team show`. The REPL equivalents are
|
|
1905
|
+
`/config team [show|set-policy <path>|enforce on|off]`.
|
|
1906
|
+
|
|
1907
|
+
### Session sharing
|
|
1908
|
+
|
|
1909
|
+
Share a conversation as a redacted JSON bundle, either as a local file or as a
|
|
1910
|
+
**secret** GitHub gist through your own `gh` login (no token is read or stored
|
|
1911
|
+
by KiwiMateCoder):
|
|
1912
|
+
|
|
1913
|
+
```bash
|
|
1914
|
+
kiwimatecoder share create # last session -> .kiwimatecoder/shares/
|
|
1915
|
+
kiwimatecoder share create my-session --output ~/Desktop/review.json
|
|
1916
|
+
kiwimatecoder share create --gist # uploads via `gh gist create`
|
|
1917
|
+
kiwimatecoder share import bundle.share.json --name from-teammate
|
|
1918
|
+
```
|
|
1919
|
+
|
|
1920
|
+
In the REPL, `/share` bundles the current session, `/share gist` uploads it,
|
|
1921
|
+
and `/share import <path>` turns a bundle into a normal saved session.
|
|
1922
|
+
|
|
1923
|
+
Privacy notes:
|
|
1924
|
+
|
|
1925
|
+
- Every string is passed through the same secret redactor used for logs, so
|
|
1926
|
+
API keys and `token = ...` assignments never leave the machine.
|
|
1927
|
+
- Tool **results are omitted** (replaced with `[tool output omitted]`) unless
|
|
1928
|
+
you pass `--include-tool-output`; when included they are redacted and
|
|
1929
|
+
truncated to 2 KB. Tool call names are kept for context, and their arguments
|
|
1930
|
+
are redacted and clipped.
|
|
1931
|
+
- Image attachments are replaced with `[image omitted]` so no base64 image data
|
|
1932
|
+
is embedded in the bundle.
|
|
1933
|
+
- Bundles are capped at ~256 KB; when a conversation is larger the oldest
|
|
1934
|
+
messages are dropped and `truncated` / `truncated_messages` record it.
|
|
1935
|
+
- Sharing is local or gist-based only. **SSO/identity and any hosted sharing
|
|
1936
|
+
service are deferred** (see the roadmap) — there is no server to run.
|
|
1937
|
+
|
|
1938
|
+
## Config validation
|
|
1939
|
+
|
|
1940
|
+
`kiwimatecoder config validate` checks the stored config and prints a table of
|
|
1941
|
+
issues, exiting non-zero when any error-level problem is found. It surfaces
|
|
1942
|
+
exactly what the tolerant getters would silently drop: unknown top-level keys
|
|
1943
|
+
(warning), malformed provider/model-filter/sampling/budget/hook/command-rule/
|
|
1944
|
+
profile/MCP/plugin entries, a model chosen for an unknown provider in
|
|
1945
|
+
`provider_models` (warning), invalid regexes, unknown hook events, bad network
|
|
1946
|
+
(proxy/CA/offline) values, bad ACP permission timeouts, a missing or corrupt
|
|
1947
|
+
team policy file, and bad default mode,
|
|
1948
|
+
output style, UI (theme/color/ASCII/output mode), or workspace-flag values.
|
|
1949
|
+
|
|
1950
|
+
## Evals
|
|
1951
|
+
|
|
1952
|
+
`kiwimatecoder eval` runs declarative regression cases against any configured
|
|
1953
|
+
provider. A case is a small JSON file with a prompt, optional starting files,
|
|
1954
|
+
and deterministic expectations about the run:
|
|
1955
|
+
|
|
1956
|
+
```json
|
|
1957
|
+
{
|
|
1958
|
+
"name": "create-file-from-prompt",
|
|
1959
|
+
"description": "Writes a requested file with exact content.",
|
|
1960
|
+
"prompt": "Create hello.txt whose contents are exactly 'hello from the eval'.",
|
|
1961
|
+
"files": {"notes.txt": "Starting workspace file."},
|
|
1962
|
+
"expect": {
|
|
1963
|
+
"text_contains": ["hello"],
|
|
1964
|
+
"text_not_contains": ["error"],
|
|
1965
|
+
"tools_called": ["write_file"],
|
|
1966
|
+
"tools_not_called": ["run_bash"],
|
|
1967
|
+
"files": {"hello.txt": ["hello from the eval"]},
|
|
1968
|
+
"success": true
|
|
1969
|
+
}
|
|
1970
|
+
}
|
|
1971
|
+
```
|
|
1972
|
+
|
|
1973
|
+
List and run the committed cases:
|
|
1974
|
+
|
|
1975
|
+
```bash
|
|
1976
|
+
kiwimatecoder eval list
|
|
1977
|
+
kiwimatecoder eval run --provider openrouter --model anthropic/claude-sonnet-5
|
|
1978
|
+
kiwimatecoder eval run --filter create --json --report eval-report.json
|
|
1979
|
+
```
|
|
1980
|
+
|
|
1981
|
+
Every field in `expect` is optional: `text_contains`/`text_not_contains` check
|
|
1982
|
+
the final assistant text, `tools_called`/`tools_not_called` check the tools the
|
|
1983
|
+
run used, `files` maps workspace paths to substrings that must appear in the
|
|
1984
|
+
file after the run, and `success` checks the run's own success flag. A run
|
|
1985
|
+
error is always a failure unless the case explicitly expects `success: false`.
|
|
1986
|
+
|
|
1987
|
+
Cases live in `evals/cases/*.json` and are discovered sorted by `name`. Copy
|
|
1988
|
+
one as a starting point, or point `--dir` at another directory. The command
|
|
1989
|
+
exits `0` when every case passes, `1` when any case fails, and `2` on invalid
|
|
1990
|
+
input (bad directory, malformed JSON, unknown provider, or no `--model` passed
|
|
1991
|
+
and none chosen for the provider — `No model chosen for <provider>…`). Eval
|
|
1992
|
+
runs call a real model, so they need a configured provider key and a chosen
|
|
1993
|
+
model (`kiwimatecoder setup`) or `--model`; each
|
|
1994
|
+
case runs in a throwaway temp workspace and nothing is recorded beyond the
|
|
1995
|
+
report you ask for. Expectations are deterministic — there is no model-graded
|
|
1996
|
+
scoring yet.
|
|
1997
|
+
|
|
1998
|
+
## Development
|
|
1999
|
+
|
|
2000
|
+
```bash
|
|
2001
|
+
pip install -e ".[dev]"
|
|
2002
|
+
pytest
|
|
2003
|
+
ruff check kiwimatecoder tests
|
|
2004
|
+
mypy kiwimatecoder
|
|
2005
|
+
```
|
|
2006
|
+
|
|
2007
|
+
## Roadmap
|
|
2008
|
+
|
|
2009
|
+
The full prioritized plan lives in [ROADMAP.md](ROADMAP.md). P0 and P1 are
|
|
2010
|
+
implemented (checkpoints/undo, command rules, dry-run, redacted audit log,
|
|
2011
|
+
hunk-level approvals, todos, ask-user, parallel reads, compaction, auto-verify,
|
|
2012
|
+
budgets, trusted workspace, and message steering with interrupt recovery), and
|
|
2013
|
+
P2 is complete (event bus + hooks, the extensible tool registry, custom
|
|
2014
|
+
commands and prompt templates, on-demand Agent Skills, a plugin system, the MCP
|
|
2015
|
+
client, config profiles with schema validation, per-turn model routing,
|
|
2016
|
+
Anthropic prompt caching, and themes/output modes/NO_COLOR accessibility).
|