Skip to content

feat: restore dictation on macOS 26+ via subprocess pynput isolation#174

Draft
isair wants to merge 2 commits intodevelopfrom
claude/distracted-agnesi
Draft

feat: restore dictation on macOS 26+ via subprocess pynput isolation#174
isair wants to merge 2 commits intodevelopfrom
claude/distracted-agnesi

Conversation

@isair
Copy link
Copy Markdown
Owner

@isair isair commented Apr 10, 2026

Summary

  • Spawns a dedicated helper subprocess (_hotkey_helper.py) whose main thread runs pynput's keyboard listener, satisfying macOS Tahoe's TSM main-dispatch-queue requirement
  • The helper communicates semantic events (hotkey_press, hotkey_release, escape) to the parent via JSON-line IPC on stdout
  • The parent retains all recording state, double-tap detection, and hands-free mode logic — no behaviour change for the user
  • Falls back gracefully (dictation disabled) if the subprocess helper fails to start
  • Shared hotkey utilities extracted into _hotkey_shared.py to avoid code duplication between engine and helper
  • README updated to reflect that dictation is now available on macOS 26+

Test plan

  • All 61 dictation tests pass (43 existing + 18 new)
  • TestSubprocessHelperEvents — verifies _on_helper_event correctly maps events to recording/hands-free/double-tap logic
  • TestHotkeySharedModule — verifies hotkey parsing, key matching, and modifier tracking in the shared module
  • TestEngineLifecycle.test_start_uses_subprocess_on_macos_26 — subprocess path used on macOS 26+
  • TestEngineLifecycle.test_start_fails_gracefully_on_macos_26_if_helper_fails — graceful degradation
  • Manual test on macOS 26+ (Tahoe) to confirm dictation works end-to-end

Closes #172

🤖 Generated with Claude Code

@isair isair marked this pull request as draft April 12, 2026 18:52
isair and others added 2 commits April 12, 2026 23:27
macOS Tahoe enforces TSM calls on the main dispatch queue, crashing
pynput's background-thread CGEventTap. Instead of disabling dictation
entirely, spawn a dedicated helper subprocess (_hotkey_helper.py) whose
main thread runs the pynput listener — satisfying TSM requirements.
The parent process receives semantic events (hotkey_press/release,
escape) via JSON-line IPC and retains all recording, double-tap, and
hands-free logic.

Closes #172

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Move duplicated hotkey-matching code (_MODIFIER_MAP, parse_hotkey,
  normalise_key, key_matches, all_modifiers_held) into a shared
  _hotkey_shared.py module, imported by both the engine and helper
- Update README to reflect that dictation now works on macOS 26+
- Rename test class to TestHotkeySharedModule

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@isair isair force-pushed the claude/distracted-agnesi branch from a753306 to c8e66da Compare April 12, 2026 22:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant