Apps
Vibe
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 againstsynctl bindsso the list cannot drift from what this build answers to.desktop_setting— whitelistedsynuirckeys, applied live.system_info— what this machine actually is, read off /proc, the DMI tables,lspciandnvidia-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).