openclaw/apps/macos
Phillip Hampton 350fe63bbf
feat(macos): Voice Wake option to trigger Talk Mode (#58490)
* feat(macos): add "Trigger Talk Mode" option to Voice Wake settings

When enabled, detecting a wake phrase activates Talk Mode (full voice
conversation: STT -> LLM -> TTS playback) instead of sending a text
message to the chat. Enables hands-free voice assistant UX.

Implementation:
- Constants.swift: new `openclaw.voiceWakeTriggersTalkMode` defaults key
- AppState.swift: new property with UserDefaults persistence + runtime
  refresh on change so the toggle takes effect immediately
- VoiceWakeSettings.swift: "Trigger Talk Mode" toggle under Voice Wake,
  disabled when Voice Wake is off
- VoiceWakeRuntime.swift: `beginCapture` checks `triggersTalkMode` and
  activates Talk Mode directly, skipping the capture/overlay/forward
  flow. Pauses the wake listener via `pauseForPushToTalk()` to prevent
  two audio pipelines competing on the mic.
- TalkModeController.swift: resumes voice wake listener when Talk Mode
  exits by calling `VoiceWakeRuntime.refresh`, mirroring PTT teardown.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: address review feedback

- TalkModeController: move VoiceWakeRuntime.refresh() after
  TalkModeRuntime.setEnabled(false) completes, preventing mic
  contention race where wake listener restarts before Talk Mode
  finishes tearing down its audio engine (P1)
- VoiceWakeRuntime: remove redundant haltRecognitionPipeline()
  before pauseForPushToTalk() which already calls it via stop() (P2)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: resume wake listener based on enabled state, not toggle value

Check swabbleEnabled instead of voiceWakeTriggersTalkMode when deciding
whether to resume the wake listener after Talk Mode exits. This ensures
the paused listener resumes even if the user toggled "Trigger Talk Mode"
off during an active session. (P2)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: play trigger chime on Talk Mode activation + send chime before TTS

- VoiceWakeRuntime: play the configured trigger chime in the
  triggersTalkMode branch before pausing the wake listener. The early
  return was skipping the chime that plays in the normal capture flow.
- TalkModeRuntime: play the Voice Wake "send" chime before TTS playback
  starts, giving audible feedback that the AI is about to respond. Talk
  Mode never used this chime despite it being configurable in settings.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: move send chime to transcript finalization (on send, not on reply)

The send chime now plays when the user's speech is finalized and about
to be sent to the AI, not when the TTS response starts. This matches
the semantics of "send sound" -- it confirms your input was captured.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 21:09:36 -04:00
..
Icon.icon
Sources feat(macos): Voice Wake option to trigger Talk Mode (#58490) 2026-03-31 21:09:36 -04:00
Tests/OpenClawIPCTests macOS: use MagicDNS for wide-area gateway discovery (#57833) 2026-03-31 10:04:11 +01:00
Package.resolved build: update macOS package dependencies 2026-03-28 04:53:02 +00:00
Package.swift build: update macOS package dependencies 2026-03-28 04:53:02 +00:00
README.md

README.md

OpenClaw macOS app (dev + signing)

Quick dev run

# from repo root
scripts/restart-mac.sh

Options:

scripts/restart-mac.sh --no-sign   # fastest dev; ad-hoc signing (TCC permissions do not stick)
scripts/restart-mac.sh --sign      # force code signing (requires cert)

Packaging flow

scripts/package-mac-app.sh

Creates dist/OpenClaw.app and signs it via scripts/codesign-mac-app.sh.

Signing behavior

Auto-selects identity (first match):

  1. Developer ID Application
  2. Apple Distribution
  3. Apple Development
  4. first available identity

If none found:

  • errors by default
  • set ALLOW_ADHOC_SIGNING=1 or SIGN_IDENTITY="-" to ad-hoc sign

Team ID audit (Sparkle mismatch guard)

After signing, we read the app bundle Team ID and compare every Mach-O inside the app. If any embedded binary has a different Team ID, signing fails.

Skip the audit:

SKIP_TEAM_ID_CHECK=1 scripts/package-mac-app.sh

Library validation workaround (dev only)

If Sparkle Team ID mismatch blocks loading (common with Apple Development certs), opt in:

DISABLE_LIBRARY_VALIDATION=1 scripts/package-mac-app.sh

This adds com.apple.security.cs.disable-library-validation to app entitlements. Use for local dev only; keep off for release builds.

Useful env flags

  • SIGN_IDENTITY="Apple Development: Your Name (TEAMID)"
  • ALLOW_ADHOC_SIGNING=1 (ad-hoc, TCC permissions do not persist)
  • CODESIGN_TIMESTAMP=off (offline debug)
  • DISABLE_LIBRARY_VALIDATION=1 (dev-only Sparkle workaround)
  • SKIP_TEAM_ID_CHECK=1 (bypass audit)