Originally created by: imshaikot
The side panel runs on whichever agent CLI you already have logged in — Claude Code, Codex or Antigravity. Mistral ships one too: Mistral Vibe (mistralai/mistral-vibe, binary vibe), open source, with a documented headless mode. Someone whose subscription is Le Chat or a Mistral API key has no way into the side panel today.
It is also a good fit on containment, which is the part that usually decides whether a runner is worth having: --enabled-tools is a real per-run allowlist, so Vibe's shell and file tools can be kept out of a run entirely — Claude Code's class, not Antigravity's.
Runner contract| What a runner needs | Mistral Vibe (v2.25.5) |
|---|---|
| Newline-delimited events | vibe --prompt … --output streaming — one JSON history entry per line |
| Per-run MCP server | No flag. [[mcp_servers]] with transport = "stdio" and its own env, in a project .vibe/config.toml; headless only honours that file with --trust |
| Appended system prompt | AGENTS.md in the trusted cwd. system_prompt_id replaces the prompt, so it is the wrong lever |
| Sessions | every entry carries sessionId; --resume <id>, and the lookup is not cwd-scoped |
| Off-machine guard | --enabled-tools 'browsentic_*' — in -p mode everything unnamed is never loaded |
| Auth | vibe --setup, or MISTRAL_API_KEY in ~/.vibe/.env |
Skills for the / picker |
~/.vibe/skills, ~/.agents/skills |
So the shape is Antigravity's — files written into a per-run cwd through Plan.files — with Claude Code's containment.
runStream rejects any run that closes before the reader calls done, so the driver needs a small opt-in: a runner says a clean exit is the end of the turn.ask, and headless turns an ask into a refusal. No glob. The config therefore has to grant every Browsentic tool by name, which means the runner needs the daemon's live tool list — the extension's, once it has drifted from the bundled one — not a hard-coded one. --auto-approve would make all of this unnecessary and is exactly what must not be used.--resume replays the whole history before the new turn. The reader has to tell replay from new output or the panel reprints the conversation.thinking key on a model in Vibe's own config. Ship with no effort names.vibe --prompt <instruction> --output streaming --trust --agent ask
--enabled-tools 'browsentic_*' [--enabled-tools web_search --enabled-tools web_fetch]
[--resume <sessionId>]
:::toml
# .vibe/config.toml, written into ~/.browsentic/agents/vibe/run/<runId>/
active_model = "<picked model, if any>"
[[mcp_servers]]
name = "browsentic"
transport = "stdio"
command = ["<node>"]
args = ["<cli.js>", "mcp"]
[mcp_servers.env]
BROWSENTIC_AGENT_RUN = "<runId>"
[tools."browsentic_page_clickElement"]
permission = "always"
# …one per tool the run's MCP server offers
--agent ask pins the approval profile, so a user whose own default_agent is auto-approve does not carry that into a browser run. The user's ~/.vibe/config.toml is read for their key and models and never written — no check() / grant() needed.
task mode writes the same file with no MCP server, and enables either read_file alone or a pattern that matches no tool — an empty --enabled-tools means every tool, which is the trap.
Guardrails: a CONTAINMENT entry in the allowlist class, keepsEnv: ['MISTRAL_', 'VIBE_'], MISTRAL_ added to the prefixes sealed away from every other agent, --auto-approve added to FORBIDDEN beside --yolo, and vetPlan asserting that nothing outside the expected names ever follows --enabled-tools.
There is no way to prove the reader against the real CLI without a Mistral key, and the field names (sessionId, createdAt, detail.toolName) come from reading Vibe's source rather than from captured output. Label it beta in the docs until a real run — one instruction, then a follow-up in the same conversation — has been through it.
[#8] proposes Grok Build as the runner after this one, and expects to reuse the two hooks this adds.
Tickets: #10
Tickets: #26
Tickets: #28
Tickets: #34
Tickets: #8
Ticket changed by: imshaikot