feat: inbound webhook receiver + /api/inbound endpoint#49
Open
jakduch wants to merge 5 commits into
Open
Conversation
- POST /api/inbound/<event_type> appends JSON to ~/.claude/inbound.jsonl
with a {type, received_at, source_ip, payload} envelope.
- GET /api/inbound?limit=N returns recent events (newest first).
- Optional shared-secret via X-Inbound-Secret header, configured in
~/.claude/inbound-config.json; mismatched/missing secret returns 403.
- 10MB log rotation -> .jsonl.1 (single generation, capped at ~20MB).
- Dashboard 'Recent inbound events' collapsible card (last 10).
- CLI 'python3 cli.py inbound [--tail N]' for terminal viewing.
- 12 tests in tests/test_inbound.py covering auth, GET ordering/limit,
rotation, unknown event types, and the CLI command.
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.
What does this add and why do you believe it belongs in this dashboard?
A Claude Code usage dashboard is great at answering "what did I spend?" but
it can't answer "why?" — the spikes, the regressions, the unexpectedly
cheap days — without context from the systems that actually triggered the
work. This PR adds a tiny inbound webhook receiver at
POST /api/inbound/<event_type>plus a viewer card and acli.py inboundcommand, so any external system can drop a small JSON note into your
personal log and have it show up next to the spend timeline.
The intended callers are exactly the things you already run: CI builds
(green/red + duration), GitHub events (PR opened, merged, reverted),
deploy hooks, or hand-rolled annotations like "started refactor X" from a
git pre-commit. The endpoint is intentionally schema-free — it stores
arbitrary payloads in
~/.claude/inbound.jsonlwith envelope metadata(type, timestamp, source IP) — because the dashboard's job is correlation,
not modeling. An optional shared secret in
~/.claude/inbound-config.jsongates writes when the dashboard is exposed beyond localhost. No new
dependencies; ~250 lines of tests cover auth, rotation, malformed input,
and the CLI tail.
Checklist
Code correctness
calcCost()calls pass 6 arguments:(model, inp, out, cache_read, cache_creation, cache_1h)`), not escaped ones (\`)Tests
python3 -m unittest discover -s tests -v— all passingpython3 -m unittest tests.test_browser -v— all passingScope
dashboard.py,scanner.py,cli.py,pricing.py,cowork.py,tests/) — or I've explained below why a new file is neededtests/test_inbound.pyis a new file: it exercises a new endpoint family(
/api/inbound,/api/inbound/<type>) and the new CLI subcommand, so itbelongs in its own module rather than bolted onto an existing test file.