Replace app icons with new Clawdbot branding (lobster-in-phone-booth design) across iOS, Android, and macOS.
Changes:
- iOS: Updated all 14 icon sizes in AppIcon.appiconset (20px to 1024px)
- Android: Updated launcher icons for all density buckets (mdpi to xxxhdpi)
- macOS: Updated Icon.icon bundle and regenerated Clawdbot.icns
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
The macOS app was crashing in two scenarios:
1. Bundle.module crash (fixes#213): When the first tool event arrived,
ToolDisplayRegistry tried to load config via ClawdbotKitResources.bundle,
which used Bundle.module directly. In packaged apps, Bundle.module
couldn't find the resource bundle at the expected path, causing a
fatal assertion failure after ~40-80 minutes of runtime.
2. dyld crash (fixes#417): Swift 6.2 requires libswiftCompatibilitySpan.dylib
but SwiftPM doesn't bundle it automatically, causing immediate crash on
launch with "Library not loaded" error.
Changes:
- ClawdbotKitResources.swift: Replace direct Bundle.module access with a
safe locator that checks multiple paths and falls back gracefully
- package-mac-app.sh: Copy ClawdbotKit_ClawdbotKit.bundle to Resources
- package-mac-app.sh: Copy libswiftCompatibilitySpan.dylib from Xcode
toolchain to Frameworks
Tested on macOS 26.2 with Swift 6.2 - app launches and runs without crashes.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Keep the chosen mic label visible when it disconnects and show a disconnected hint while falling back to system default.
- Avoid clearing the preferred mic on device changes so it auto-restores when available.
- Add audio input change and default-input logs in voice wake runtime/tester/meter to debug routing.
Why: Start Test is a local verification tool, but it was forwarding transcripts to the gateway/chat, which confused users and made tests look like real commands.
What: stop forwarding from VoiceWakeTester and clarify in docs that the tester does not send to the gateway.
Why: voice wake tests often delivered partial/final transcripts without reliable word timings, so trigger matching failed, timeouts overwrote detections, and test runs/mic capture kept running after UI changes.
What: add text-only/prefix fallback and silence-based detection in the test flow, stop/clean up any prior test, cancel timeout on detection/stop, and tear down meter/test when the Voice Wake tab is inactive. Runtime detection now falls back on final text-only matches when timing is missing. UI state now reflects finalizing and prevents hanging tests.
CLAuthorizationStatus.authorizedWhenInUse only exists on iOS. On macOS,
location services only support .authorizedAlways. This was causing
compilation warnings and potentially incorrect behavior.
Fixes:
- GeneralSettings.swift: Remove authorizedWhenInUse check
- PermissionManager.swift: Update ensureLocation and status methods
- MacNodeRuntime.swift: Update location permission check
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Add sms.send command to allow sending text messages via the paired Android device.
Changes:
- Add SmsManager class to handle SMS sending via Android SmsManager API
- Add ClawdisSmsCommand enum and Sms capability to protocol constants
- Wire sms.send command into NodeRuntime invoke handler
- Add SEND_SMS permission to AndroidManifest.xml
- Advertise sms capability when SEND_SMS permission is granted
The SMS capability is only advertised when the user has granted SEND_SMS
permission. Messages longer than 160 chars are automatically split into
multipart messages.
Prepares the macOS app for Swift 6 strict concurrency mode by:
1. Adding Sendable conformance to WizardNextResult, WizardStartResult,
and WizardStatusResult in GatewayModels.swift
2. Adding AnyCodable bridging helpers in OnboardingWizard.swift to
handle type conflicts between ClawdisProtocol and local module
3. Making CLLocationManagerDelegate methods nonisolated in:
- MacNodeLocationService.swift
- PermissionManager.swift (LocationPermissionRequester)
Using Task { @MainActor in } pattern to safely access MainActor
state from nonisolated protocol requirements.
These changes are forward-compatible and don't affect behavior on
current Swift versions.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Previously, if the gateway was unreachable (wrong IP, offline, etc.),
the Android app would crash with an unhandled socket exception.
Changes:
- Wrap socket.connect() in try/catch to handle connection failures
- Return PairResult with error message instead of crashing
- Display actual error message in status text instead of generic 'pairing required'
This gives users useful feedback like 'Connection refused' or
'Network is unreachable' instead of a crash.
- Add 'camera' case to Capability enum
- Add UI strings (title, subtitle, icon) in PermissionsSettings
- Add ensureCamera() and camera status check in PermissionManager
- Add CameraPermissionHelper for opening System Settings
🦞 Clawd's first code contribution!
- Add CLAWDIS_GATEWAY_PASSWORD to launchd plist environment
- Read password from gateway.remote.password config in client
- Fix Swift 6.2 sending parameter violations in config save functions
- Add password parameter to GatewayConnection.Config type
- GatewayChannel now sends password in connect auth params
- GatewayEndpointStore and GatewayLaunchAgentManager read password from config
- CLI gateway client reads password from remote config and env
GatewayChannel now sends both 'token' and 'password' fields in the auth
payload to support both authentication modes. Gateway checks the field
matching its auth.mode configuration ('token' or 'password').
Also adds config file password fallback for remote mode, allowing
gateway password to be configured in ~/.clawdis/clawdis.json without
requiring environment variables.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>