Introduction and setup
Run Sayri, configure a provider, find every file it writes.
Introduction and setup
Sayri is the AI agent for Pulsar OS: voice in, voice out, an agent that can run commands, and a security model that makes it safe to leave running. It consumes a fraction of the tokens and files of similar agents, and its code is small enough to audit.
What it does
- Listens and speaks with 100% local models (whisper.cpp for STT, Piper for TTS), with wake word support.
- Runs as an agent: the model issues
bashcommands, Sayri executes them under the sandbox and feeds the output back. - Runs multiple agents in parallel, each with its own model, sandbox level and gateways.
- Connects to Discord, Telegram or any other channel through gateway plugins.
- Installs skills from the Pulsar OS store and from ClawHub.
- Uses almost no resources.
Requirements
System packages (same list as the Debian control file):
- python3, python3-gi, python3-httpx
- gir1.2-gtk-4.0, gir1.2-webkit-6.0
- libgtk4-layer-shell0
- pipewire
Optional, per feature:
whisper-cli(whisper.cpp) plus a model for speech-to-text. Downloadable from the settings window.- Piper plus a voice for text-to-speech. Also downloadable.
bwrap(bubblewrap), required for sandbox levels 1 and 2. Without it, isolated levels fall back to the host — do not do that on a machine you care about.grimfor screenshots,ydotoolfor input automation.
There is no LLM server bundled. Sayri talks to any OpenAI-compatible endpoint. The shipped default is Ollama (http://127.0.0.1:11434/v1, model llama3.2). On first run, the setup screen asks for a provider and API key.
Running without installing
Sayri is a plain Python package. From a checkout:
export PYTHONPATH="$PWD/PKG/sayri/usr/share/sayri/lib"
python3 -m sayri
The __main__ entry point re-executes itself with libgtk4-layer-shell preloaded (LD_PRELOAD); on Wayland this is what pins the overlay and makes WebKit load reliably. The web UI build and bundled sounds are auto-detected from the package layout, so no SAYRI_DATA_DIR is needed.
To keep all state inside the repo during development:
export SAYRI_CONFIG_DIR="$PWD/.sayri/config"
export SAYRI_STATE_DIR="$PWD/.sayri/state"
When installed as a package, launch with sayri.
Command line
sayri Launch the agent (orb + cajita overlay)
sayri --toggle | -t Toggle the overlay of the running instance
sayri --show / --hide Show or hide the overlay
sayri --settings | -s Open the settings window
sayri --quit | -q Quit the running instance
sayri --autostart Start silently (used by the autostart entry)
sayri skills <args> Manage skills
sayri plugins <args> Manage plugins and gateways
sayri screenshot <path> Take a screenshot (needs grim)
Sayri is single-instance: the first launch opens a UNIX socket ($SAYRI_STATE_DIR/sayri.sock); later invocations forward their command to the running instance over that socket.
Configuration
Settings live in a GLib key file at ~/.config/sayri/sayri.conf (or $SAYRI_CONFIG_DIR/sayri.conf). Groups:
[provider]—base_url,api_key,model,system_prompt,agent_mode,temperature,max_tokens,stream,timeout[stt]—mode(always|wakeword|manual),wake_word,model_size,language,mic_device,silence_ms,live_transcript[tts]—enabled,language,voice,quality,speed[ui]—orb_size,orb_position,autostart,always_on_top,bubble_visible
Edit by hand or with the settings window (gear icon in the cajita, or sayri --settings).
Where everything lives
| Path | Contents |
|---|---|
~/.config/sayri/sayri.conf |
Main configuration |
~/.config/sayri/skills/ |
Installed skills |
~/.config/sayri/plugins/ |
Installed plugins (user) |
~/.config/sayri/agents/ |
Agent profiles, one JSON per agent |
~/.config/sayri/memory.md |
Long-term memory, editable by the model |
~/.config/sayri/USER.md |
User profile |
~/.local/share/sayri/models/ |
Whisper STT models |
~/.local/share/sayri/voices/ |
Piper TTS voices |
~/.local/share/sayri/sessions.db |
Conversation history (SQLite) |
~/.local/share/sayri/sandboxes/ |
Isolated workspaces per agent |
~/.local/share/sayri/logs/ |
Gateway instance logs |
All three roots can be overridden with SAYRI_DATA_DIR, SAYRI_CONFIG_DIR and SAYRI_STATE_DIR. SAYRI_SKIP_PRELOAD=1 disables the layer-shell preload, SAYRI_FORCE_WAYLAND=1 forces the Wayland backend.