Skip to content

Code Command Grammar — Voice-Driven Code Editing Actions

Description

A rule-based command classification module intercepts transcribed phrases before injection and classifies them as either raw dictation or one of five structured editing intents: NAVIGATE, EDIT, REFACTOR, TERMINAL, or DICTATE (the default pass-through). Classification uses approximately 100 regex patterns augmented with stem normalization (no GPU, no model inference). When a command intent is detected, the daemon emits a command_detected JSON-RPC event over the existing IPC socket in addition to — or instead of — raw text injection. Editor plugins and shell integrations subscribe to this IPC stream and translate structured intents into native API calls. The module is entirely optional and additive; DICTATE is always the default fallback, so any unrecognized phrase is injected as plain text.

User Pain

Developers using voice dictation today face a sharp boundary: voice can type text but cannot drive the editor. Actions like "go to line 42", "delete the last three words", "rename this function", or "run the tests" all require switching to keyboard or mouse mid-dictation. This breaks the voice-native workflow that tools like Talon and Serenade offer [EVIDENCE src-007] [EVIDENCE src-006]. YazSes users who came from Talon specifically report this as the top missing feature. The pain is especially acute for users with RSI or motor disabilities who adopted voice dictation specifically to reduce keyboard use — they are forced back to the keyboard for every non-text action.

Proposed Solution

Module: src/yazses/commands/code.py

Intent taxonomy:

Intent Example phrases Action
NAVIGATE "go to line 42", "jump to function main", "open file config dot py" Emit event; plugin dispatches editor API
EDIT "delete last three words", "undo", "copy line", "select all", "paste" Emit keyboard shortcut OR event
REFACTOR "rename this to snake case", "extract function", "move to new file" Emit event; plugin uses LSP rename
TERMINAL "run tests", "git status", "make build" Emit event; shell integration types command
DICTATE everything else Pass through to text injector unchanged

Classification pipeline:

  1. Pre-filter: If transcript contains no known command keywords (compiled from a keyword index), skip classification entirely and return DICTATE. This keeps the hot path at <1ms for pure dictation.

  2. Regex matcher (commands/rules/code_rules.py): 100 compiled re.Pattern objects, grouped by intent. Each rule includes: pattern, intent, parameter extraction groups, and a confidence weight (0.0–1.0). Patterns use named groups: (?P<line_number>\d+), (?P<symbol_name>\w[\w\s]+).

  3. Stem normalizer (commands/stemmer.py): Applies Porter stemming via nltk.stem.PorterStemmer (already a transitive dep via faster-whisper ecosystem) before matching. Maps "jumping" → "jump", "deleting" → "delet". Word-level, O(N words) with N typically <15.

  4. Disambiguation: If multiple rules match with confidence within 0.2 of each other, and LLM router (cap-008) is enabled, route to LLM for disambiguation. Otherwise, take highest confidence match.

  5. IPC event structure:

    {
      "jsonrpc": "2.0",
      "method": "command_detected",
      "params": {
        "intent": "navigate",
        "action": "go_to_line",
        "params": {"line": 42},
        "raw_transcript": "go to line 42",
        "confidence": 0.97
      }
    }
    

Editor integrations (initial set): - VS Code extension (extensions/vscode/): Subscribes to IPC, maps navigate/go_to_linevscode.commands.executeCommand('revealLine', ...), edit/undovscode.commands.executeCommand('undo'), etc. - Neovim plugin (extensions/nvim/yazses.lua): Connects to UNIX socket, dispatches via vim.cmd. - Shell integration (extensions/shell/yazses_shell.sh): Reads terminal events and writes to the active terminal's input using tmux send-keys or xdotool type.

Config:

[commands]
enabled = true
mode = "code"                  # "code" | "prose" | "gaming" | "custom"
custom_rules_file = "~/.config/yazses/rules.toml"
inject_on_no_match = true      # Always fall back to DICTATE

Feasibility Notes

Complexity: Medium. Rule authoring is the bulk of the work; the classification engine itself is straightforward. The VS Code extension requires TypeScript knowledge but follows a standard template. The main engineering risk is false positive rates on DICTATE text that happens to match command patterns (e.g., "go to the store" matching NAVIGATE).

Dependencies: nltk for stemming (small, no GPU). No new major dependencies. Editor extensions are optional and developed independently.

Risks: - False positive rate on natural dictation: mitigate with a high confidence threshold (≥0.85) and a configurable per-intent sensitivity setting. - Neovim and VS Code have different async models; ensure IPC listener does not block editor UI thread. - Custom rule files in TOML require a well-documented schema; provide a JSON Schema + example file. - "rename this to snake case" requires LSP access on the remote side — gate behind [commands.lsp_enabled] flag.

Success Metrics

  • Command classification latency (pre-filter fast path): <1ms for DICTATE.
  • Command classification latency (full path): <10ms on a 4-core CPU.
  • False positive rate on a 500-sentence natural-speech dictation corpus: <0.5%.
  • True positive rate on a 200-command test set (manually labelled): >95%.
  • VS Code extension round-trip from speech release to editor action: <1.2s (including ASR).
  • User activation rate: ≥30% of YazSes users enable commands.enabled = true within 30 days of release.

Evidence

  • [EVIDENCE src-006] Serenade's intent dispatch architecture — structured JSON events over IPC as the integration boundary between ASR and editor.
  • [EVIDENCE src-007] Talon's command grammar approach — regex + rule-based classification without GPU, demonstrating production viability.
  • [EVIDENCE src-001] Word-level timestamps assist in parameter extraction (e.g., isolating the symbol name in "rename this to snake case").