@ziamana/bruine 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +315 -0
- package/THIRD_PARTY_NOTICES.md +24 -0
- package/cordis.patch.yml +166 -0
- package/dist/bin.js +5358 -0
- package/dist/compat.js +40 -0
- package/dist/plugins/approval.js +147 -0
- package/dist/plugins/headless.js +236 -0
- package/dist/plugins/herdr.js +470 -0
- package/dist/plugins/mcp.js +275 -0
- package/dist/plugins/modes.js +850 -0
- package/dist/plugins/render.js +3723 -0
- package/dist/plugins/repl.js +9589 -0
- package/dist/plugins/silence.js +234 -0
- package/dist/plugins/startup.js +42 -0
- package/dist/plugins/web-search.js +138 -0
- package/package.json +93 -0
- package/skills/code-review/SKILL.md +30 -0
- package/skills/git-workflow/SKILL.md +31 -0
- package/skills/impeccable/LICENSE +191 -0
- package/skills/impeccable/NOTICE.md +11 -0
- package/skills/impeccable/SKILL.md +87 -0
- package/skills/impeccable/reference/adapt.md +318 -0
- package/skills/impeccable/reference/adapt.native.md +58 -0
- package/skills/impeccable/reference/android.md +46 -0
- package/skills/impeccable/reference/animate.md +89 -0
- package/skills/impeccable/reference/audit.md +137 -0
- package/skills/impeccable/reference/audit.native.md +139 -0
- package/skills/impeccable/reference/bolder.md +33 -0
- package/skills/impeccable/reference/clarify.md +94 -0
- package/skills/impeccable/reference/colorize.md +86 -0
- package/skills/impeccable/reference/component-review.md +63 -0
- package/skills/impeccable/reference/craft-floor.md +44 -0
- package/skills/impeccable/reference/craft.md +5 -0
- package/skills/impeccable/reference/critique.md +806 -0
- package/skills/impeccable/reference/degraded/asset-producer.md +42 -0
- package/skills/impeccable/reference/degraded/documenter.md +24 -0
- package/skills/impeccable/reference/degraded/finish-reviewer.md +38 -0
- package/skills/impeccable/reference/degraded/manual-edit-applier.md +92 -0
- package/skills/impeccable/reference/delight.md +70 -0
- package/skills/impeccable/reference/distill.md +111 -0
- package/skills/impeccable/reference/doctor.md +54 -0
- package/skills/impeccable/reference/document.md +416 -0
- package/skills/impeccable/reference/extract.md +69 -0
- package/skills/impeccable/reference/generate.md +101 -0
- package/skills/impeccable/reference/harden.md +345 -0
- package/skills/impeccable/reference/hooks.md +113 -0
- package/skills/impeccable/reference/init.md +131 -0
- package/skills/impeccable/reference/ios.md +51 -0
- package/skills/impeccable/reference/layout.md +84 -0
- package/skills/impeccable/reference/live-setup.md +104 -0
- package/skills/impeccable/reference/live.md +325 -0
- package/skills/impeccable/reference/mode-operate.md +21 -0
- package/skills/impeccable/reference/mode-persuade.md +19 -0
- package/skills/impeccable/reference/mode-read.md +21 -0
- package/skills/impeccable/reference/new-work.md +154 -0
- package/skills/impeccable/reference/onboard.md +234 -0
- package/skills/impeccable/reference/operate.md +61 -0
- package/skills/impeccable/reference/optimize.md +258 -0
- package/skills/impeccable/reference/overdrive.md +127 -0
- package/skills/impeccable/reference/polish.md +105 -0
- package/skills/impeccable/reference/quieter.md +99 -0
- package/skills/impeccable/reference/region-map.md +26 -0
- package/skills/impeccable/reference/routing.md +24 -0
- package/skills/impeccable/reference/shape.md +59 -0
- package/skills/impeccable/reference/typeset.md +80 -0
- package/skills/impeccable/reference/visualize.md +46 -0
- package/skills/impeccable/scripts/VERSION +1 -0
- package/skills/impeccable/scripts/command-metadata.json +98 -0
- package/skills/impeccable/scripts/data/font-index-failures.json +121 -0
- package/skills/impeccable/scripts/data/font-index.json +1 -0
- package/skills/impeccable/scripts/impeccable +206 -0
- package/skills/impeccable/scripts/impeccable.cmd +214 -0
- package/skills/impeccable/scripts/live-browser-dom.js +167 -0
- package/skills/impeccable/scripts/live-browser-ignores.js +242 -0
- package/skills/impeccable/scripts/live-browser-session.js +148 -0
- package/skills/impeccable/scripts/live-browser.js +13510 -0
- package/skills/impeccable/scripts/modern-screenshot.umd.js +14 -0
- package/skills/make-interfaces-feel-better/LICENSE +21 -0
- package/skills/make-interfaces-feel-better/SKILL.md +187 -0
- package/skills/make-interfaces-feel-better/agents/openai.yaml +3 -0
- package/skills/make-interfaces-feel-better/animations.md +403 -0
- package/skills/make-interfaces-feel-better/icons.md +63 -0
- package/skills/make-interfaces-feel-better/performance.md +88 -0
- package/skills/make-interfaces-feel-better/surfaces.md +256 -0
- package/skills/make-interfaces-feel-better/typography.md +157 -0
- package/skills/playwright-cli/LICENSE +201 -0
- package/skills/playwright-cli/SKILL.md +489 -0
- package/skills/playwright-cli/references/element-attributes.md +23 -0
- package/skills/playwright-cli/references/playwright-tests.md +39 -0
- package/skills/playwright-cli/references/pr-attachments.md +60 -0
- package/skills/playwright-cli/references/request-mocking.md +87 -0
- package/skills/playwright-cli/references/running-code.md +245 -0
- package/skills/playwright-cli/references/session-management.md +227 -0
- package/skills/playwright-cli/references/storage-state.md +275 -0
- package/skills/playwright-cli/references/test-generation.md +433 -0
- package/skills/playwright-cli/references/tracing.md +139 -0
- package/skills/playwright-cli/references/video-recording.md +216 -0
- package/skills/remotion/SKILL.md +42 -0
- package/skills/systematic-debugging/SKILL.md +26 -0
- package/skills/thermo-nuclear-code-quality-review/LICENSE +21 -0
- package/skills/thermo-nuclear-code-quality-review/SKILL.md +192 -0
- package/skills/write-tests/SKILL.md +35 -0
- package/skills/youtube-transcript/LICENSE +21 -0
- package/skills/youtube-transcript/SKILL.md +41 -0
- package/skills/youtube-transcript/package.json +8 -0
- package/skills/youtube-transcript/transcript.js +44 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 ziamana
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
<picture>
|
|
4
|
+
<source media="(prefers-color-scheme: dark)" srcset="docs/media/wordmark-dark.svg">
|
|
5
|
+
<img src="docs/media/wordmark-light.svg" alt="bruine" width="380">
|
|
6
|
+
</picture>
|
|
7
|
+
|
|
8
|
+
### A coding agent for your terminal that runs your own models.
|
|
9
|
+
|
|
10
|
+
*bruine* (French, /bʁɥin/): a fine, steady rain.
|
|
11
|
+
|
|
12
|
+
[](LICENSE)
|
|
13
|
+
[](https://nodejs.org)
|
|
14
|
+

|
|
15
|
+
[](CHANGELOG.md)
|
|
16
|
+
|
|
17
|
+
<a href="docs/media/bruine-film.mp4"><img src="docs/media/hero.webp" alt="The bruine film: the word bruine becomes the logo in the rain, then the effort climbs from low to max and the rain turns into a storm" width="100%"></a>
|
|
18
|
+
|
|
19
|
+
<sub>▶ <a href="docs/media/bruine-film.mp4"><b>Watch the 42-second film</b></a> (with sound) · made in code with Remotion, the demo inside it is the real bruine, recorded cell by cell</sub>
|
|
20
|
+
|
|
21
|
+
</div>
|
|
22
|
+
|
|
23
|
+
<br>
|
|
24
|
+
|
|
25
|
+
Point bruine at a llama.cpp server on your machine, at any cloud provider (DeepSeek, Anthropic,
|
|
26
|
+
OpenAI, Google, OpenRouter, Groq, Mistral, xAI and about twenty more), or at anything that speaks
|
|
27
|
+
the OpenAI-compatible `/v1` API. It reads and edits your code, runs your commands, and asks before
|
|
28
|
+
anything risky. There is no account, and nothing is sent anywhere you did not point it at.
|
|
29
|
+
|
|
30
|
+
```
|
|
31
|
+
npm install -g @ziamana/bruine
|
|
32
|
+
bruine
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
The first launch opens a setup wizard: it finds a local model server if you run one, asks for API
|
|
36
|
+
keys if you want a cloud route, lets you pick skills, and writes `~/.bruine/`.
|
|
37
|
+
|
|
38
|
+
## See it
|
|
39
|
+
|
|
40
|
+
<img src="docs/demo/bruine.svg" alt="bruine in a terminal: a prompt, the model's reasoning streaming then folding away, a file read, an edit shown as a diff, two permission prompts, the tests passing, and a second prompt that was queued while it worked going out after" width="100%">
|
|
41
|
+
|
|
42
|
+
<sub>A real session in a real terminal on a real project, with a scripted model so it is the same every
|
|
43
|
+
time: [`test/e2e/demo-recording.test.ts`](test/e2e/demo-recording.test.ts) records it. The stills below
|
|
44
|
+
come the same way, from [`test/e2e/screenshots.test.ts`](test/e2e/screenshots.test.ts).</sub>
|
|
45
|
+
|
|
46
|
+
<table>
|
|
47
|
+
<tr>
|
|
48
|
+
<td width="50%" valign="top">
|
|
49
|
+
<img src="docs/media/approval.png" alt="An approval: a framed amber band saying Allow write src/summary.ts, with y Allow once, a Always allow every write this session, n Reject, and the prompt box below reading Waiting for you 3s">
|
|
50
|
+
<p><b>It asks first, in one keystroke.</b> The request is the one framed thing on screen: <code>y</code> once,
|
|
51
|
+
<code>a</code> always (and it says exactly what "always" covers), <code>n</code> or <code>esc</code> no. The
|
|
52
|
+
turn's clock stops and the rain holds still while it waits for you.</p>
|
|
53
|
+
</td>
|
|
54
|
+
<td width="50%" valign="top">
|
|
55
|
+
<img src="docs/media/retry.png" alt="A retry: the transcript says The model has not answered for 1s. Retry 1/5 in 0.5s, and the prompt box reads Working 6s, retry 1/5">
|
|
56
|
+
<p><b>A quiet model is retried, out loud.</b> How long bruine waits depends on what the model was doing,
|
|
57
|
+
how hard it was asked to think and how many tries it has had; when it gives up, the transcript says
|
|
58
|
+
why, which attempt, and when.</p>
|
|
59
|
+
</td>
|
|
60
|
+
</tr>
|
|
61
|
+
<tr>
|
|
62
|
+
<td width="50%" valign="top">
|
|
63
|
+
<img src="docs/media/image.png" alt="read_image design/mockup.png: the image itself drawn in the terminal with coloured half blocks, a night-blue gradient with a falling drop and rings, captioned PNG 192x108">
|
|
64
|
+
<p><b>It shows you what it looks at.</b> An image the model reads is drawn right in the transcript, in
|
|
65
|
+
any 24-bit or 256-colour terminal: no graphics protocol, no window, just colour.</p>
|
|
66
|
+
</td>
|
|
67
|
+
<td width="50%" valign="top">
|
|
68
|
+
<img src="docs/media/light.png" alt="bruine on a light terminal theme: an edit shown as a diff with pale red and green bands, dark text, and the status bar with cache 95.3% and ctx 6.4% of 100k">
|
|
69
|
+
<p><b>Light or dark, it reads.</b> bruine asks the terminal for its background and fits every colour to
|
|
70
|
+
it; on 256-colour terminals the surfaces stay gray instead of turning navy.</p>
|
|
71
|
+
</td>
|
|
72
|
+
</tr>
|
|
73
|
+
</table>
|
|
74
|
+
|
|
75
|
+
## Why bruine
|
|
76
|
+
|
|
77
|
+
- **Your models, first class.** A local model on one GPU is not a degraded cloud: bruine keeps the
|
|
78
|
+
prompt cache warm (the system prompt and the tool list never change inside a session), keeps side
|
|
79
|
+
requests off a single-slot server, and shows what the hardware really does.
|
|
80
|
+
- **One permission gate you can read.** Ask, Auto or Full access, decided by a rule table in plain
|
|
81
|
+
TypeScript with tests, not a black box: a plain read runs, a path outside the project asks, a
|
|
82
|
+
dangerous command always asks, and Plan mode refuses changes. MCP tools go through the same gate.
|
|
83
|
+
- **Numbers you can trust.** Context used, tokens per second, prefill and cache hits are measured from
|
|
84
|
+
bruine's own clock. The harness once reported 79 tok/s where the truth was 60; bruine does not copy it.
|
|
85
|
+
- **Calm.** Reasoning streams word by word and folds into one line; tool calls read as sentences; edits
|
|
86
|
+
are diffs; you can keep typing while it works. And it rains in your terminal, as hard as the model is
|
|
87
|
+
asked to think.
|
|
88
|
+
|
|
89
|
+
## The gist in a minute
|
|
90
|
+
|
|
91
|
+
| You want to | In bruine |
|
|
92
|
+
|---|---|
|
|
93
|
+
| Plan before it builds | `Shift+Tab` toggles Plan and Build |
|
|
94
|
+
| Choose how much it asks | `/permissions`, or `/ask`, `/auto`, `/full` |
|
|
95
|
+
| Think harder or faster | `ctrl+e` cycles the reasoning effort, `/effort` picks one |
|
|
96
|
+
| Switch model mid-session | `/model`, `f2` walks the ones you used recently |
|
|
97
|
+
| Queue the next task while it works | just type and press Enter: it waits above the box |
|
|
98
|
+
| Run a command yourself | `!npm test` (the output is not sent to the model) |
|
|
99
|
+
| Show it a screenshot | `ctrl+v` (`alt+v` in Windows Terminal) |
|
|
100
|
+
| Use your MCP servers | `mcpServers` in `bruine.json` or `.mcp.json`, then `/mcp` |
|
|
101
|
+
| Reuse your skills | Claude Code, OpenCode, pi and `~/.agents/skills` skills are picked up |
|
|
102
|
+
| Script it | `bruine -p "task" --output-format json` |
|
|
103
|
+
|
|
104
|
+
A first setup also asks, as a plain yes or no, whether to use Space Bunny Free: a model OpenCode serves
|
|
105
|
+
at no charge for a limited time through its Zen gateway, with no account and no key. The answer starts on
|
|
106
|
+
No. Saying yes sends your prompts and files to OpenCode's provider (which states zero retention and no
|
|
107
|
+
training), and the offer can end without notice, so keep another model in reach.
|
|
108
|
+
|
|
109
|
+
## What it does
|
|
110
|
+
|
|
111
|
+
| Feature | What you see |
|
|
112
|
+
|---|---|
|
|
113
|
+
| Live reasoning | The model's thinking streams in place, word by word, then collapses to `Thought for 4.2s` |
|
|
114
|
+
| Diffs | Every edit and write is shown as a diff, one green or red band per line, before you approve it |
|
|
115
|
+
| Images, both ways | `ctrl+v` sends a screenshot to a vision model, and an image the model reads is drawn in the transcript |
|
|
116
|
+
| Retries you can see | An adaptive silence budget per request, and "Retry 2/5" in the transcript instead of a clock that keeps counting |
|
|
117
|
+
| Updates | A notice when a new version is out, and `/update` installs it after a yes |
|
|
118
|
+
| Tool calls | Every call streams its arguments, then a grouped summary with a duration and a coloured rail |
|
|
119
|
+
| A real permission gate | Ask / Auto / Full access, decided by a rule table you can read, not a black box |
|
|
120
|
+
| Plan mode | `Shift+Tab` to plan before it builds; the plan is a message, the tools never change |
|
|
121
|
+
| `/model` and `/provider` | Switch model mid-session from the server's own live catalogue |
|
|
122
|
+
| Skills | Reuses the skills you already wrote for Claude Code, OpenCode, pi or `~/.agents/skills` |
|
|
123
|
+
| Context and speed | A footer that shows context used, tok/s, prefill and cache hit rate |
|
|
124
|
+
| Works on | Windows Terminal, PowerShell, macOS Terminal, iTerm2, Konsole, GNOME Terminal |
|
|
125
|
+
| herdr | Works with herdr: shows up as `bruine` in `herdr agent list`. |
|
|
126
|
+
|
|
127
|
+
## The weather
|
|
128
|
+
|
|
129
|
+
Use `/effect` for a live preview picker, or choose directly: `/effect bruine` (quiet drizzle), `/effect pluie` (steady rain), `/effect foudre` (heavy rain with distant lavender lightning), `/effect auto` (drizzle at rest; while working, rain as hard as the reasoning effort: each of low, medium, high, xhigh and max has its own weather, and max brings distant lightning), or `/effect off`.
|
|
130
|
+
`/effect on` is an alias for `/effect auto`. Enter saves the choice in `bruine.json`; Escape cancels the preview. Weather is rendered locally and uses no model tokens.
|
|
131
|
+
It follows the visible screen, including empty space below the composer and while reading back. It stays clear of the composer, controls and painted cards, pauses while selecting text, and follows `BRUINE_NO_ANIMATION`, `BRUINE_NO_RAIN`, ASCII and no-color settings.
|
|
132
|
+
|
|
133
|
+
<p align="center"><a href="docs/media/bruine-film.mp4"><img src="docs/media/effort.webp" alt="The prompt box as ctrl+e climbs from low to max: its border glows violet, then runs every colour, and the rain turns into a storm" width="100%"></a></p>
|
|
134
|
+
|
|
135
|
+
## MCP servers
|
|
136
|
+
|
|
137
|
+
bruine runs the tools of any MCP server, in the format Claude Code and Cursor use, so a server row
|
|
138
|
+
from a README or from your Claude Code config works as it is. Put your own servers under
|
|
139
|
+
`mcpServers` in `~/.bruine/bruine.json`; a project can share its own in `.mcp.json` at its root.
|
|
140
|
+
|
|
141
|
+
```json
|
|
142
|
+
{
|
|
143
|
+
"mcpServers": {
|
|
144
|
+
"github": { "command": "npx", "args": ["-y", "@modelcontextprotocol/server-github"], "env": { "GITHUB_TOKEN": "${GITHUB_TOKEN}" } },
|
|
145
|
+
"docs": { "type": "http", "url": "https://example.com/mcp", "readOnly": true }
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
- The tools show up as `mcp__<server>__<tool>` and go through the same permission gate as every
|
|
151
|
+
other tool: they ask first in Ask mode, are judged in Auto, and Plan mode refuses them. A server
|
|
152
|
+
marked `"readOnly": true` runs without asking (also in Plan mode); `"alwaysAllow": ["tool"]`
|
|
153
|
+
lets chosen tools through. `${VAR}` and `${VAR:-default}` are read from the environment.
|
|
154
|
+
- A project's `.mcp.json` starts programs on your machine, so its servers only run once you have
|
|
155
|
+
seen what they run and said yes. The answer is kept per project, and a changed command asks again.
|
|
156
|
+
- Servers connect before the first turn and the tool list stays the same for the whole session, so
|
|
157
|
+
the prompt cache survives. `/mcp` lists the servers, their state and tools; `/mcp enable <name>`
|
|
158
|
+
and `/mcp disable <name>` apply to the next session.
|
|
159
|
+
- Tools are bridged; MCP resources and prompts are not (yet). Streamable HTTP is supported, the old
|
|
160
|
+
SSE transport is not.
|
|
161
|
+
|
|
162
|
+
## How it compares
|
|
163
|
+
|
|
164
|
+
An honest table, checked against each project's documentation in October 2026; tell us if something
|
|
165
|
+
moved. Every one of these is a good tool, and some do things bruine does not.
|
|
166
|
+
|
|
167
|
+
| | bruine | Claude Code | OpenCode | Aider | Codex CLI |
|
|
168
|
+
|---|---|---|---|---|---|
|
|
169
|
+
| Source | MIT | Proprietary | MIT | Apache-2.0 | Apache-2.0 |
|
|
170
|
+
| Models | Any: local llama.cpp, any `/v1` server, ~30 cloud providers | Claude (Anthropic API, Bedrock, Vertex) | 75+ providers, local included | Most LLMs, local included | OpenAI; local open-weight models with `--oss` |
|
|
171
|
+
| Built for local models | Yes: cache kept warm, single-slot aware, measured tok/s | No | Supported | Supported | gpt-oss through Ollama or LM Studio |
|
|
172
|
+
| MCP | Tools, stdio and HTTP | Yes | Yes | Not built in | Yes |
|
|
173
|
+
| Permission model | One rule table, Ask / Auto / Full, Plan mode | Modes and rules, Plan mode | Per-agent permissions, Plan agent | Confirms commands; Git is the safety net | Approval modes and an OS sandbox |
|
|
174
|
+
| Undo a change | No (use Git) | Yes, checkpoints and `/rewind` | Yes, `/undo` `/redo` | Yes, every edit is a commit, `/undo` | No (`/undo` was removed; use Git) |
|
|
175
|
+
| IDE integration | No, terminal only | Yes | Yes (LSP, desktop app) | Editor plugins by the community | Yes |
|
|
176
|
+
|
|
177
|
+
**Where bruine is behind, today:** no checkpoints or rewind (Git is your undo), no IDE or ACP
|
|
178
|
+
integration, MCP is tools only (no resources, prompts or OAuth login), no LSP, and it is young (0.1)
|
|
179
|
+
on top of a harness that is itself a developer preview. If you mostly use Claude models in an IDE,
|
|
180
|
+
Claude Code is the better fit; if you want Git-commit-per-edit, Aider is.
|
|
181
|
+
|
|
182
|
+
## FAQ
|
|
183
|
+
|
|
184
|
+
**Is it free?** Yes, MIT, and everything that runs locally stays MIT. You pay your model provider, or
|
|
185
|
+
nothing at all with a local model.
|
|
186
|
+
|
|
187
|
+
**Does it send my code anywhere?** Only to the model route you configured. Telemetry is off unless you
|
|
188
|
+
turn it on in the setup. Network discovery of model servers is opt-in and only touches private ranges
|
|
189
|
+
(10/8, 172.16/12, 192.168/16, and Tailscale 100.64/10).
|
|
190
|
+
|
|
191
|
+
**Which local model should I use?** One trained for tool calls, served by llama.cpp (or any OpenAI
|
|
192
|
+
compatible server) with a context of 32k or more. Small models can chat but tend to lose the thread in
|
|
193
|
+
long agent loops. The setup detects what the server's chat template supports (thinking, effort levels).
|
|
194
|
+
|
|
195
|
+
**Does it work on Windows?** Yes: Windows Terminal, PowerShell and the classic console; commands run in
|
|
196
|
+
PowerShell there. [docs/PLATFORMS.md](docs/PLATFORMS.md) lists what was checked and what still has limits.
|
|
197
|
+
|
|
198
|
+
**How do I make it ask less?** `/auto` lets a fast model judge the routine actions (risky ones still
|
|
199
|
+
ask), the approval's `a` (Always) remembers one exact command for the session and says which, and
|
|
200
|
+
`/full` asks nothing at all (it says so loudly). For an MCP server you trust, `"readOnly": true` or `"alwaysAllow": [...]`.
|
|
201
|
+
|
|
202
|
+
**Can I reuse my Claude Code setup?** Your skills, yes, and MCP servers in the same format, including a
|
|
203
|
+
project's `.mcp.json`. Claude Code hooks are not run.
|
|
204
|
+
|
|
205
|
+
**What is dsh?** [DeepSeek Harness](https://github.com/deepseek-ai), the agent runtime underneath.
|
|
206
|
+
bruine is a profile and a bundle of plugins on top of it, not a fork, so harness updates arrive without
|
|
207
|
+
a merge. The version is pinned and upgraded on purpose.
|
|
208
|
+
|
|
209
|
+
**Why does it rain?** Because it is called bruine. The weather is local, uses no tokens, stays out of
|
|
210
|
+
the input box and the cards, follows the effort with `/effect auto`, and goes away with `/effect off`
|
|
211
|
+
or `BRUINE_NO_ANIMATION=1`.
|
|
212
|
+
|
|
213
|
+
## Commands
|
|
214
|
+
|
|
215
|
+
```
|
|
216
|
+
bruine Start bruine. Extra args are passed through to dsh.
|
|
217
|
+
bruine --continue Resume the latest conversation in this project.
|
|
218
|
+
bruine -p "task" Run a task without the terminal UI and print its answer.
|
|
219
|
+
bruine -p - Read a task from stdin.
|
|
220
|
+
bruine setup (Re)run the setup wizard, pre-filled with your current values.
|
|
221
|
+
bruine skills List the skills bruine has enabled.
|
|
222
|
+
bruine update Update bruine through its installer.
|
|
223
|
+
bruine --version Print the version.
|
|
224
|
+
bruine --help Print the help.
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
Use `--output-format json` or `--output-format stream-json` with `-p` for scripts. A headless
|
|
228
|
+
task denies any tool action that would need a permission prompt; use `--permission-mode full`
|
|
229
|
+
only when that task should run with full access.
|
|
230
|
+
|
|
231
|
+
Inside a session, `/` opens the command palette: `/new`, `/resume`, `/verify`, `/compact`, `/plan`, `/permissions`,
|
|
232
|
+
`/model`, `/provider`, `/effort`, `/skills`, `/plugins`, `/mcp`, `/update`, `/reload`, `/help`, `/exit`. `f2` walks the routes you
|
|
233
|
+
used recently. You can keep typing while bruine works: a prompt sent during a turn waits above the
|
|
234
|
+
box and goes out, as its own turn, when the current one ends (`↑` on an empty box takes the last one
|
|
235
|
+
back to edit; `escape` stops the turn and puts the queued prompts back in the box, unsent). `ctrl+t` shows the task list, `ctrl+o` expands tool output, `ctrl+e` cycles the
|
|
236
|
+
reasoning effort, `ctrl+v` pastes an image (`alt+v` in Windows Terminal, which keeps `ctrl+v` for its own paste).
|
|
237
|
+
|
|
238
|
+
## Updates
|
|
239
|
+
|
|
240
|
+
Once a day, bruine asks npm for the latest version (one plain GET, nothing about you). When there
|
|
241
|
+
is a newer one, the session says so above the box: `/update` installs it after a yes, through the
|
|
242
|
+
installer bruine was installed with (npm, pnpm or bun), and `bruine update` does the same from a
|
|
243
|
+
shell. A git checkout is never touched. `"updateCheck": false` in `bruine.json` turns the check off.
|
|
244
|
+
What changed is in [CHANGELOG.md](CHANGELOG.md).
|
|
245
|
+
|
|
246
|
+
## When the model goes quiet
|
|
247
|
+
|
|
248
|
+
A model can be silent for a long time and still be working: thinking at a high effort, or writing a
|
|
249
|
+
large file whose content the server sends at once. It can also simply have stopped. bruine gives
|
|
250
|
+
each silence a budget that depends on what the model was doing (more time for a model that has not
|
|
251
|
+
started, has just finished thinking, or is writing a big tool call; less in the middle of a
|
|
252
|
+
sentence), scaled by the effort and doubled on every retry. Past it, the request is retried, and the
|
|
253
|
+
transcript says so: "The model has not answered for 3m. Retry 2/5 in 1.2s." The route's
|
|
254
|
+
`streamIdleTimeoutMs` in `settings.yaml` stays the hard ceiling.
|
|
255
|
+
|
|
256
|
+
## Environment
|
|
257
|
+
|
|
258
|
+
| Variable | Effect |
|
|
259
|
+
|---|---|
|
|
260
|
+
| `BRUINE_HOME` | Where bruine keeps its config (default `~/.bruine`) |
|
|
261
|
+
| `BRUINE_ASCII=1` | Plain-ASCII glyphs instead of symbols |
|
|
262
|
+
| `BRUINE_NO_ANIMATION=1` | No rain, header or spinner animation |
|
|
263
|
+
| `BRUINE_NO_RIPPLE=1` | Only the ring a finished turn leaves on the prompt rule; the rest of the motion stays |
|
|
264
|
+
| `BRUINE_NO_RAIN=1` | No rain in the setup (margins and behind the panel); the rest of the motion stays |
|
|
265
|
+
| `BRUINE_NO_GLOW=1` | The prompt frame stays one colour whatever the thinking effort (otherwise `high` shimmers violet slowly, `xhigh` fast, and `max` runs every colour) |
|
|
266
|
+
| `BRUINE_INTRO` | The logo's entrance at launch: `random` (the default), `off`, or one effect: `rain`, `decrypt`, `beams`, `wipe`, `slide`, `blackhole`, `spotlights`, `waves`, `fog`, `mist`, `afterrain`, `storm`. Also `"intro"` in `bruine.json`. Any key stops it. |
|
|
267
|
+
| `BRUINE_TOOL_SUMMARIES=0` | Disable readable tool descriptions (also `"toolSummaries": false` in `bruine.json`). Summaries reuse existing arguments and make no model calls. |
|
|
268
|
+
| `BRUINE_BG=0` | Never paint a background, whatever the terminal reports |
|
|
269
|
+
| `BRUINE_NO_UPDATE_CHECK=1` | Never contact the npm registry to check for a version |
|
|
270
|
+
| `BRUINE_SILENCE=off` | Keep the adapters' fixed stream timeout instead of bruine's adaptive silence budget |
|
|
271
|
+
|
|
272
|
+
## Three promises
|
|
273
|
+
|
|
274
|
+
**The numbers are measured, not quoted.** The tok/s in the footer is computed by bruine from its own
|
|
275
|
+
timestamps. The same measurement found the harness reporting 79 tok/s where the truth was 60, so
|
|
276
|
+
bruine does not copy it.
|
|
277
|
+
|
|
278
|
+
**The permission gate is the only one.** The harness sandbox is deliberately left fully open and
|
|
279
|
+
bruine's own rule table is what asks. One layer, readable, testable: a plain command is allowed, a
|
|
280
|
+
path outside the workspace is not, and a dangerous one is never guessed about.
|
|
281
|
+
|
|
282
|
+
**Your prompt cache survives.** The system prompt and the tool list stay byte-identical for the whole
|
|
283
|
+
session. A mode change is an appended message, never a prompt or tool swap. A test spawns the real
|
|
284
|
+
harness and asserts the request prefix never changes.
|
|
285
|
+
|
|
286
|
+
Telemetry is off unless you turn it on in the wizard. Network discovery is opt-in and only ever
|
|
287
|
+
touches private ranges (10/8, 172.16/12, 192.168/16, and Tailscale 100.64/10).
|
|
288
|
+
|
|
289
|
+
## Requirements
|
|
290
|
+
|
|
291
|
+
Node 22 or newer. Windows, macOS, or Linux.
|
|
292
|
+
|
|
293
|
+
## License
|
|
294
|
+
|
|
295
|
+
MIT. Everything that runs locally stays MIT.
|
|
296
|
+
|
|
297
|
+
## More
|
|
298
|
+
|
|
299
|
+
- [`docs/ARCHITECTURE.md`](./docs/ARCHITECTURE.md) - the design, the product constraints, and the
|
|
300
|
+
dsh APIs bruine depends on
|
|
301
|
+
- [`docs/tickets/`](./docs/tickets) - the work, one ticket at a time
|
|
302
|
+
- [`docs/PLATFORMS.md`](./docs/PLATFORMS.md) - what was checked and fixed for Windows and macOS
|
|
303
|
+
- [`bench/`](./bench) - the benchmark: a system-prompt change only ships when a number says it helps
|
|
304
|
+
|
|
305
|
+
## Existing Kumo installations
|
|
306
|
+
|
|
307
|
+
The `bruine` and `kumo` commands use the same launcher. Existing installs keep working without moving or deleting their home.
|
|
308
|
+
|
|
309
|
+
The home is selected in this order: `BRUINE_HOME`, `KUMO_HOME`, an existing `~/.bruine`, an existing `~/.kumo`, then `~/.bruine` for a fresh install.
|
|
310
|
+
Every `BRUINE_*` setting takes precedence over its matching `KUMO_*` fallback, including an explicitly empty value.
|
|
311
|
+
Bruine reads `bruine.json` first and falls back to `kumo.json` only when the new file is absent. Saves write `bruine.json` and leave `kumo.json` untouched.
|
|
312
|
+
The installed-skills manifest follows the same rule: `.bruine-installed.json`, falling back to `.kumo-installed.json`.
|
|
313
|
+
Bruine creates `profiles/bruine` when needed and leaves `profiles/kumo` in place. Updates install the `bruine` npm package.
|
|
314
|
+
|
|
315
|
+
The GitHub repository is `ziamana/bruine`; the old `ziamana/kumo-code` address redirects to it.
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Third-party notices
|
|
2
|
+
|
|
3
|
+
Bruine ships a few skills written by other people, copied unchanged from their public
|
|
4
|
+
repositories with their license files. Each one keeps its own `LICENSE` (and `NOTICE.md`
|
|
5
|
+
where its author provides one) inside `skills/<name>/`. They are offered in the setup, and
|
|
6
|
+
a user can leave any of them out.
|
|
7
|
+
|
|
8
|
+
| Skill | Author and source | License | Taken from |
|
|
9
|
+
|---|---|---|---|
|
|
10
|
+
| `impeccable` | Paul Bakaus, https://github.com/pbakaus/impeccable | Apache-2.0 | commit e103efe, `plugin/skills/impeccable` |
|
|
11
|
+
| `make-interfaces-feel-better` | Jakub Krehel, https://github.com/jakubkrehel/make-interfaces-feel-better | MIT | commit 35545ea, `skills/make-interfaces-feel-better` |
|
|
12
|
+
| `thermo-nuclear-code-quality-review` | Cursor, https://github.com/cursor/plugins | MIT | commit 23e4138, `cursor-team-kit/skills/thermo-nuclear-code-quality-review` |
|
|
13
|
+
| `youtube-transcript` | Mario Zechner, https://github.com/badlogic/pi-skills | MIT | commit 90bb51c, `youtube-transcript` |
|
|
14
|
+
| `playwright-cli` | Microsoft, https://github.com/microsoft/playwright-cli | Apache-2.0 | commit b85c7a7, `skills/playwright-cli` |
|
|
15
|
+
|
|
16
|
+
`impeccable` itself carries a notice (`skills/impeccable/NOTICE.md`) for reference files it
|
|
17
|
+
derives from `ehmo/platform-design-skills` (MIT).
|
|
18
|
+
|
|
19
|
+
The Bruine skills in the same folder (`code-review`, `git-workflow`, `systematic-debugging`,
|
|
20
|
+
`write-tests`, `remotion`) are Bruine's own and fall under Bruine's license.
|
|
21
|
+
|
|
22
|
+
`youtube-transcript` installs its npm dependency (`youtube-transcript-plus`, MIT) the first
|
|
23
|
+
time it is used; nothing of it is shipped. `impeccable`'s launcher may download its helper
|
|
24
|
+
binary on first use.
|
package/cordis.patch.yml
ADDED
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
# The bruine bundle patch: an interactive terminal agent over dsh-base.
|
|
2
|
+
# Inserts the bruine plugins (startup, repl, render, approval, web-search, mcp) and
|
|
3
|
+
# the extra tool rows. Cache rule (ARCHITECTURE section 0): the system prompt
|
|
4
|
+
# and the tools array are byte-identical all session long — modes are a
|
|
5
|
+
# bruine-side gate + appended messages, never a prompt/tool swap.
|
|
6
|
+
|
|
7
|
+
# T36: only the harness identity is switched off here. The persona itself is
|
|
8
|
+
# composed at boot by src/profile.ts into the profile's own patch layer, where
|
|
9
|
+
# it carries the model's display name (a local route's model id is a .gguf
|
|
10
|
+
# path) — and where the bruine-bench system-prompt variants are applied, without
|
|
11
|
+
# ever editing this file or dsh.
|
|
12
|
+
- id: system-prompt
|
|
13
|
+
config:
|
|
14
|
+
includeHarnessIdentity: false
|
|
15
|
+
|
|
16
|
+
# bruine's own search provider (SearXNG / Brave / Tavily, configured in
|
|
17
|
+
# bruine.json; "none" by default). Never dsh-free-search. The provider registers
|
|
18
|
+
# itself with the `web` runtime lazily, so no gating is needed here.
|
|
19
|
+
- id: web
|
|
20
|
+
config:
|
|
21
|
+
searchProvider: bruine
|
|
22
|
+
fetchProvider: http
|
|
23
|
+
|
|
24
|
+
# T26: bruine owns the USER skills root. Setup links/copies the chosen skills
|
|
25
|
+
# into $DSH_HOME/skills (dsh's dshHome root, unchanged), so repoint
|
|
26
|
+
# agentsHome at a bruine-owned empty directory: `~/.agents/skills` is no longer
|
|
27
|
+
# read implicitly. Project skills (`.agents/skills`, `.dsh/skills` in the
|
|
28
|
+
# workspace) keep working; `dshHomePath` resolves $DSH_HOME at boot, exactly
|
|
29
|
+
# like the dsh-base rows for sessions/storages.
|
|
30
|
+
- id: skill-filesystem
|
|
31
|
+
config:
|
|
32
|
+
agentsHome: !!js dshHomePath('agents')
|
|
33
|
+
|
|
34
|
+
# T31c: the session-title LLM request fires in parallel with the first turn
|
|
35
|
+
# (dsh-session-title onMainRequest); on a single-slot local server it steals
|
|
36
|
+
# ~1.6 s from the first answer (BOS timing proxy). BRUINE_TITLE_LLM=off — set
|
|
37
|
+
# by the launcher when the default route is private/localhost — disables the
|
|
38
|
+
# provider row; dsh then titles from the first prompt with NO request. Cloud
|
|
39
|
+
# routes keep their LLM title.
|
|
40
|
+
- id: session-title-llm
|
|
41
|
+
disabled: !!js process.env.BRUINE_TITLE_LLM === 'off'
|
|
42
|
+
|
|
43
|
+
# T16: safety comes from bruine's own gate, not dsh's sandbox — commands really
|
|
44
|
+
# run on the machine. The sandbox is left fully open; bruine's pre-tool gate is
|
|
45
|
+
# the only permission layer, so dsh escalation never fires.
|
|
46
|
+
- id: sandbox-policy
|
|
47
|
+
config:
|
|
48
|
+
mode: danger-full-access
|
|
49
|
+
workspaceRoot: !!js process.cwd()
|
|
50
|
+
|
|
51
|
+
# Pin approvals to "ask": when bruine's gate returns `ask`, the approval service
|
|
52
|
+
# must actually reach bruine-approval's select.
|
|
53
|
+
- id: approval
|
|
54
|
+
config:
|
|
55
|
+
policy: ask
|
|
56
|
+
|
|
57
|
+
# The presets service validates that the composed (sandbox, approval) pair
|
|
58
|
+
# matches a preset: bruine-ask = sandbox off + approvals reach bruine's select.
|
|
59
|
+
- id: permission
|
|
60
|
+
name: '@deepseek-ai/dsh-permission-presets'
|
|
61
|
+
config:
|
|
62
|
+
defaultPreset: bruine-ask
|
|
63
|
+
presets:
|
|
64
|
+
read-only:
|
|
65
|
+
sandbox: read-only
|
|
66
|
+
approval: ask
|
|
67
|
+
name: Read Only
|
|
68
|
+
description: Files are read-only for tools.
|
|
69
|
+
workspace-write:
|
|
70
|
+
sandbox: workspace-write
|
|
71
|
+
approval: ask
|
|
72
|
+
name: Workspace Edit
|
|
73
|
+
description: Allow edits within the workspace.
|
|
74
|
+
danger-full-access:
|
|
75
|
+
sandbox: danger-full-access
|
|
76
|
+
approval: never
|
|
77
|
+
name: No Sandbox
|
|
78
|
+
description: No sandbox.
|
|
79
|
+
bruine-ask:
|
|
80
|
+
sandbox: danger-full-access
|
|
81
|
+
approval: ask
|
|
82
|
+
name: bruine gate
|
|
83
|
+
description: Sandbox off; bruine's own gate asks before risky actions.
|
|
84
|
+
|
|
85
|
+
# Keep the model-facing catalog fixed for each session. The launcher reads
|
|
86
|
+
# bruine.json before dsh starts; an absent tools setting selects lean.
|
|
87
|
+
- id: plan-mode
|
|
88
|
+
disabled: !!js process.env.BRUINE_TOOLS !== 'full'
|
|
89
|
+
- id: tool-subagent-control
|
|
90
|
+
disabled: !!js process.env.BRUINE_TOOLS !== 'full'
|
|
91
|
+
- id: tool-subagent-list-agents
|
|
92
|
+
disabled: !!js process.env.BRUINE_TOOLS !== 'full'
|
|
93
|
+
- id: tool-subagent-fork
|
|
94
|
+
disabled: !!js process.env.BRUINE_TOOLS !== 'full'
|
|
95
|
+
|
|
96
|
+
# A sub-agent run in the background is a plain job in the lean catalog: job_output
|
|
97
|
+
# reads it, job_kill stops it and /tasks lists it. The persistent mode needs
|
|
98
|
+
# send_message and list_agents, which only the full catalog mounts; with them off a
|
|
99
|
+
# model has no way to follow the child and polls job_output with an id the job
|
|
100
|
+
# registry has never heard of ("unknown job"), then does the work itself. One-shot
|
|
101
|
+
# also waits for the child by default, which is what a small model expects.
|
|
102
|
+
# (A config here replaces the base row's whole config, so the provider and the tool
|
|
103
|
+
# name are repeated.)
|
|
104
|
+
- id: tool-subagent
|
|
105
|
+
config:
|
|
106
|
+
provider: spawn
|
|
107
|
+
toolName: subagent
|
|
108
|
+
backgroundMode: !!js (process.env.BRUINE_TOOLS === 'full' && 'continuable') || 'one-shot'
|
|
109
|
+
- id: tool-workflow
|
|
110
|
+
disabled: !!js process.env.BRUINE_TOOLS !== 'full'
|
|
111
|
+
- id: tool-goal
|
|
112
|
+
disabled: !!js process.env.BRUINE_TOOLS !== 'full'
|
|
113
|
+
- id: tool-ralph
|
|
114
|
+
disabled: !!js process.env.BRUINE_TOOLS !== 'full'
|
|
115
|
+
|
|
116
|
+
- insert:
|
|
117
|
+
- id: bruine-startup
|
|
118
|
+
name: '@ziamana/bruine/startup'
|
|
119
|
+
|
|
120
|
+
- id: bruine-repl
|
|
121
|
+
name: '@ziamana/bruine/repl'
|
|
122
|
+
inject: [bruineStartup]
|
|
123
|
+
disabled: !!js process.env.BRUINE_HEADLESS === '1'
|
|
124
|
+
|
|
125
|
+
- id: bruine-headless
|
|
126
|
+
name: '@ziamana/bruine/headless'
|
|
127
|
+
inject: [bruineStartup]
|
|
128
|
+
disabled: !!js process.env.BRUINE_HEADLESS !== '1'
|
|
129
|
+
|
|
130
|
+
- id: bruine-render
|
|
131
|
+
name: '@ziamana/bruine/render'
|
|
132
|
+
|
|
133
|
+
- id: bruine-herdr
|
|
134
|
+
name: '@ziamana/bruine/herdr'
|
|
135
|
+
disabled: !!js process.env.BRUINE_HEADLESS === '1'
|
|
136
|
+
|
|
137
|
+
- id: bruine-approval
|
|
138
|
+
name: '@ziamana/bruine/approval'
|
|
139
|
+
|
|
140
|
+
- id: bruine-modes
|
|
141
|
+
name: '@ziamana/bruine/modes'
|
|
142
|
+
|
|
143
|
+
- id: bruine-web-search
|
|
144
|
+
name: '@ziamana/bruine/web-search'
|
|
145
|
+
|
|
146
|
+
# MCP servers as tools (mcpServers in bruine.json, and the project's approved
|
|
147
|
+
# .mcp.json): one dsh MCP client per server, all connected before the first
|
|
148
|
+
# turn so the tools array never changes inside a session.
|
|
149
|
+
- id: bruine-mcp
|
|
150
|
+
name: '@ziamana/bruine/mcp'
|
|
151
|
+
|
|
152
|
+
# An adaptive silence budget on every model stream: longer while the model thinks hard or
|
|
153
|
+
# writes a large file, longer on every retry, and a retryable TIMEOUT when it runs out.
|
|
154
|
+
- id: bruine-silence
|
|
155
|
+
name: '@ziamana/bruine/silence'
|
|
156
|
+
|
|
157
|
+
- id: tool-ask-user
|
|
158
|
+
name: '@deepseek-ai/dsh-tool-ask-user'
|
|
159
|
+
|
|
160
|
+
- id: tool-str-replace-editor
|
|
161
|
+
name: '@deepseek-ai/dsh-tool-str-replace-editor'
|
|
162
|
+
disabled: !!js process.env.BRUINE_TOOLS !== 'full'
|
|
163
|
+
|
|
164
|
+
- id: tool-present
|
|
165
|
+
name: '@deepseek-ai/dsh-tool-present'
|
|
166
|
+
disabled: !!js process.env.BRUINE_TOOLS !== 'full'
|