Skip to main content

gws doctor

Run programmatic checks against the GetWebstack failure-mode catalog. This is the diagnose step in the /gws-setup and /gws-debug loops — it's how the AI knows what to fix.

Two tiers of checks:

  1. Artifact checks (always run today) — look at gws.json, generated Dockerfiles, and K8s manifests for known foot-guns: USER directive in a Dockerfile, server bound to 127.0.0.1, port mismatch between Dockerfile EXPOSE / gws.json port / K8s containerPort, multi-stage / distroless base image (breaks file sync), placeholder values left in generated artifacts.
  2. Cluster checks (Phase 3b — registry shipped, command wiring still landing) — CrashLoopBackOff log fetch + diagnosis from a regex catalog, pod ↔ service selector mismatch, HTTP probe failures with status codes, file-sync session / exec-probe / log-error rules.

The cluster rule registry is fully populated, but gws doctor itself currently invokes only the artifact runner — so today the command behaves as if --artifacts-only were always set, regardless of the flag. The flag surface (-p, -w, --all-worktrees) is wired ahead of the runner switch.

Usage

gws doctor [options]
FlagDescriptionDefault
-p, --project <name>Project to diagnose.inferred from gws.json in cwd
-w, --worktree <name>Worktree to diagnose.active worktree
--all-worktreesDiagnose every worktree of the current project. (No-op in Phase 3a — wired ahead of cluster checks.)false
--service <name>Limit checks to one service.all services
--artifacts-onlySkip cluster checks.false (true today; see above)
--jsonEmit machine-readable JSON instead of human text.false

Auth: not required.

Exit code

CodeMeaning
0No errors (warnings allowed)
1At least one finding with severity error

That makes gws doctor safe to drop into a CI step — fail the build if gws config import produced anything broken.

Output

Human:

Ran 1 check: 1 error, 0 warnings.

ERROR [api] dockerfile.user-directive .gws/services/api/Dockerfile:14
USER directive in Dockerfile breaks bidirectional file sync.
fix: Remove the USER line — dev-mode containers run as root by design.

JSON (--json):

{
"summary": { "checked": 1, "errors": 1, "warnings": 0 },
"findings": [
{
"severity": "error",
"check": "dockerfile.user-directive",
"service": "api",
"file": ".gws/services/api/Dockerfile",
"line": 14,
"message": "USER directive in Dockerfile breaks bidirectional file sync.",
"fix": "Remove the USER line — dev-mode containers run as root by design."
}
]
}

Findings are ordered errors-first, then warnings, preserving discovery order within a tier.

Common findings

Check IDs are stable and namespaced — safe to grep / filter on. Live source: gws/src/libs/doctor/rules.ts (artifact rules) and gws/src/libs/doctor/cluster/ (cluster rules).

Artifact rules (always run):

Check idSymptomSuggested fix
dockerfile.user-directiveContainer exits immediately on dev-mode start.Remove the USER directive.
dockerfile.multi-stage-minimal-runtimeFile sync silently doesn't work.Switch to single-stage with the source in the final image.
dockerfile.distroless-baseFile sync silently doesn't work.Use a full base image (no distroless/scratch).
dockerfile.port-mismatchService URL returns 502/503.Make Dockerfile EXPOSE, gws.json port, and K8s containerPort agree.
source.localhost-bindPod runs but Service can't reach it.Bind to 0.0.0.0.
artifact.placeholderGenerated artifact still contains {{…}} placeholders or is missing.Re-run gws generate-template / fill in the placeholder.

Cluster rules (registered; runner wiring in progress — see top of page):

Check idWhat it catches
cluster.crashloopCrashLoopBackOff, fetches logs and tags from the regex catalog.
cluster.selector-mismatchPod labels don't match the Service selector.
cluster.http-probeService URL probe failed; reports the HTTP status.
cluster.file-sync.sessiongws-file-sync SSH sidecar isn't reachable.
cluster.file-sync.exec-probeFile-sync exec probe failed inside the pod.
cluster.file-sync.log-errorsSync sidecar emitted error logs.

Examples

# Diagnose everything
gws doctor

# JSON — for /gws-debug and CI
gws doctor --json

# Limit to one service
gws doctor --service api --json

# Pre-import gate
gws doctor --artifacts-only && gws config import gws.json && gws up

See also