Skip to content
Dan Riddell edited this page Sep 30, 2026 · 1 revision

Doctor

letsgo doctor [--json]

A read-only, offline diagnosis of the tools letsgo needs and the state of the repository it is pointed at. It makes no network calls and writes no files, so it is safe to run anywhere, including on a machine you are only borrowing.

$ letsgo doctor

  tools
  ✓ go         go1.27.1 (/usr/local/go/bin/go)
  ! go.mod     wants go1.27.1; GOTOOLCHAIN will switch
  ✓ git        /usr/bin/git
  ! govulncheck not found — go install golang.org/x/vuln/cmd/govulncheck@latest
  ✓ apidiff    v0.0.0-2026...

  repository
  ✓ letsgo.mod parses
  ✗ plugin     letsgo-multi v0.3.0: digest mismatch (installed sha256:ab12...)
  ! history    shallow clone — use fetch-depth: 0
  ✓ remote     github.com/you/gambit
  ✓ worktree   clean

Each line is <✓|!|✗> <name> <detail>, and ! or ✗ carries a hint saying what to do about it. The exit code is 1 if anything is ✗, and 0 otherwise — so a ! never fails a pipeline, which is the difference between "you should know this" and "this will not work".

Tools

  • go and git — found or not, with the path and version. Missing is ✗: nothing works without them.
  • govulncheck and apidiff — missing is ! with the go install line, because their gates skip rather than fail by default. Under require vulncheck a missing govulncheck becomes ✗, since that is exactly what require asked for.
  • go.mod skew — a local Go different from the go or toolchain line is !. It is not wrong, but the toolchain is a build input, so it is worth seeing before a release rather than after one.

Repository

  • letsgo.mod — a parse or decode error is ✗, reported as file:line:col. The same positions the editor shows as squiggles.
  • plugins — each pin that is missing, or whose installed digest does not match, is ✗. letsgo would refuse it at release time; finding out now is cheaper.
  • history — a shallow clone, or no tags at all, is ! with the fetch-depth: 0 hint. This is the most common CI surprise: the changelog and the API gate both need history the default checkout does not fetch.
  • remote — a non-GitHub origin is !, naming the outputs that get skipped.
  • worktree — dirty is !. A release needs a clean one, but a diagnosis is not a release.

JSON

{"schema": 1, "checks": [
  {"group": "tools", "name": "govulncheck", "status": "warn",
   "detail": "not found",
   "hint": "go install golang.org/x/vuln/cmd/govulncheck@latest"}
]}

status is ok, warn or fail.

Why it agrees with plan

Doctor reuses plan's own resolution rather than re-deriving anything. Two commands that each work out where go is, which config applies and what the plugins are pinned to would eventually disagree, and a diagnostic that disagrees with the thing it diagnoses is worse than no diagnostic.

What it does not do is run the gates. plan is the command that says whether a release would succeed; doctor says whether the machine and the checkout are in a fit state to try.

Clone this wiki locally