Sets up project structure, working conventions (CLAUDE.md), README with the full assignment and roadmap, seeded CHANGELOG, and a buildable Go scaffold (Step 0) with flag parsing and stub probe types. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
5.5 KiB
Plan: Website latency CLI tool (Go first, then Python)
Context
We're building a small CLI tool that measures the latency of one or more websites given their URLs. The point of difference from a naive timer is a full per-phase breakdown of an HTTP request — DNS resolution, TCP connect, TLS handshake, server processing (time-to-first-byte), and content transfer — not just a single total number.
We start simple (total latency only) and grow the tool in clear steps. The Go implementation comes first; once the user is satisfied, we port the same behaviour to Python. This plan also establishes project-wide working conventions (plans, changelog, per-feature docs) up front.
Design decisions confirmed with the user:
- Output: human-readable text by default, with a
--jsonflag for machine output. - Sampling: a
--count/-nflag repeats N requests per URL and reports min/avg/max per phase. - Input: accept multiple URLs as positional arguments, measured in turn.
Toolchain present: Go 1.26.4, Python 3.14.6.
Proposed layout
tt-excercise/
├── CLAUDE.md # working conventions (created first)
├── README.md # the assignment + implementation steps
├── CHANGELOG.md # timestamped completed features
├── docs/
│ ├── plans/ # timestamped plans (this plan copied here)
│ └── usage/ # per-feature user documentation
├── go/
│ ├── go.mod # module: latprobe (name adjustable)
│ ├── main.go # CLI: flag parsing, orchestration, output
│ └── internal/probe/
│ └── probe.go # timing logic via net/http/httptrace
└── python/ # added later, during the port
Binary/module name proposed: latprobe (easy to change).
Foundation files (created at the start)
CLAUDE.md — working conventions
- Every plan is saved under
docs/plans/with a filename starting with the current timestamp inyyyy-mm-dd-hh-mmformat (e.g.2026-07-01-00-08-go-latency-tool.md). - Every completed feature is appended to
CHANGELOG.mdwith a timestamp. - Every feature ships with user documentation under
docs/usage/including a concrete example of how to use it.
README.md — the assignment
- Project purpose: CLI tool to measure website latency, with a full per-request phase breakdown including DNS resolution.
- Two implementations: Go first, then a Python port.
- Usage sketch and the staged implementation roadmap (below).
- Note that Go 1.26 / Python 3.14 are the development versions.
CHANGELOG.md
- Seeded with a header; entries appended per completed feature.
Implementation steps (Go)
Each step is a self-contained, reviewable increment. We pause for the user's
sign-off between steps. On completion of each: append to CHANGELOG.md and add
its docs/usage/ page.
Step 0 — Scaffold. Create go/go.mod (go mod init latprobe), a minimal
main.go that prints usage, and the directory structure. Confirms the toolchain
builds.
Step 1 — Simple total latency. Accept a single URL argument, perform an
HTTP GET, and print the total wall-clock time of the request. No breakdown yet.
Reuse the standard library only (net/http, time).
Step 2 — Full per-phase breakdown (the core feature). Instrument the request
with net/http/httptrace.ClientTrace to capture timestamps and derive each phase:
- DNS lookup (
DNSStart→DNSDone) - TCP connect (
ConnectStart→ConnectDone) - TLS handshake (
TLSHandshakeStart→TLSHandshakeDone, HTTPS only) - Server processing / TTFB (
WroteRequest→GotFirstResponseByte) - Content transfer (
GotFirstResponseByte→ response body fully read) - Total
Print an aligned text breakdown.
httptraceis the key reusable stdlib piece — no third-party dependency needed.
Step 3 — Multiple URLs + sampling. Accept multiple positional URLs; add
--count/-n (default 1) to repeat each URL N times and report min/avg/max
per phase. Group output clearly per URL.
Step 4 — JSON output. Add a --json flag producing structured output
(per URL, per phase, with the min/avg/max aggregates and sample count). Keep the
human-readable text as the default.
Reasonable extras to consider later (not committed now): --timeout,
--method, redirect handling, HTTP/2 vs HTTP/1.1 reporting, exit codes on failure.
Port to Python (after Go is approved)
Mirror the same CLI and output. Python has no direct httptrace equivalent, so
the plan will measure phases at a lower level — e.g. custom timing around
socket.getaddrinfo (DNS), connection establishment, and TLS wrap, or by using
urllib3/httpx connection hooks. The detailed Python design will be drafted
as its own plan (saved to docs/plans/) when we reach that stage.
Verification
cd go && go build ./...succeeds at every step.- Manual runs against known hosts, e.g.:
./latprobe https://example.com→ total only (Step 1), full breakdown (Step 2+)../latprobe -n 5 https://example.com https://www.google.com→ min/avg/max per URL../latprobe --json https://example.com→ valid JSON (pipe through a JSON validator).
- Sanity-check phase numbers: phases should roughly sum to the total; HTTPS shows a TLS phase, plain HTTP does not.
go vet ./...clean.
Bookkeeping at execution time
On exiting plan mode, before/with Step 0:
- Copy this plan to
docs/plans/2026-07-01-00-08-go-latency-tool.md. - Create
CLAUDE.md,README.md,CHANGELOG.mdas described above.