Skip to content

Latest commit

 

History

History
224 lines (172 loc) · 11.3 KB

install.md

File metadata and controls

224 lines (172 loc) · 11.3 KB

Installing Omarchy Voice Computer

This guide starts from a fresh Omarchy machine.

1. Requirements

sudo pacman -S --needed go jq pipewire-pulse libpulse   # most of these come with Omarchy
omarchy-voxtype-install                  # optional: F9 dictation

You need Go 1.27 or newer. An older Go fetches the right toolchain by itself (GOTOOLCHAIN=auto, the default). The bar plugin needs Omarchy's shell bar, and the key binds need Omarchy's Lua Hyprland config (~/.config/hypr/bindings.lua).

2. Backends

vcd needs three OpenAI-compatible endpoints, set in ~/.config/voice-computer/config.json:

Part Route vcd calls Local server Hosted
stt: speech to text POST {url}/v1/audio/transcriptions whisper.cpp's whisper-server OpenAI whisper-1
chat: the brain POST {url}/v1/chat/completions (streamed, with tools) llama.cpp's llama-server OpenAI, or any OpenAI-compatible API
tts: text to speech POST {url}/v1/audio/speech (response_format: pcm, 24 kHz mono) Kokoro-FastAPI OpenAI tts-1

url is the base URL without /v1. Each part can use a different server.

A minimal local setup

Every model runs on this machine and nothing leaves it. These are the defaults in install/config.example.json:

# Speech to text on :8081 (whisper.cpp; a model from its models/download-ggml-model.sh)
whisper-server -m ggml-base.en.bin --port 8081 --inference-path /v1/audio/transcriptions

# The brain on :8080 (llama.cpp; any instruct GGUF that can call tools, 3-8B is plenty;
# --jinja is needed for tool calls)
llama-server -m your-model.gguf --jinja --port 8080 -c 8192

# Text to speech on :8880 (Kokoro-FastAPI, CPU image)
docker run -d --name kokoro -p 8880:8880 ghcr.io/remsky/kokoro-fastapi-cpu:latest

