Apps

Vibe

Edit on GitHub · last edited

The desktop assistant — a chat window and a terminal REPL over the model already resident in synapd, with the run of the desktop.

Vibe opens folders, panels and applications, changes settings and applies them live, reads and edits files, answers questions about this machine, and runs shell commands you confirm. Its default backend is synapd, so it reuses the model already loaded on the GPU: no second model, no extra VRAM, no account. Give it a key and it will talk to Claude or OpenAI instead.

Upstream: velle999/vibe. Packaged for SynapseOS as vibe.

Running it

vibe                    # the terminal REPL, in whatever directory you point it at
vibe gui                # the chat window — the same assistant

Or press the speech bubble in the bar, which toggles the window. It is one assistant either way: one conversation loop, one tool set, one set of confirmations.

Command What it does
vibe the REPL
vibe gui the chat window
vibe provider [name] show or set the backend — synapd, ollama, llama_cpp, anthropic, openai
vibe host [name|local] which synapd answers — this machine's socket, or another box's bridge
vibe key [provider] where each API key lives; vibe key anthropic prompts, - reads stdin, --forget removes it
vibe voice read answers aloud, and take dictation — also what the screen reader speaks through, so the desktop has one voice
vibe wake on|off listen for its name
vibe intents [line] what it answers directly, without a model — and which rule claims a line

What it can touch

Alongside the file and shell tools it has always had:

  • desktop_open — a folder by the name you use for it (downloads, my pictures, home), an application, a web address, or one of the desktop's own panels: control panel, task manager, displays, network, bluetooth, wallpaper, theme, widgets, clipboard history, emoji picker, calculator.
  • desktop_action — any of the compositor's own verbs, checked against synctl binds so the list cannot drift from what this build answers to.
  • desktop_setting — whitelisted synuirc keys, applied live.
  • system_info — what this machine actually is, read off /proc, the DMI tables, lspci and nvidia-smi. A field it cannot read is left out rather than filled in.

The confirmation gate

The line is does it write, not is it dangerous. bash, write_file, edit_file, desktop_action, desktop_setting and move_file pause for a y / n / always prompt; read_file, glob, grep, list_dir, desktop_open and system_info never do.

Opening a folder is not a decision worth interrupting for, and a confirmation on harmless things trains the hand to press Enter without reading — which is what makes the prompt worthless on the request that matters. --yolo disables the gate for a session.

Modes

Auto is the default and picks one of three per message, then behaves exactly as if you had chosen it:

Mode Behaviour
Ask answers, with no tools at all — the fastest turn, and the right one for a question about the world
Agent answers and acts, with the gate in front of anything that writes
Plan read-only tools: it can look at the machine and change nothing, and the answer is the steps it would take

The routing is evidence the process already has — whether synsh claims the line, whether the words name a file or a setting or this machine — not a question put to the model, which costs a round trip and is got wrong in exactly the cases that matter.

Requests that never reach a model

A line that plainly names a desktop action — "open downloads", "what's in my documents", "lock the screen", "pc stats" — is carried out directly. No model is loaded, no tokens are generated, and the answer is the tool's own words.

This is not an optimisation. Measured end to end on "open downloads" with the model in the loop, the request reached the file manager in 2 runs out of 8: the shipped 7B has no structured tool-calling, so the tools are prompt text and the calls are <tool_call> blocks a regex reads back — and it will announce a tool, ask permission for one that never asks, or write its own Tool result: and answer from the fiction. There is no prompt that fixes a request which should not have been put to a model at all.

vibe intents lists what is answered this way; vibe intents "<line>" says which rule claims a line and runs nothing.

It claims whole lines only. open, run, list and lock are real programs as well as real English, so "how do I open my downloads from a script" still reaches the model.

It is also a shell

synsh answers everyday lines from a table in milliseconds — "what time is it", "is firefox installed", "open youtube" — and vibe asks it first. A line synsh recognises as a command is run rather than described, after showing you the command and waiting. See synsh.

Voice

The voice stack is synapse-voice, the speech engine Chibi uses too, not a second copy: piper for speech, faster-whisper for dictation, with their models, so both work offline. vibe voice reads answers aloud and takes dictation; vibe wake on listens for its name, and the bar's assistant button changes while it is listening — a window you cannot see is not a disclosure that the microphone is open.

The listener ships disabled, and an update never turns it on. The switches are in the control panel and in syn-settings, and the wake words are yours.

Backends

vibe provider anthropic          # persisted for the next start
VIBE_BACKEND=ollama vibe         # or per-invocation
vibe host desktop.lan            # synapd's TCP bridge on another host
VIBE_SYNAPD_HOST=10.0.0.5 vibe   # ... or for one run only

synapd is the default and needs no account. ollama and llama_cpp are for local setups you already run. anthropic goes through the official SDK rather than an OpenAI-compatible shim, so adaptive thinking, tool-use blocks and the refusal stop reason survive; openai reuses the chat-completions path.

Keys live in your keyring where there is one and a 0600 file where there is not. syn-settings ▸ Assistant sets the backend and stores the key from a window — the field is masked, and the key never becomes a command-line argument at any point.

How it talks to synapd

synapd is a single-shot request/response daemon with no structured tool-calling, so vibe drives its text tool path: the tools are described in the prompt, the model emits <tool_call>{…}</tool_call> blocks, and vibe parses, executes and feeds the result back, looping until the task is done. It sends a SYN_QF_RAW query (see synapd) so it owns the whole chat template and is not capped at synapd's short default answer length.

Owning the template matters: SynapseOS ships a Mistral, whose template has no system role and rejects one, so the system prompt folds into the first user turn. Emitting somebody else's turn markers at it produces an assistant that invents its own.

Expectations

The stock model is a 7B — fine for questions about your files and this machine, small edits and scaffolding, and mediocre at agentic tool-calling. That is why the desktop requests above do not go through it at all. Swap in a stronger GGUF (drop it in as /var/lib/synapd/models/synapse.gguf and restart synapd), point vibe at a larger backend over the bridge, or give it a cloud key.

It is pure Python — python-rich and python-prompt_toolkit come from the Arch repos, so there is no venv. The app lives at /usr/lib/vibe/app, the launcher at /usr/bin/vibe, and the chat window is quickshell rendering /usr/share/vibe/vibe.qml in its own process.

See also: synapd (the backend and wire protocol), synsh (the shell it asks first) and Chibi (which shares its speech engine).