# macOS dictation

## Version 1.4.0: live textbox mode and gesture choice

For Right Option toggle plus an independent hold key, after preparing a local speech model:

```sh
olenji hotkey set right_alt --activation toggle --binding hold:ctrl+alt+space --delivery insert --delivery-timing live --feedback --json
```

Hold records until release. Toggle records after one press/release and finishes on the next press. In **Settings → Dictation keys and delivery → Set up shortcut**, choose **Primary gesture** and **Add another key mapping** for up to eight additional keys (nine total); duplicates and overlapping physical definitions are refused (for example, `alt+a` and `right_alt+a`). **Use Right Option + live typing + popup** sets only the primary key to Right Option, insertion output, live timing and native feedback. It keeps the existing gesture and additional mappings; choose those separately. Select **Prepare setup command**, then apply the resulting command through your local agent or terminal. This behavior is included in 1.4.0; discover the connected version before configuring it. Both gestures share one capture owner and a bounded recording deadline. Faults interrupt toggled capture even when its key is up.

Live delivery shows cumulative provisional words inside the original writable textbox as recognition produces them, then corrects/finalizes them without duplication. Keep the original field and caret. The native helper privately reads a bounded full field value (up to 200,000 UTF-16 units), verifies it and the original app/field/caret before replacing only its own draft. Observed typing, selection, focus or security/permission changes stop further updates. Native Accessibility has no atomic compare-and-replace against a human edit racing the setter. Cancellation may leave provisional words visible; inspect them before retrying. No clipboard, Enter/Send, retarget or uncertain replay is used.

Use `--delivery-timing final` for the draft-free final-only contract below. That remains the default, as does transcript-only output when insertion is not explicitly selected. Linux supports final-only insertion; Windows currently saves transcripts only. The macOS popup reports connected microphone activity, processing and results without taking focus or displaying dictated text. Buffered model inference means words may arrive in chunks rather than immediately. Native acceptance of this new path is recorded separately.

## Final-only insertion and platform checks

**Version 1.4.0, prepared 2 November 2026:** physical-key setup, configurable gestures, live textbox delivery, native feedback and Secure Input recovery belong to this version. Publication is tracked separately from the source/build review. The owner manages native Mac testing. A popup-only probe covers the indicator, not physical keys, microphone input, permissions or actual field insertion.

Ask your local AI agent: **“Get Olenji and use my chosen shortcut to write what I say into the focused field. Don’t send it.”**

The agent prepares an installed speech model, configures the shortcut with explicit `--delivery insert` or MCP `output: "insert"`, and checks the returned status. Microphone recording and model setup remain separate from shortcut registration. Use a supported standard CPython installation; no Apple source build is required for portable Faster Whisper dictation.

## Permission and first use

Allow the app or executable **macOS identifies** in System Settings → Privacy & Security:

- **Microphone** for recording.
- **Input Monitoring** for the global shortcut.
- **Accessibility** for insertion into another app.

macOS can attribute a command and its helper to the launching app or terminal. Do not assume the entry is always named Olenji, Python, Codex or Terminal. A failed preflight does not automatically display an approval prompt. After granting access, re-enable the binding and check its actual status. Olenji does not grant permissions itself, reset TCC or require Full Disk Access.

Focus an ordinary editable field and clear any selection. For Hold, keep the key down while speaking and release to finish. For Toggle, press/release to start and press again to finish. The transcript stays in Olenji. Final-only supported-field delivery inserts once after clean recognition; live mode updates its own draft while speaking. Neither mode presses Enter or sends the message.

## Short recovery instructions

- **Secure keyboard entry:** leave the protected field/state. The enabled binding stays visibly suspended while Olenji makes up to six fresh handshake attempts after 1, 2, 4, 8, 16 and 30 seconds. Release the trigger fully, then deliberately press again after Ready. If recovery is exhausted, enable the binding again. No recording or insertion resumes automatically, and Olenji never disables secure input.
- **Keyboard layout changed:** reconfigure the chosen shortcut. A stale physical key is not reused silently.
- **Unsupported field:** read or copy the saved transcript yourself, or use a supported ordinary field. Chrome/Electron accessibility-tree support depends on that application; OS name alone does not establish it.
- **Interrupted or uncertain delivery:** inspect the field and saved transcript before repeating. Interrupted final-only recordings skip insertion. Live mode may leave its latest provisional span for review. A write that may already have happened is never replayed automatically.