Small models answer best with thinking off, or with a reasoning format that keeps the thinking out of the answer (llama-server's default). vcd drops <think>…</think> blocks from what it speaks, but not reasoning whose <think> the chat template put in the prompt (--reasoning-format none).

Hosted (OpenAI or compatible)

Put the key in a file only you can read, and name the file in the config. Never put the key itself in the config:

install -m 600 /dev/null ~/.config/voice-computer/openai.key
$EDITOR ~/.config/voice-computer/openai.key
{
  "backend": "openai",
  "stt":  {"url": "https://api.openai.com", "model": "whisper-1",   "key_file": "~/.config/voice-computer/openai.key"},
  "chat": {"url": "https://api.openai.com", "model": "gpt-4o-mini", "key_file": "~/.config/voice-computer/openai.key"},
  "tts":  {"url": "https://api.openai.com", "model": "tts-1",       "key_file": "~/.config/voice-computer/openai.key"},
  "voice": "alloy"
}

With a hosted backend, everything in the README's privacy section goes to that provider.

3. Install

git clone https://github.com/makefunstuff/omarchy-voice-computer
cd omarchy-voice-computer
install/install.sh

The installer is safe to run again after an update. It:

  • builds ~/.local/bin/vc and starts voice-computer.service (a user service);
  • writes ~/.config/voice-computer/config.json from install/config.example.json if you have no config yet (it never overwrites one);
  • adds a marked block (>>> voice-computer … <<< voice-computer) to ~/.config/hypr/bindings.lua and a Voice entry to the Omarchy menu (~/.config/omarchy/extensions/omarchy-menu.jsonc);
  • copies the bar plugin to ~/.config/omarchy/plugins/ and puts it on the bar after the audio widget;
  • points voxtype (if installed) at your STT endpoint, turns its own hotkey off (Omarchy's F9 bind drives it) and adds a drop-in for voxtype.service.

Before it changes a file it backs it up beside the original as FILE.bak.voice-computer.<time>: bindings.lua, the menu file, shell.json and config.json. voxtype's config.toml is backed up once, at the first install, so that backup is your own config from before (an empty one: you had none). If bindings.lua already binds the talk or confirm key, or SHIFT or SUPER + SHIFT with the talk key, outside the block (an o.bind("F7", …) line), it stops and changes nothing. It doesn't look at binds in other files, or at other spellings of the key.

Then edit the config for your endpoints and restart:

omarchy-launch-editor ~/.config/voice-computer/config.json   # or Voice → Edit settings in the menu
systemctl --user restart voice-computer
vc status

F9 dictation reads stt from the config when the installer runs. After you change stt, run install/install.sh again so voxtype follows.

Trying it without any models

go run ./cmd/fakevoice starts a fake backend and prints a config for it. It hears every turn as the same words and answers with a second of silence per sentence, so you can try the keys and the bar.

4. Keys

Key What it does
F7 (hold) Talk; let go and the computer answers. 60 s at most.
F7 (tap) Stop the answer, or say no to an open confirm
SUPER + ALT + F7 Confirm the open confirm; it confirms on release, once
F9 (hold) Dictation, typed at the cursor (Omarchy's own bind)
SHIFT + F7 Repeat the last agent reply (only with agent replies)
SUPER + SHIFT + F7 Agent replies on or off

To use other keys, run the installer with them. The confirm key must be modifiers plus the talk key, and the agent-reply keys follow the talk key. The installer rewrites its block in bindings.lua and keeps the keys in the config (talk_key, confirm_key), so the prompts and the bar name them and later runs keep them:

VC_TALK_KEY="F8" VC_CONFIRM_KEY="SUPER + ALT + F8" install/install.sh

Don't edit the marked block by hand: the next install puts it back. Bind anything else outside it.

5. Configuration

~/.config/voice-computer/config.json. Missing keys keep their defaults:

Key Default What it is
backend openai openai (the three endpoints), or realtime: a Realtime-style websocket at {realtime.url}/v1/realtime?model=… answers (text in, audio out), and stt/tts are still used. Not tried against OpenAI's own Realtime API.
stt, chat, tts, realtime see above {"url", "model", "key_file"}; key_file empty means no key
voice af_heart the TTS voice
chat_extra none extra fields for every chat request, e.g. {"temperature": 0.2} or {"chat_template_kwargs": {"enable_thinking": false}}
tts_extra none extra fields for every TTS request, e.g. {"speed": 1.1}
instructions built in the brain's standing instructions
max_output_tokens 1000 the brain's answer length, sent as max_tokens; 0 leaves it out (for models that want max_completion_tokens in chat_extra)
talk_key, confirm_key F7, SUPER + ALT + F7 the keys the prompts and the bar name (set by the installer)
tap_ms 300 a press shorter than this is a tap
max_turn_s 60 the mic closes after this
idle_close_s 120 the session closes after this long idle; the last turns are replayed into the next one
overlay_hide_s 8 the overlay hides this long after an answer
history 20 turns kept in memory and replayed into a new session
card_timeout_s 30 an unanswered confirm is a no after this
notes_file ~/Documents/notes/inbox.md where "note that …" writes
terminals common terminals window classes never closed
reply_spaces none agent replies: the Shepherdr spaces whose coordinators' replies are spoken; none means off
reply_voice the computer's the TTS voice for agent replies
reply_idle_s, reply_poll_ms 30, 2000 how long you must be idle before a reply to news plays; how often Shepherdr is asked
shepherdr, shepherdr_credential shepherdr, ~/.shepherdr/clients/vcd.credential.json the command and vcd's own credential

6. The bar

The plugin shows a mic glyph after the audio widget:

  • dim mic: ready; M muted (speech off, the mic still works)
  • filled mic: listening, … thinking, speaker: speaking, • needs you (a confirm is open)
  • crossed-out mic: off; hover or click to see why

Click it for the last turns, the model answering and the mute switch. Middle-click cancels. Its settings in Omarchy's bar settings include the vc command it runs.

7. Troubleshooting

  • The bar says Off. Hover it, or run vc status, to see why: an endpoint can't be reached, a key file is missing, or a key was refused. Check each URL with curl {url}/v1/models.
  • Nothing happens on F7. Is vc running (systemctl --user status voice-computer)? Does hyprctl binds | grep -A3 F7 show the bind? Another app may grab F7 in its own submap.
  • It never hears anything. Check the default source with wpctl status, and record a test clip with parecord --rate=16000 --channels=1 /tmp/t.wav.
  • The brain never acts. The chat server must support tool calls (llama.cpp needs --jinja). VC_LIVE=1 go test ./internal/intent -run TestPhrasesLive -v runs the labelled phrase set against your backend.
  • Slow answers. vc latency shows p50/p90 for each step. journalctl --user -u voice-computer -f shows each turn's timings (never words).
  • F9 types nothing. journalctl --user -u voxtype -f. vcd sends a notification when a clip is lost, and turns voxtype to local Whisper while the STT endpoint is down.

8. Uninstall

install/uninstall.sh

This removes the service, vc, the bar plugin, its blocks in bindings.lua and the menu (after a backup) and voxtype's drop-in, and sets voxtype back to local Whisper. Its other settings (the VAD, the endpoint, its hotkey off) stay. It keeps ~/.config/voice-computer/ and the backups. To get voxtype's config exactly as it was before the first install, copy back the oldest ~/.config/voxtype/config.toml.bak.voice-computer.*.

9. Optional: agent replies (Shepherdr)

If you run coding agents under Shepherdr, the voice computer can speak what a space's coordinator writes to you in its chat. It stays off until you name the spaces in the config:

{ "reply_spaces": ["home", "my-project"], "reply_voice": "am_adam" }

Then run install/install.sh again. It issues vcd its own credential to read those chats (shepherdr client issue vcd, saved in ~/.shepherdr/clients/vcd.credential.json). vcd asks Shepherdr every 2 s whether a coordinator is working. When its turn ends, vcd speaks the newest reply:

  • Plain and short: no markdown, code, paths, links, IDs, hashes or log lines, and at most the first two short sentences. The overlay shows it under the space's name.
  • Never over you: a reply waits while you hold the talk key, while a turn is being answered, while the computer speaks, or while you dictate, and plays after that. A tap of the talk key drops it.
  • News waits: a reply to anything other than your own last message (news, a heartbeat) waits until you have been idle for reply_idle_s.
  • Quiet: say "be quiet" (or press SUPER + SHIFT + F7, or use the menu) to mute replies, and "talk to me" to hear them again. SHIFT + F7 repeats the last one.
  • Privacy: the reply's text goes to your TTS endpoint and nowhere else. It never reaches the brain, and its words are never logged.

Handing work to agents by voice is planned for a later release.