“post to Slack that I’ll be five minutes late” → posts “I’ll be five minutes late” to your Slack webhook “add a reminder to buy milk” → runs your Add to Reminders macOS Shortcut with “buy milk”
Install
How it works
Detection runs on the server’safterTranscribe hook, in three stages:
- Prefilter — a cheap, deterministic phrase match gates everything. If your speech contains no trigger phrase, nothing else runs and the transcript is dictated normally. No LLM call, no added latency.
- Agent — when a trigger matches, a multi-step tool-calling agent (using the LLM you’ve already configured for cleanup) decides whether it’s really a command and extracts the payload — the part of your speech that isn’t the trigger words.
- Action — the command fires and the utterance is consumed (via
api.control.consume()): the rest of the pipeline is skipped and no text is delivered to the focused app.
If no LLM is available, detection falls back to a deterministic match (the longest matching trigger wins) so commands still work — just without the smarter intent check and payload extraction.
api.llm capability, so there’s no separate provider or key to set up. Signed-in Freestyle Cloud users get this too — the agent runs on Freestyle Cloud’s managed LLM, with no local model required.
Action types
UI page
The plugin adds a Voice Commands page to the app sidebar (shown once the plugin is enabled). From there you can:- Add a command with a name, one or more trigger phrases, a description, and an action.
- Edit or delete existing commands, and enable/disable them without deleting.
window.freestyle host bridge to the plugin’s own CRUD endpoint and persisted with plugin storage, so it survives restarts and takes effect on the next dictation.
Build from source
pkgroll --minify (server-side plugin code, bundling the AI SDK) followed by vite build (UI page).
Source
plugins/voice-commands/ in the monorepo.