# 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 `--json` flag for machine output. - **Sampling:** a `--count`/`-n` flag 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 in `yyyy-mm-dd-hh-mm` format (e.g. `2026-07-01-00-08-go-latency-tool.md`). - Every completed feature is appended to `CHANGELOG.md` with 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. `httptrace` is 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: 1. Copy this plan to `docs/plans/2026-07-01-00-08-go-latency-tool.md`. 2. Create `CLAUDE.md`, `README.md`, `CHANGELOG.md` as described above.