Skip to content

Commit 983dd08

Browse files
mitulgargclaude
andcommitted
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>
1 parent c6a3dac commit 983dd08

25 files changed

Lines changed: 1190 additions & 228 deletions

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,3 +192,4 @@ src/env_doctor/web/*
192192
!src/env_doctor/web/.gitkeep
193193
PR_SUMMARY.md
194194
CHANGES-cuda-install-run.md
195+
*.stackdump

CHANGELOG.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,16 @@ All notable changes to env-doctor will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

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.
15+
16+
---
17+
818
## [0.3.1] - 2026-04-15
919

1020
### Added

CHANGES-cuda-install-run.md

Lines changed: 0 additions & 155 deletions
This file was deleted.

README.md

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -184,20 +184,29 @@ There are two roles — the **dashboard host** (receives and displays reports) a
184184
pip install "env-doctor[dashboard]"
185185
env-doctor dashboard
186186
# → 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>
187189
```
188190

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+
189193
**Step 2 — Report from each GPU machine** (only needs the core CLI, not the `[dashboard]` extra):
190194

191195
```bash
192196
pip install env-doctor
193197

194198
# One-time report
195-
env-doctor check --report-to http://<dashboard-host>:8765
199+
env-doctor check --report-to http://<dashboard-host>:8765 --token <token>
196200

197201
# Or: set up automatic reporting every 2 minutes
198-
env-doctor report install --url http://<dashboard-host>:8765 --interval 2m
202+
env-doctor report install \
203+
--url http://<dashboard-host>:8765 \
204+
--token <token> \
205+
--interval 2m
199206
```
200207

208+
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+
201210
`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.
202211

203212
### Smart Change Detection
@@ -248,9 +257,19 @@ For machines behind NAT (different networks), use [Tailscale](https://tailscale.
248257

249258
```bash
250259
# Install Tailscale on each machine, then use the Tailscale IP
251-
env-doctor report install --url http://100.x.x.x:8765
260+
env-doctor report install --url http://100.x.x.x:8765 --token <token>
252261
```
253262

263+
### Deploying to a Shared Host
264+
265+
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+
254273
### What the Dashboard Shows
255274

256275
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 —
269288
```
270289
Dashboard GPU Machine
271290
┌────────────┐ ┌──────────────────┐
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+
└──────┬─────┘ └────────┬─────────┘
277296
│ │
278297
▼ ▼
279298
Queue command env-doctor check
@@ -662,6 +681,14 @@ env-doctor check --json
662681
env-doctor check --ci
663682
```
664683

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 |
691+
665692
**GitHub Actions example:**
666693
```yaml
667694
- run: pip install env-doctor

docs/commands/dashboard.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,9 +125,12 @@ The dashboard exposes a REST API that machines post to:
125125

126126
| Endpoint | Method | Description |
127127
|----------|--------|-------------|
128-
| `/api/report` | POST | Receive a check report |
128+
| `/api/report` | POST | Receive a check report; returns `pending_commands[]` for the machine |
129129
| `/api/machines` | GET | List all machines with latest status |
130130
| `/api/machines/{id}` | GET | Full machine detail and latest report |
131131
| `/api/machines/{id}/history` | GET | Snapshot timeline |
132+
| `/api/machines/{id}/commands` | POST | Queue a remediation command (must start with `env-doctor` or `doctor`) |
133+
| `/api/machines/{id}/commands` | GET | List recent commands with status and output |
134+
| `/api/machines/{id}/commands/{cmd_id}/result` | POST | Machine posts execution result `{output, exit_code}` |
132135

133136
See the [Fleet Monitoring Guide](../guides/fleet-monitoring.md) for full setup instructions.

docs/guides/fleet-monitoring.md

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,44 @@ env-doctor check --report-to http://10.0.1.50:8765
271271

272272
---
273273

274+
## Remote Remediation
275+
276+
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.
303+
304+
| Exit code | Meaning |
305+
|-----------|---------|
306+
| `0` | All detected components compatible; uninstalled libraries ignored |
307+
| `1` | Installed components have warnings or version conflicts |
308+
| `2` | One or more components in error state |
309+
310+
---
311+
274312
## Data Storage
275313

276314
**On the dashboard host:**

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
44

55
[project]
66
name = "env-doctor"
7-
version = "0.3.1"
7+
version = "0.3.2"
88
description = "A CLI tool to verify and fix AI/ML environment compatibility (Driver <-> CUDA <-> Wheels) with platform-specific installation guides."
99
readme = "README.md"
1010
license = { file = "LICENSE" }

src/env_doctor/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = "0.3.1"
1+
__version__ = "0.3.2"

0 commit comments

Comments
 (0)