feat: add --events flag for machine-readable NDJSON lifecycle events on stderr#85
Open
nextbysam wants to merge 5 commits intosteipete:mainfrom
Open
feat: add --events flag for machine-readable NDJSON lifecycle events on stderr#85nextbysam wants to merge 5 commits intosteipete:mainfrom
nextbysam wants to merge 5 commits intosteipete:mainfrom
Conversation
Add internal/out/EventWriter — a thread-safe NDJSON event emitter that
writes structured {"event","data","ts"} lines to a writer. When disabled
(default), Emit() is a no-op.
Wire it through: --events persistent flag on root → rootFlags.asEvents →
app.Options.Events → App.events field. Exposed via App.Events() accessor.
No behavioral change yet — all stderr output still uses fmt.Fprintf.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace every fmt.Fprintf(os.Stderr, ...) in Sync() with a dual-path: when --events is set, emit a typed JSON event; otherwise print the existing human-readable string unchanged. Events covered: connected, disconnected, history_sync (with conversation count), progress (with messages_synced count), reconnecting, stopping, idle_exit (with idle_duration and messages_synced). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace the two stderr prints in auth.go with event-aware paths:
- "Starting authentication…" → {"event":"auth_starting"}
- QR terminal art → {"event":"qr_code","data":{"code":"<raw-string>"}}
The raw QR payload lets consumers render their own QR (web canvas,
mobile SDK, image file) instead of being stuck with ASCII block art.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- out/events_test.go: verify NDJSON output, disabled no-op, nil data omitted - app/sync_events_test.go: use fakeWA to drive Sync() with events enabled, assert connected/history_sync/progress/stopping events are emitted, assert idle_exit fires on bootstrap mode, assert no output when disabled Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When --events is enabled, each incoming WhatsApp message now emits a new_message NDJSON event to stderr with the full message payload (id, chat, sender, text, media info, reactions, replies). This enables programmatic consumers to react to individual messages in real-time rather than only tracking aggregate sync progress. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
achhabra2
added a commit
to achhabra2/wacli
that referenced
this pull request
Apr 8, 2026
Update whatsmeow to v0.0.0-20260327181659-02ec817e7cf4 to fix WhatsApp 405 client-outdated error (issue steipete#106). Also fix scoping of pm variable in sync event handler after merging PR steipete#80 (revoke/edit) with PR steipete#85 (events).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
waclihas--jsonfor structured stdout output, but the auth/sync lifecycle — the most important part for programmatic consumers — only emits human-readable strings to stderr:Anyone building an application on top of
wacliis forced to regex-parse English sentences to track what's happening. This is fragile: one wording change upstream silently breaks the consumer, and useful structured data (theProgressfloat from whatsmeow, conversation counts) gets thrown away in the string formatting.This is a blind spot in an otherwise well-designed scripting interface —
--jsonclearly signals intent for programmatic use, and issue #83 (JSON-RPC daemon) and issue #65 (Unix socket IPC) reinforce that vision.Solution
Add a
--eventspersistent flag that emits newline-delimited JSON to stderr during auth and sync, one event per line:{"event":"auth_starting","ts":1709042400000} {"event":"qr_code","data":{"code":"2@abc123..."},"ts":1709042400001} {"event":"connected","ts":1709042400002} {"event":"history_sync","data":{"conversations":42},"ts":1709042400003} {"event":"progress","data":{"messages_synced":75},"ts":1709042400004} {"event":"idle_exit","data":{"idle_duration":"30s","messages_synced":150},"ts":1709042400005}Without
--events, behavior is byte-for-byte identical to before. This is purely additive.Events emitted
auth_startingwacli authbeginsqr_codecode(raw QR string, not terminal art)connectedevents.Connecteddisconnectedevents.Disconnectedhistory_syncevents.HistorySyncconversations(count)progressmessages_synced(count)reconnectingstoppingmessages_syncedidle_exitidle_duration,messages_syncedThe
qr_codeevent is particularly useful: instead of detecting Unicode block characters in a stream, consumers get the raw QR payload string and can render it however they want (web canvas, mobile SDK, PNG file).Changes
internal/out/events.go—EventWriter: thread-safe NDJSON emitter, no-op when disabledcmd/wacli/root.go—--eventspersistent flag wired toApp.eventsinternal/app/app.go—Events *out.EventWriterinOptions;App.Events()accessorinternal/app/sync.go— everyfmt.Fprintf(os.Stderr, ...)dual-pathed: JSON event or existing textcmd/wacli/auth.go—auth_startingandqr_codeeventsinternal/out/events_test.go— unit tests for EventWriterinternal/app/sync_events_test.go— integration tests using the existing fakeWA harnessUsage
Combine with
jqfor easy scripting:🤖 Generated with Claude Code