Documentation

Actions YAML reference

Schema, placeholders, action types, and the shell allowlist.

Every voice action is one YAML file in ~/Library/Application Support/com.techguider.wisspa/actions/. The folder is file-watched: save a file and the registry reloads — no restart. The 14 defaults are seeded on first launch; browse them on the registry page.

Full schema

id: screenshot                      # unique id (filename should match)
name: "Interactive Screenshot to Clipboard"
description: "Triggers macOS interactive screenshot, copies result to clipboard"
triggers:                           # spoken phrases, matched exactly then fuzzily
  - "screenshot"
  - "take a screenshot"
  - "screen grab"
type: shell                         # shell | applescript | open_url | open_app | keystroke
command: "screencapture -i -c"      # what runs — meaning depends on type
working_dir: null                   # optional, shell only
requires_permissions:               # checked before firing, with a clear error
  - screen_recording
destructive: false                  # true = flagged as destructive in the UI
success_feedback: "Screenshot captured to clipboard"
failure_feedback: "Screenshot failed"
enabled: true                       # false = loaded but never matches

Matching rules

Your transcript is matched against every enabled action's triggers:

  1. Exact match first — longest trigger wins, so "search github for X" beats "search".
  2. Fuzzy pass — small Levenshtein distance (≤ 3) to tolerate transcription wobbles. Deliberately conservative: a near-miss doesn't fire, it just tells you nothing matched.

Action types

type command is… Example
shell a shell command screencapture -i -c
applescript AppleScript source tell application "System Events" to key code 123
open_url a URL to open in the default browser https://github.com/search?q={query}
open_app an app name to launch/focus Calendar
keystroke a key combo to simulate cmd+v

Placeholders

Filled at the moment you speak, before the command runs:

  • {query} — everything you said after the trigger phrase ("search github for tauri" → tauri). Percent-encoded automatically in open_url.
  • {clipboard} — current clipboard text.
  • {selected_text} — the text you had selected.
  • {active_app} — the frontmost app's name.

The shell allowlist

Shell commands are validated at load and rejected if they contain sudo, rm -rf, dd, or piped curl/wget execution. A rejected action shows up as invalid in Settings → Actions with the reason — the rest of the registry keeps working. Voice-activated rm -rf / is a genre of disaster we'd rather not enable.

Permissions and destructive flags

  • requires_permissions — declare accessibility, screen_recording, automation, or microphone. Wisspa checks the grant before firing and tells you exactly which one is missing instead of failing silently.
  • destructive: true — for anything that closes windows, kills processes, or locks things. It doesn't add a prompt; it marks the action clearly in the UI so you know which ones bite.

An example of your own

"Mute my mic" as a new file mute_audio.yaml:

id: mute_audio
name: "Mute system audio"
description: "Sets output volume to zero"
triggers:
  - "mute audio"
  - "mute my audio"
type: applescript
command: "set volume with output muted"
requires_permissions:
  - automation
destructive: false
success_feedback: "Audio muted"
failure_feedback: "Couldn't mute audio"
enabled: true

Save it in the actions folder and say "mute audio" — it's live that second.