You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
#22 deliberately shipped a minimal callstack CLI for status and send, leaving monitor as a follow-up if event streaming would make the first PR too large. Operators still need a safe way to tail live modem activity while bringing up hardware: inbound SMS, delivery reports, call state, USSD responses, reconnects, and signal changes.
This issue scopes a local CLI monitor command, not a network API. It complements #31 (/ws) by helping developers debug a Pi/modem from the terminal without opening another HTTP surface.
User journey
A developer SSHes into the Raspberry Pi running a modem.
They run callstack monitor --at-port /dev/ttyUSB2 --json during setup.
As typed events occur, the CLI prints one sanitized JSON line per event.
They can Ctrl-C cleanly without a traceback, leaked message content in errors, or orphaned modem tasks.
For human troubleshooting, they can omit --json and get concise text output that masks private identifiers by default.
Default output should avoid printing SMS bodies and full phone numbers. If a future operator really needs full payloads, make that an explicit opt-in flag in a separate security-reviewed change.
Technical approach
Add a monitor subcommand in callstack/cli.py using the existing global config flags and asyncio.run() style.
Create a small event serialization helper, preferably shared or compatible with the future WebSocket serializer from Add authenticated WebSocket realtime event stream #31, that maps typed events to PII-safe envelopes:
IncomingSMSEvent -> sms.received with masked sender and body length or redacted body.
SMSDeliveryReportEvent -> sms.delivery_report with reference/status and masked recipient if present.
If tests/test_event_serialization.py is not created because the serializer stays inside callstack/cli.py, replace that path with the exact CLI test file(s) covering serialization.
Motivation
#22 deliberately shipped a minimal
callstackCLI forstatusandsend, leavingmonitoras a follow-up if event streaming would make the first PR too large. Operators still need a safe way to tail live modem activity while bringing up hardware: inbound SMS, delivery reports, call state, USSD responses, reconnects, and signal changes.This issue scopes a local CLI monitor command, not a network API. It complements #31 (
/ws) by helping developers debug a Pi/modem from the terminal without opening another HTTP surface.User journey
callstack monitor --at-port /dev/ttyUSB2 --jsonduring setup.--jsonand get concise text output that masks private identifiers by default.API / UX sketch
JSON-lines output example:
{"type":"modem.state","timestamp":"2026-06-25T00:00:00Z","data":{"connected":true}} {"type":"sms.delivery_report","timestamp":"2026-06-25T00:00:10Z","data":{"reference":42,"status":"delivered"}}Human output example:
Default output should avoid printing SMS bodies and full phone numbers. If a future operator really needs full payloads, make that an explicit opt-in flag in a separate security-reviewed change.
Technical approach
monitorsubcommand incallstack/cli.pyusing the existing global config flags andasyncio.run()style.IncomingSMSEvent->sms.receivedwith masked sender and body length or redacted body.SMSDeliveryReportEvent->sms.delivery_reportwith reference/status and masked recipient if present.CallStateEvent->call.state.ModemDisconnectedEvent/ModemReconnectedEvent->modem.state.SignalQualityEvent->signal.quality.USSDResponseEvent->ussd.responsewith text redacted or length-only by default.modem.bus, place envelopes into a boundedasyncio.Queue, and print until interrupted.modem.state/status snapshot after successful connection if it can be done without extra hardware assumptions.--eventsfiltering so developers can narrow output without changing code.KeyboardInterrupt/cancellation cleanly and ensure all subscriptions are removed before closing the modem.Affected modules and tests
Likely files:
callstack/cli.py— parser, monitor runner, output modes.callstack/events/serialize.pyorcallstack/realtime.py— typed-event-to-envelope helper reused later by Add authenticated WebSocket realtime event stream #31.tests/test_cli.py— monitor parser/config mapping and clean cancellation behavior.tests/test_event_serialization.py— PII-safe envelope mapping for each public event type.Existing context:
callstack/cli.pyalready has_add_config_args(),_config_from_args(), and safe error handling.Modem.busis public on theModemobject and already supportssubscribe()/unsubscribe().events/types.pyalready defines the public event dataclasses needed for monitor output.Hardware / modem caveats
Acceptance criteria
callstack --helpandcallstack monitor --helpdocument the monitor command and shared port/config flags.callstack monitor --jsonprints one valid JSON object per event for the selected event types.--eventsfilters supported event types and rejects unknown names with a useful non-zero CLI error.Exact verification gates
If
tests/test_event_serialization.pyis not created because the serializer stays insidecallstack/cli.py, replace that path with the exact CLI test file(s) covering serialization.Non-goals