You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat: dashboard UX improvements and remote remediation fixes (v0.3.2)
- Fix exit code semantics: NOT_FOUND libraries no longer trigger exit code 1
in `check --json`, so remote commands show as done instead of failed
- Dashboard auto-refreshes machine diagnostics 1.5s after a queued command completes
- Add bearer token auth module for dashboard API
- Add CustomCommandBox and Login components
- Bump version to 0.3.2
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: CHANGELOG.md
+10Lines changed: 10 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -5,6 +5,16 @@ All notable changes to env-doctor will be documented in this file.
5
5
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
8
+
## [0.3.2] - 2026-05-02
9
+
10
+
### Fixed
11
+
-**Exit code semantics for `check --json`**: `NOT_FOUND` library status no longer triggers exit code 1. Previously, having torch/tensorflow/jax uninstalled caused `env-doctor check --json` to exit 1 (warning), making remote remediation commands show as "failed" on the dashboard even when the check ran successfully. New exit codes: `0` = pass (no issues or only missing libraries), `1` = warnings (installed components with version conflicts), `2` = errors (broken components).
12
+
13
+
### Changed
14
+
-**Dashboard auto-refresh after remote command**: After a queued command completes on a machine, the Machine Detail page now automatically re-fetches and re-renders the diagnostics panel (1.5 s after the command finishes) — no manual page refresh needed.
Copy file name to clipboardExpand all lines: README.md
+35-8Lines changed: 35 additions & 8 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -184,20 +184,29 @@ There are two roles — the **dashboard host** (receives and displays reports) a
184
184
pip install "env-doctor[dashboard]"
185
185
env-doctor dashboard
186
186
# → Serving at http://localhost:8765
187
+
# → 🔐 Generated new API token at ~/.env-doctor/api-token
188
+
# Token: <copy this — paste into the browser login + share with hosts>
187
189
```
188
190
191
+
On first launch the dashboard generates a shared API token (saved at `~/.env-doctor/api-token`, mode 0600). The browser login screen and every host CLI need that token. Override the location with `ENV_DOCTOR_API_TOKEN=<token>` in the dashboard's environment.
192
+
189
193
**Step 2 — Report from each GPU machine** (only needs the core CLI, not the `[dashboard]` extra):
The token is saved in `~/.env-doctor/report-config.json` so the scheduled cron / Task Scheduler entry stays clean (no secrets in `crontab -l`).
209
+
201
210
`report install` creates a scheduled task on the GPU machine — a **cron job** on Linux/macOS or a **Windows Task Scheduler** entry on Windows. That task runs `env-doctor check --report-to <url>` on the configured interval.
202
211
203
212
### Smart Change Detection
@@ -248,9 +257,19 @@ For machines behind NAT (different networks), use [Tailscale](https://tailscale.
248
257
249
258
```bash
250
259
# Install Tailscale on each machine, then use the Tailscale IP
If you're hosting one dashboard for a small team rather than running it on a single laptop:
266
+
267
+
1.**Use the API token.** Generated automatically on first launch (see Step 1 above), or pin a known value with `ENV_DOCTOR_API_TOKEN`. All `/api/*` routes require `Authorization: Bearer <token>`.
268
+
2.**Put TLS in front.** The dashboard speaks plain HTTP. Terminate TLS in nginx, Caddy, or a cloud load balancer and forward to `127.0.0.1:8765`. Tokens travel in the `Authorization` header — they need TLS to stay private outside trusted networks.
269
+
3.**Restrict CORS.** Set `ENV_DOCTOR_CORS_ORIGINS=https://dashboard.example.com` on the dashboard process so the browser only honours requests from your origin (defaults to `*` for backward compatibility with local use).
270
+
4.**Tune staleness.** A machine is flagged "stale" once its `last_seen` is older than `ENV_DOCTOR_STALE_SECONDS` seconds (default 3600 = 1 hour, ≈ 2× the default heartbeat).
271
+
5.**Rotating the token.** Edit `~/.env-doctor/api-token` (or update `ENV_DOCTOR_API_TOKEN` and restart). Each host CLI needs `env-doctor report install --token <new>` re-run, or its `~/.env-doctor/report-config.json` updated, before the next check-in.
272
+
254
273
### What the Dashboard Shows
255
274
256
275
The web UI at `http://<dashboard-host>:8765` displays:
@@ -269,11 +288,11 @@ The dashboard can queue `env-doctor` CLI commands to run on remote machines —
269
288
```
270
289
Dashboard GPU Machine
271
290
┌────────────┐ ┌──────────────────┐
272
-
│ Operator │ │ Scheduled check │
273
-
│ clicks │ │ (cron / Task │
274
-
│ "▶ Run" on │ │ Scheduler) │
275
-
│ Fleet page │ │ │
276
-
└──────┬──────┘ └────────┬─────────┘
291
+
│ Operator │ │ Scheduled check │
292
+
│ clicks │ │ (cron / Task │
293
+
│ "▶ Run" on │ │ Scheduler) │
294
+
│ Fleet page │ │ │
295
+
└──────┬─────┘ └────────┬─────────┘
277
296
│ │
278
297
▼ ▼
279
298
Queue command env-doctor check
@@ -662,6 +681,14 @@ env-doctor check --json
662
681
env-doctor check --ci
663
682
```
664
683
684
+
**Exit code semantics for `check --json` / `check --ci`:**
685
+
686
+
| Code | Meaning |
687
+
|------|---------|
688
+
|`0`| All detected components are compatible (uninstalled libraries do not count as failures) |
689
+
|`1`| Installed components have warnings or version conflicts |
690
+
|`2`| One or more components are in an error state |
The dashboard can queue `env-doctor` commands to run on remote machines — no SSH required.
277
+
278
+
### How it works
279
+
280
+
1. **Operator** opens a machine's detail page in the dashboard and types a command in the "Run a command" box (e.g. `env-doctor install torch --execute`).
281
+
2. The command is stored in the database with status `pending`.
282
+
3. On the **next check-in** (`POST /api/report`), the server returns the pending command in the response.
283
+
4. The **GPU machine CLI** executes the command, captures stdout/stderr, and POSTs the result back to `/api/machines/{id}/commands/{cmd_id}/result`.
284
+
5. The CLI then re-runs `env-doctor check --report-to <url>` to verify the fix and post a fresh diagnostic snapshot.
285
+
6. The **dashboard auto-refreshes** the machine detail page 1.5 s after the command completes, showing updated diagnostics without a manual page reload.
286
+
287
+
### Security
288
+
289
+
Only commands prefixed with `env-doctor` or `doctor` are accepted by the server. Arbitrary shell commands are rejected with HTTP 400.
290
+
291
+
### Command lifecycle
292
+
293
+
| Status | Meaning |
294
+
|--------|---------|
295
+
| `pending` | Queued, waiting for machine to check in |
296
+
| `running` | Machine picked it up, executing now |
297
+
| `done` | Completed with exit code 0 |
298
+
| `failed` | Completed with non-zero exit code |
299
+
300
+
### Exit codes for `env-doctor check --json`
301
+
302
+
When `env-doctor check --json` is queued as a remote command, exit code 1 does **not** mean the check failed — it means there are installed components with warnings. Uninstalled libraries alone do not produce a non-zero exit code.
0 commit comments