## Implementation and evidence

For final-only delivery, the native helper uses Apple’s public `NSWorkspace.frontmostApplication` to identify the app receiving keyboard events and refreshes the documented cached lifecycle state before rechecking its retained identity. It creates that app’s Accessibility reference directly. It uses Apple’s selected-text accessibility setter only when the actual ordinary field explicitly permits that setter. A reported disabled state is refused. Native text areas such as TextEdit may lack a separate enabled attribute: only the attribute-unsupported result is accepted there, while positive setter writability remains mandatory. This does not treat missing metadata as an enabled-state observation; no-value, malformed, denied and failed responses still stop delivery. It validates typed empty UTF-16 ranges, secure subroles, focused application/element identity and their PIDs, then confirms the newly inserted span and caret. It reads no surrounding draft, uses no clipboard and never replaces the whole field value. Cross-process accessibility has no atomic compare-and-insert transaction, so uncertain results remain explicit.

The shortcut listener is listen-only and sends only the chosen action's edges. `right_alt` selects physical Right Option alone; `left_alt` is Left Option and `alt+right` is Option+Right Arrow. Either-side modifiers, modifier chords, F1–F20, native Fn and modified navigation/numpad keys are supported where the keyboard delivers them. Ordinary letter/digit chords require a modifier and follow the current layout; non-ASCII characters are refused. Record the chord again after a layout change. Media and mouse buttons are unsupported. Normal Option shortcuts still reach the focused app and can also activate a modifier-only binding. Extra modifiers or the opposite side interrupt a sided physical hold, and listener interruption also cancels an active toggle recording. Repeat, preheld and interrupted input requires a full release before a new press. Layout-dependent letters, remappers, external/virtual keyboards and physical Fn/media settings require a real device check.

Settings → Dictation keys and delivery offers a focused physical-key recorder, selected shortcut model/language, named input, delivery and feedback choices. It prepares a local setup command; the paired browser cannot directly enable monitoring. Explicit `--input-device` saves an enumerated microphone ID and observed-name guard. Optional `--input-device-name` verifies the name seen during enumeration before accepting the ID; the browser command includes this check. A missing or changed ID fails instead of silently switching from an external microphone to the built-in input. Omission follows the OS default.

**Show native desktop feedback** is enabled unless previously disabled. This optional feedback is a separate nonactivating, click-through AppKit panel with recording/level/elapsed, processing and delivery states. It displays no dictated text, surrounding draft or credentials, has no clipboard/Send/activation action, and places itself on the display containing the pointer. `--no-feedback` turns it off. Unsupported/stale feedback is reported separately from capture. Recording means a connected owned microphone, not just a registered listener. Feedback cannot replace checking the actual target and saved transcript. Native focus, accessibility, Spaces/fullscreen, display edges/scaling, sleep/wake and reduced-motion checks remain pending for this new implementation.

Default output remains a saved transcript. Explicit final-only insertion retains the original field and uses its current empty caret at delivery; it does not freeze the entire draft/caret for the utterance. Keep the target focused and inspect uncertain delivery before retrying. New feedback, physical-key and recovery behavior is covered by controlled Linux API/protocol tests; prior native TextEdit/F20 checks certify only their older exact artifacts.

[Apple foreground application](https://developer.apple.com/documentation/appkit/nsworkspace/frontmostapplication), [running-application lifetime](https://developer.apple.com/documentation/appkit/nsrunningapplication), [selected-text setter](https://developer.apple.com/documentation/appkit/nsaccessibilityprotocol/setaccessibilityselectedtext(_:)), [attribute writability](https://developer.apple.com/documentation/applicationservices/1459972-axuielementisattributesettable), [UTF-16 range queries](https://developer.apple.com/documentation/applicationservices/kaxstringforrangeparameterizedattribute), [microphone authorization](https://developer.apple.com/documentation/bundleresources/requesting-authorization-for-media-capture-on-macos) and [Input Monitoring](https://support.apple.com/en-ie/guide/mac-help/mchl4cedafb6/mac) are the primary contracts. The [native handoff](/docs/1.4.0/source/#source-122e0644ea856ce65c28) explains the automated owned TextEdit and shortcut-registration checks. Exact execution reports distinguish research, Ubuntu regressions, native Apple framework/field behavior and publication.
