feat: promptconduit watch [--verbose] — tail outbound HTTP traffic#49
Draft
scotthavird wants to merge 1 commit into
Draft
feat: promptconduit watch [--verbose] — tail outbound HTTP traffic#49scotthavird wants to merge 1 commit into
promptconduit watch [--verbose] — tail outbound HTTP traffic#49scotthavird wants to merge 1 commit into
Conversation
New top-level `watch` subcommand that lets users see every request the
CLI sends to the platform in real time. Useful for debugging the
"events aren't showing up on the dashboard" class of problem without
spelunking the debug log.
Mechanism:
- New internal/outbound package implements an http.RoundTripper that
wraps http.DefaultTransport, captures each request+response, and
appends one ndjson line to ~/.config/promptconduit/outbound.ndjson
(mode 0600). Wired into internal/client.NewClient so both the
foreground command and the `hook --send-event` subprocess feed
into the same file — no edits to the 15+ send methods individually.
- Authorization / Cookie / X-Api-Key / *secret* / *token* / *key*
headers redacted to "***" before write.
- Bodies capped at 64KB per direction; oversized requests record
`req_truncated: true` plus the original size for context. File
rotates to outbound.ndjson.1 when it crosses 50MB; one backup kept.
- Cross-process concurrency: O_APPEND with a per-process sync.Mutex
on every platform; on Unix, lines >4KB take an exclusive flock so
they don't tear under the 4KB POSIX PIPE_BUF atomicity limit.
- Tail uses stdlib polling (200ms) and recovers across rotation by
watching the inode (Unix) or size-shrink (Windows).
UX:
- `promptconduit watch` — live tail, one summary line per request:
`15:30:42 POST /v1/events/raw 3.2KB → 200 (87ms)` with ANSI
status color when stdout is a tty.
- `promptconduit watch --verbose` — also pretty-prints the JSON
body indented under each summary.
- `promptconduit watch --lines N` — backfill the last N entries
before going live.
- Ctrl-C / SIGTERM exits cleanly with no usage banner.
Tests in internal/outbound/ (22 cases): round-trip via httptest.Server,
file permissions 0600, body truncation, rotation under a low threshold,
downstream-readable body after capture, network-error recording,
tail backfill+live, tail recovery across rotation, header redaction
table, render summary (default + verbose + color + error path),
truncateBody pure helper, ParseLine round-trip.
Out of scope: internal/updater builds its own *http.Client for the
GitHub releases check, so update-check traffic bypasses the mirror.
Documented in the README — it's predictable and noisy and isn't what
`watch` is for. The hook update notifier and upgrade command continue
to work normally; they're just invisible to `watch`.
https://claude.ai/code/session_019CWBC2E8pQuShejfsKYrvp
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.
Summary
New top-level
watchsubcommand that streams every HTTP request the CLI makes to the platform to your terminal in real time. Closes the "events aren't showing up on the dashboard, but I don't know if my hook is even firing" debugging gap.Each request shows up as a one-line summary by default:
ANSI color on status (green 2xx, yellow 3xx, red 4xx/5xx) when stdout is a tty.
Mechanism
internal/outboundpackage implements anhttp.RoundTripperthat wrapshttp.DefaultTransport, captures each request+response, and appends one ndjson line to~/.config/promptconduit/outbound.ndjson(mode0600). The mirror is wired intoclient.NewClientso both the foreground command and thehook --send-eventsubprocess feed into the same file — no edits to the 15+Send*/Sync*/Get*methods individually.Authorization,Cookie,Set-Cookie,X-Api-Key,Proxy-Authorizationplus any header name containingtoken/secret/key(case-insensitive) are replaced with***before write.req_truncated: true+req_original_size_bytesso the user can tell something got clipped.outbound.ndjsoncrosses 50MB it's renamed tooutbound.ndjson.1(one backup kept) and a fresh file is started.O_APPEND+ per-processsync.Mutexeverywhere; on Unix, lines >4KB additionally take an exclusiveflockto dodge the 4KB POSIX PIPE_BUF atomicity limit so parent andhook --send-eventsubprocess writes don't tear.Out of scope (documented in README)
internal/updaterbuilds its own*http.Clientfor the GitHub releases check, so update-check traffic bypasses the mirror. That's intentional — it's predictable and noisy and isn't whatwatchis for. Theupgradecommand continues to work; it's just invisible towatch.Test plan
go build ./... && go vet ./... && go test ./...cleaninternal/outbound/: httptest round-trip, body capture, file mode0600, body truncation, rotation under a low threshold, downstream-readable request body after mirror capture, network-error recorded witherrorfield, header redaction table (Authorization/Cookie/X-Api-Key/X-Secret-Token redacted, Content-Type / User-Agent preserved, nil-safe, doesn't mutate input), render summary (default / verbose / color codes / network error),truncateBodypure helper,ParseLineround-trip, tail backfill + live, tail recovery across rotationv0.5.0, confirmed mirror file at$XDG_CONFIG_HOME/promptconduit/outbound.ndjsonwith mode-rw-------, full envelope JSON captured, Authorization redacted, transport error recorded; then ranwatch --verbose --lines 1and saw the summary + pretty-printed body; clean exit on Ctrl-Chttps://claude.ai/code/session_019CWBC2E8pQuShejfsKYrvp
Generated by Claude Code