When the relay is running, `warelay send` and `warelay heartbeat` now
communicate via Unix socket IPC (~/.warelay/relay.sock) to send messages
through the relay's existing WhatsApp connection.
Previously, these commands created new Baileys sockets that wrote to the
same auth state files, corrupting the Signal session ratchet and causing
the relay's subsequent sends to fail silently.
Changes:
- Add src/web/ipc.ts with Unix socket server/client
- Relay starts IPC server after connecting
- send command tries IPC first, falls back to direct
- heartbeat uses sendWithIpcFallback helper
- inbound.ts exposes sendMessage on listener object
- Messages sent via IPC are added to echo detection set
The test 'falls back to most recent session when no to is provided' was
using resolveStorePath() which returns the real ~/.warelay/sessions.json.
This overwrote production session data with test values, causing session
fragmentation issues.
Changed to use a temp directory like other tests.
Bug fixes:
- Empty result field handling: Changed truthy check to explicit type
check (`typeof parsed?.text === "string"`) in command-reply.ts.
Previously, Claude CLI returning `result: ""` would cause raw JSON
to be sent to WhatsApp.
- Response prefix on heartbeat: Apply `responsePrefix` to heartbeat
alert messages in runReplyHeartbeat, matching behavior of regular
message handler.
Changed from 10 to 30 minutes to avoid false positives when
heartbeatMinutes is set to 10. The watchdog should be significantly
longer than the heartbeat interval to account for:
- Network latency
- Slow command responses
- Brief connection hiccups
With heartbeatMinutes=10, a 30-minute watchdog gives 3x buffer before
triggering auto-restart.
Tests were picking up real ~/.warelay/warelay.json with emojis and
prefixes (like "🦞"), causing test assertions to fail. Added proper
config mocks to all test files.
Changes:
- Mock loadConfig() in index.core.test.ts, inbound.media.test.ts,
monitor-inbox.test.ts
- Update test-helpers.ts default mock to disable all prefixes
- Tests now use clean config: no messagePrefix, no responsePrefix,
no timestamp, allowFrom=["*"]
This ensures tests validate core behavior without user-specific config.
The responsePrefix feature itself is already fully config-driven - this
only fixes test isolation.
Fixes issue where unauthorized messages from +212652169245 (5elements spa)
triggered Bad MAC errors and silently killed the event emitter, preventing
all future message processing.
Changes:
1. Early allowFrom filtering in inbound.ts - blocks unauthorized senders
before they trigger encryption errors
2. Message timeout watchdog - auto-restarts connection if no messages
received for 10 minutes
3. Health monitoring in heartbeat - warns if >30 min without messages
4. Mock loadConfig in tests to handle new dependency
Root cause: Event emitter stopped firing after Bad MAC errors from
decryption attempts on messages from unauthorized senders. Connection
stayed alive but all subsequent messages.upsert events silently failed.
Replaces samePhoneMarker/samePhoneResponsePrefix with:
- messagePrefix: prefix for all inbound messages
- Default: '[warelay]' if no allowFrom, else ''
- responsePrefix: prefix for all outbound replies
Also adds timestamp options:
- timestampPrefix: boolean to enable [Nov 29 06:30] format
- timestampTimezone: IANA timezone (default UTC)
Updated README with new config table entries.
Automatically prefixes responses with a configurable string when in
same-phone mode. This helps distinguish bot replies from user messages
in the same chat bubble.
Example config:
"samePhoneResponsePrefix": "🦞"
Will prefix all same-phone replies with the lobster emoji.
Adds full support for self-messaging setups where you chat with yourself
and an AI assistant replies in the same WhatsApp bubble.
Changes:
- Same-phone mode (from === to) always allowed, bypasses allowFrom check
- Echo detection via bounded Set (max 100) prevents infinite loops
- Configurable samePhoneMarker in config (default: "[same-phone]")
- Messages prefixed with marker so assistants know the context
- fromMe filter removed from inbound.ts (echo detection in auto-reply)
- Verbose logging for same-phone detection and echo skips
Tests:
- Same-phone allowed without/despite allowFrom configuration
- Body prefixed only when from === to
- Non-same-phone rejected when not in allowFrom
- Added Twitter automation patterns using Peekaboo + AppleScript
- Documented JS injection for reliable button clicks on Twitter's dynamic UI
- Added audd.io music recognition API example
- These are the techniques Clawd uses to reply to tweets autonomously
- Added browser-tools to CLI tools table (lightweight DevTools CLI)
- Added browser-tools usage section for web scraping
- Added "See It In Action" section with 3 example tweets
- Links to agent-scripts repo
- Wrap Baileys connection.update listeners in try-catch to prevent
unhandled exceptions from crashing the relay process
- Add WebSocket-level error handlers in session.ts
- Add global unhandledRejection/uncaughtException handlers in index.ts
- Make listener.onClose error-safe with .catch() in auto-reply.ts
- Change default heartbeat from 30min to 10min
- Rewrite claude-config.md with personality, better explain personal
assistant features, add recommended MCPs section