cuda-doctor 0.1.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. cuda_doctor-0.1.2/LICENSE +21 -0
  2. cuda_doctor-0.1.2/PKG-INFO +276 -0
  3. cuda_doctor-0.1.2/README.md +241 -0
  4. cuda_doctor-0.1.2/pyproject.toml +99 -0
  5. cuda_doctor-0.1.2/setup.cfg +4 -0
  6. cuda_doctor-0.1.2/src/cuda_doctor/__init__.py +5 -0
  7. cuda_doctor-0.1.2/src/cuda_doctor/__main__.py +6 -0
  8. cuda_doctor-0.1.2/src/cuda_doctor/checks/__init__.py +71 -0
  9. cuda_doctor-0.1.2/src/cuda_doctor/checks/base.py +44 -0
  10. cuda_doctor-0.1.2/src/cuda_doctor/checks/compiler_checks.py +123 -0
  11. cuda_doctor-0.1.2/src/cuda_doctor/checks/cuda_checks.py +193 -0
  12. cuda_doctor-0.1.2/src/cuda_doctor/checks/driver_checks.py +158 -0
  13. cuda_doctor-0.1.2/src/cuda_doctor/checks/environment_checks.py +141 -0
  14. cuda_doctor-0.1.2/src/cuda_doctor/checks/gpu_checks.py +94 -0
  15. cuda_doctor-0.1.2/src/cuda_doctor/checks/pytorch_checks.py +340 -0
  16. cuda_doctor-0.1.2/src/cuda_doctor/cli.py +134 -0
  17. cuda_doctor-0.1.2/src/cuda_doctor/collectors/__init__.py +37 -0
  18. cuda_doctor-0.1.2/src/cuda_doctor/collectors/cmake.py +17 -0
  19. cuda_doctor-0.1.2/src/cuda_doctor/collectors/compiler.py +71 -0
  20. cuda_doctor-0.1.2/src/cuda_doctor/collectors/cuda.py +78 -0
  21. cuda_doctor-0.1.2/src/cuda_doctor/collectors/environment.py +71 -0
  22. cuda_doctor-0.1.2/src/cuda_doctor/collectors/gpu.py +20 -0
  23. cuda_doctor-0.1.2/src/cuda_doctor/collectors/ninja.py +17 -0
  24. cuda_doctor-0.1.2/src/cuda_doctor/collectors/nvidia_smi.py +99 -0
  25. cuda_doctor-0.1.2/src/cuda_doctor/collectors/python_env.py +37 -0
  26. cuda_doctor-0.1.2/src/cuda_doctor/collectors/pytorch.py +75 -0
  27. cuda_doctor-0.1.2/src/cuda_doctor/collectors/system.py +60 -0
  28. cuda_doctor-0.1.2/src/cuda_doctor/compatibility/__init__.py +68 -0
  29. cuda_doctor-0.1.2/src/cuda_doctor/compatibility/compiler_cuda.py +129 -0
  30. cuda_doctor-0.1.2/src/cuda_doctor/compatibility/cuda_driver.py +120 -0
  31. cuda_doctor-0.1.2/src/cuda_doctor/compatibility/pytorch_cuda.py +102 -0
  32. cuda_doctor-0.1.2/src/cuda_doctor/core/__init__.py +1 -0
  33. cuda_doctor-0.1.2/src/cuda_doctor/core/context.py +25 -0
  34. cuda_doctor-0.1.2/src/cuda_doctor/core/enums.py +40 -0
  35. cuda_doctor-0.1.2/src/cuda_doctor/core/exceptions.py +24 -0
  36. cuda_doctor-0.1.2/src/cuda_doctor/core/models.py +230 -0
  37. cuda_doctor-0.1.2/src/cuda_doctor/core/runner.py +126 -0
  38. cuda_doctor-0.1.2/src/cuda_doctor/data/cuda_compiler_compatibility.json +69 -0
  39. cuda_doctor-0.1.2/src/cuda_doctor/data/cuda_driver_compatibility.json +17 -0
  40. cuda_doctor-0.1.2/src/cuda_doctor/data/known_issues.json +23 -0
  41. cuda_doctor-0.1.2/src/cuda_doctor/diagnosis/__init__.py +1 -0
  42. cuda_doctor-0.1.2/src/cuda_doctor/diagnosis/engine.py +69 -0
  43. cuda_doctor-0.1.2/src/cuda_doctor/diagnosis/issue.py +69 -0
  44. cuda_doctor-0.1.2/src/cuda_doctor/diagnosis/recommendations.py +133 -0
  45. cuda_doctor-0.1.2/src/cuda_doctor/py.typed +0 -0
  46. cuda_doctor-0.1.2/src/cuda_doctor/reporters/__init__.py +17 -0
  47. cuda_doctor-0.1.2/src/cuda_doctor/reporters/base.py +36 -0
  48. cuda_doctor-0.1.2/src/cuda_doctor/reporters/json_report.py +35 -0
  49. cuda_doctor-0.1.2/src/cuda_doctor/reporters/markdown.py +151 -0
  50. cuda_doctor-0.1.2/src/cuda_doctor/reporters/terminal.py +364 -0
  51. cuda_doctor-0.1.2/src/cuda_doctor/utils/__init__.py +1 -0
  52. cuda_doctor-0.1.2/src/cuda_doctor/utils/commands.py +99 -0
  53. cuda_doctor-0.1.2/src/cuda_doctor/utils/parsing.py +107 -0
  54. cuda_doctor-0.1.2/src/cuda_doctor/utils/paths.py +99 -0
  55. cuda_doctor-0.1.2/src/cuda_doctor/utils/platform.py +18 -0
  56. cuda_doctor-0.1.2/src/cuda_doctor/utils/redact.py +58 -0
  57. cuda_doctor-0.1.2/src/cuda_doctor/utils/versions.py +88 -0
  58. cuda_doctor-0.1.2/src/cuda_doctor/version.py +3 -0
  59. cuda_doctor-0.1.2/src/cuda_doctor.egg-info/PKG-INFO +276 -0
  60. cuda_doctor-0.1.2/src/cuda_doctor.egg-info/SOURCES.txt +62 -0
  61. cuda_doctor-0.1.2/src/cuda_doctor.egg-info/dependency_links.txt +1 -0
  62. cuda_doctor-0.1.2/src/cuda_doctor.egg-info/entry_points.txt +2 -0
  63. cuda_doctor-0.1.2/src/cuda_doctor.egg-info/requires.txt +9 -0
  64. cuda_doctor-0.1.2/src/cuda_doctor.egg-info/top_level.txt +1 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 cuda-doctor contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,276 @@
1
+ Metadata-Version: 2.4
2
+ Name: cuda-doctor
3
+ Version: 0.1.2
4
+ Summary: Local CUDA / PyTorch development environment diagnostic tool
5
+ Author: cuda-doctor contributors
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/TheManWhoIsStupid/cuda-doctor
8
+ Project-URL: Issues, https://github.com/TheManWhoIsStupid/cuda-doctor/issues
9
+ Project-URL: Changelog, https://github.com/TheManWhoIsStupid/cuda-doctor/blob/main/CHANGELOG.md
10
+ Keywords: cuda,pytorch,nvidia,gpu,diagnostics,developer-tools
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Environment :: Console
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Operating System :: Microsoft :: Windows
15
+ Classifier: Operating System :: POSIX :: Linux
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Topic :: Software Development :: Debuggers
22
+ Classifier: Topic :: System :: Systems Administration
23
+ Requires-Python: >=3.10
24
+ Description-Content-Type: text/markdown
25
+ License-File: LICENSE
26
+ Requires-Dist: typer>=0.9
27
+ Requires-Dist: rich>=13.0
28
+ Provides-Extra: dev
29
+ Requires-Dist: pytest>=7.0; extra == "dev"
30
+ Requires-Dist: pytest-cov; extra == "dev"
31
+ Requires-Dist: ruff>=0.4; extra == "dev"
32
+ Requires-Dist: mypy>=1.8; extra == "dev"
33
+ Requires-Dist: pre-commit; extra == "dev"
34
+ Dynamic: license-file
35
+
36
+ # cuda-doctor
37
+
38
+ [![CI](https://github.com/TheManWhoIsStupid/cuda-doctor/actions/workflows/ci.yml/badge.svg)](https://github.com/TheManWhoIsStupid/cuda-doctor/actions/workflows/ci.yml)
39
+
40
+ > Read-only local diagnostics for CUDA / PyTorch development environments.
41
+ >
42
+ > Detect → Analyze → Explain → Recommend. Never modifies your system.
43
+
44
+ `cuda-doctor` inspects your machine the way a colleague would before helping you
45
+ debug a CUDA problem: it looks at the GPUs, the NVIDIA driver, the CUDA toolkit(s)
46
+ on disk and on `PATH`, the host compiler, and your PyTorch install — then tells
47
+ you what looks wrong, why, and what to do about it.
48
+
49
+ It is inspired by `flutter doctor`: findings are explained in plain language,
50
+ and a completed run always exits `0` (only internal tool failures exit non-zero).
51
+
52
+ ## Quick start
53
+
54
+ Install from PyPI (Python 3.10+):
55
+
56
+ ```bash
57
+ # Linux / macOS
58
+ python -m pip install cuda-doctor
59
+
60
+ # Windows
61
+ py -m pip install cuda-doctor
62
+ ```
63
+
64
+ Then run it:
65
+
66
+ ```bash
67
+ cuda-doctor # full diagnosis, terminal report
68
+ ```
69
+
70
+ > **Install it where your PyTorch lives.** cuda-doctor imports PyTorch
71
+ > in-process from the Python environment it runs in. To diagnose the PyTorch
72
+ > in one of your conda/venv environments, install and run it *inside* that
73
+ > environment:
74
+ >
75
+ > ```bash
76
+ > conda activate my-torch-env
77
+ > python -m pip install cuda-doctor
78
+ > cuda-doctor
79
+ > ```
80
+ >
81
+ > For the same reason, prefer `pip install` over [pipx](https://pipx.pypa.io):
82
+ > a pipx install runs in its own isolated environment and cannot see the
83
+ > PyTorch installed in your conda/venv environment — it would report
84
+ > "torch not installed" even when it is.
85
+
86
+ ```text
87
+ CUDA Doctor v0.1.2
88
+
89
+ System
90
+ OS Linux Ubuntu 22.04.5 LTS (kernel 5.15.0-91-generic)
91
+ ...
92
+ NVIDIA Driver
93
+ Version 580.126.09
94
+ Reported CUDA 13.0
95
+ ...
96
+ Summary
97
+ Status: HEALTHY (2 info)
98
+ ```
99
+
100
+ ## Commands
101
+
102
+ | Command | What it does |
103
+ | --- | --- |
104
+ | `cuda-doctor` | Same as `cuda-doctor diagnose` |
105
+ | `cuda-doctor diagnose` | Full diagnosis, terminal report |
106
+ | `cuda-doctor diagnose --verbose` | Also show info-level notes and probe errors |
107
+ | `cuda-doctor diagnose --format json` | Machine-readable report (schema v1) |
108
+ | `cuda-doctor diagnose --format markdown --output report.md` | Write a shareable report |
109
+ | `cuda-doctor info` | Tool metadata: version, checks, issue codes |
110
+ | `cuda-doctor --version` | Version |
111
+
112
+ `python -m cuda_doctor …` works identically to the `cuda-doctor` entry point.
113
+
114
+ **Exit codes:** `0` the diagnosis ran (regardless of findings) · `2` internal
115
+ fatal error. Findings never change the exit code — this is a diagnostician, not
116
+ a CI gate.
117
+
118
+ ## What it checks (v0.1)
119
+
120
+ | Area | Codes | Highlights |
121
+ | --- | --- | --- |
122
+ | GPU | `GPU001`–`GPU003` | nvidia-smi missing, no GPUs, smi execution failure |
123
+ | Driver | `DRV001`–`DRV002` | unknown driver version; driver below the documented minimum for the toolkit's CUDA generation |
124
+ | CUDA | `CUDA001`–`CUDA006` | no nvcc; CUDA_HOME unset/invalid; multiple toolkits; multiple CUDA bins in PATH; nvcc ≠ CUDA_HOME |
125
+ | PyTorch | `TORCH001`–`TORCH006` | not installed; import failures (with known-signature advice); `is_available()` False; CPU-only wheel; runtime vs toolkit; runtime from a newer CUDA generation than the driver |
126
+ | Compiler | `CMP001`–`CMP002` | no host compiler; gcc/Visual Studio outside the toolkit's supported range |
127
+ | Environment | `ENV001`–`ENV004` | stale CUDA paths; duplicates; conflicting `LD_LIBRARY_PATH`; older CUDA shadowing newer in PATH |
128
+
129
+ Every finding carries a stable issue code, evidence, and concrete
130
+ recommendations. Example reports: [`examples/sample_report.md`](examples/sample_report.md)
131
+ · [`examples/sample_report.json`](examples/sample_report.json).
132
+
133
+ ### The nuance that matters: three different "CUDA versions"
134
+
135
+ A machine reports three unrelated CUDA versions, and most false alarms in CUDA
136
+ debugging tools come from comparing the wrong pair:
137
+
138
+ 1. **The local toolkit** (`nvcc --version`) — what you *compile* with.
139
+ 2. **PyTorch's bundled runtime** (`torch.version.cuda`) — the CUDA libraries
140
+ shipped inside the wheel; official wheels bundle their own runtime, so it
141
+ does not have to match the local toolkit (`TORCH004` stays INFO).
142
+ 3. **The driver's CUDA UMD version** (the `CUDA Version:` line in
143
+ `nvidia-smi`) — the toolkit generation the driver was *validated with*.
144
+ It is **not a hard ceiling**.
145
+
146
+ That third point is the one most tools get wrong. Since CUDA 11, NVIDIA
147
+ supports **CUDA minor-version compatibility**: within a CUDA major family
148
+ (e.g. any CUDA 12.x), applications built with a newer minor release run on
149
+ older drivers of the same generation, as long as the driver meets the
150
+ documented family minimum (Linux 525.60.13 / Windows 528.33 for CUDA 12.x;
151
+ for CUDA 13.x the documented rule is the R580 driver branch, i.e. >= 580).
152
+ So "toolkit 12.6, nvidia-smi says 12.2" is at most an informational note
153
+ (`DRV002` INFO), not an error — with the caveats that newer
154
+ driver-dependent features and newer PTX may still need a driver update.
155
+
156
+ What *is* a genuine error is a **generation gap** — a CUDA 13 toolkit or
157
+ PyTorch runtime on a CUDA 12-generation driver (`DRV002`/`TORCH006`) — and
158
+ even then only when CUDA is not observed working: if
159
+ `torch.cuda.is_available()` is `True`, observed runtime success always
160
+ overrides the static version comparison.
161
+
162
+ ## Platforms
163
+
164
+ - **Linux** — first-class; developed and continuously smoke-tested on Ubuntu
165
+ 22.04 with NVIDIA H20 GPUs and 4 parallel CUDA toolkit installations.
166
+ - **Windows** — supported (separate code paths for `CUDA_PATH*` variables,
167
+ Visual Studio detection via vswhere, `CREATE_NO_WINDOW` on subprocesses).
168
+ Automated tests cover the Windows code paths with simulated environments;
169
+ real-hardware validation is ongoing.
170
+ - **macOS** — runs and reports "no NVIDIA driver" as informational (Apple
171
+ Silicon is out of scope for v0.1).
172
+
173
+ ## Privacy
174
+
175
+ Reports are designed to be shareable:
176
+
177
+ - your home directory is rewritten to `~`, leftover usernames to `<user>`;
178
+ - hostname and username are never collected in the first place;
179
+ - `PATH`/`LD_LIBRARY_PATH` are shown only as the CUDA-relevant subset, never
180
+ dumped in full;
181
+ - nvidia-smi output excerpts are truncated.
182
+
183
+ Still, a JSON report describes your hardware and software stack — read it
184
+ before posting publicly.
185
+
186
+ ## Architecture
187
+
188
+ ```
189
+ CLI (Typer) ─ CollectionRunner ─▶ Collectors (facts only)
190
+ │ subprocess (no shell, timeouts),
191
+ │ filesystem, env, torch import
192
+ ▼
193
+ EnvironmentSnapshot
194
+ (dataclasses; absence = None)
195
+ │
196
+ DiagnosisEngine (24 checks)
197
+ + bundled compatibility JSON
198
+ ▼
199
+ Issues + Summary
200
+ ▼
201
+ Reporters: terminal / JSON / Markdown
202
+ ```
203
+
204
+ Key invariants (see `AGENTS.md`):
205
+
206
+ - **Collectors never judge; checks never collect.** Rules are pure functions of
207
+ the snapshot (+ compatibility data), which makes them unit-testable without
208
+ hardware.
209
+ - **Safe failure over crashes.** Every external probe is guarded; a failing
210
+ collector surfaces as data, not an exception.
211
+ - **Compatibility knowledge is data**, versioned JSON inside the package
212
+ (`src/cuda_doctor/data/`), updatable without touching logic.
213
+ - **Read-only, always.** v0.1 executes no command that modifies the system.
214
+
215
+ ## Limitations (v0.1)
216
+
217
+ - Single-user, single-machine scope; no container/WSL-specific detection.
218
+ - Compatibility decisions are deliberately **conservative**: driver minimums
219
+ follow NVIDIA's documented CUDA minor-version-compatibility baselines per
220
+ major family, and anything the bundled knowledge does not cover — a future
221
+ CUDA major (e.g. CUDA 14 before the data ships), an unlisted toolkit minor
222
+ for compiler rules, or an unreported driver version — is reported as
223
+ **unknown**, never guessed from older versions.
224
+ - Compiler compatibility tables are coarse and worded as *potential* issues;
225
+ the definitive source is always the CUDA Installation Guide for your
226
+ toolkit version.
227
+ - No conda-environment awareness beyond what `PATH`/env vars imply.
228
+ - nvidia-smi is the only GPU source; `NVML`/`lspci` fallbacks are future work.
229
+ - Chinese localization is planned (the maintainers are bilingual); v0.1 output
230
+ is English.
231
+
232
+ ## Development
233
+
234
+ ```bash
235
+ bash scripts/dev_install.sh # Linux/macOS (pip install -e ".[dev]")
236
+ # or: pwsh scripts/dev_install.ps1 (Windows)
237
+
238
+ pytest # 310 tests: unit + integration (hermetic)
239
+ ruff check src tests # lint
240
+ mypy # types (strict-ish: disallow_untyped_defs)
241
+ ```
242
+
243
+ CI runs the same commands on Ubuntu and Windows across Python 3.10–3.13
244
+ (`.github/workflows/ci.yml`) — no GPU, driver, CUDA, or PyTorch required.
245
+
246
+ The test suite needs **no GPU and no CUDA**: collectors run against an injected
247
+ fake command runner, and real parser fixtures captured from actual H20 /
248
+ RTX 4090 machines live under `tests/fixtures/`.
249
+
250
+ ### Repository layout
251
+
252
+ ```
253
+ src/cuda_doctor/
254
+ ├── cli.py # Typer app: diagnose / info / --version
255
+ ├── core/ # models, enums, CollectionRunner, exceptions
256
+ ├── collectors/ # one module per fact source
257
+ ├── checks/ # 24 diagnostic rules (pure)
258
+ ├── diagnosis/ # engine, Issue/Summary, recommendations
259
+ ├── compatibility/ # driver/compiler/torch knowledge + JSON loading
260
+ ├── reporters/ # terminal (Rich), JSON, Markdown
261
+ ├── data/ # bundled compatibility tables
262
+ └── utils/ # commands, parsing, paths, redaction, versions
263
+ ```
264
+
265
+ ## Roadmap (v0.2+)
266
+
267
+ - NVML and `lspci` fallbacks when nvidia-smi is absent or broken.
268
+ - Conda-aware environment inspection.
269
+ - `--json-schema` self-description and a stable JSON schema contract test.
270
+ - WSL detection and WSL-specific driver mismatch explanations.
271
+ - Chinese output (`--lang zh`).
272
+ - `cuda-doctor fix --dry-run` advisory mode (still no modifications in v0.2).
273
+
274
+ ## License
275
+
276
+ MIT — see `LICENSE`.
@@ -0,0 +1,241 @@
1
+ # cuda-doctor
2
+
3
+ [![CI](https://github.com/TheManWhoIsStupid/cuda-doctor/actions/workflows/ci.yml/badge.svg)](https://github.com/TheManWhoIsStupid/cuda-doctor/actions/workflows/ci.yml)
4
+
5
+ > Read-only local diagnostics for CUDA / PyTorch development environments.
6
+ >
7
+ > Detect → Analyze → Explain → Recommend. Never modifies your system.
8
+
9
+ `cuda-doctor` inspects your machine the way a colleague would before helping you
10
+ debug a CUDA problem: it looks at the GPUs, the NVIDIA driver, the CUDA toolkit(s)
11
+ on disk and on `PATH`, the host compiler, and your PyTorch install — then tells
12
+ you what looks wrong, why, and what to do about it.
13
+
14
+ It is inspired by `flutter doctor`: findings are explained in plain language,
15
+ and a completed run always exits `0` (only internal tool failures exit non-zero).
16
+
17
+ ## Quick start
18
+
19
+ Install from PyPI (Python 3.10+):
20
+
21
+ ```bash
22
+ # Linux / macOS
23
+ python -m pip install cuda-doctor
24
+
25
+ # Windows
26
+ py -m pip install cuda-doctor
27
+ ```
28
+
29
+ Then run it:
30
+
31
+ ```bash
32
+ cuda-doctor # full diagnosis, terminal report
33
+ ```
34
+
35
+ > **Install it where your PyTorch lives.** cuda-doctor imports PyTorch
36
+ > in-process from the Python environment it runs in. To diagnose the PyTorch
37
+ > in one of your conda/venv environments, install and run it *inside* that
38
+ > environment:
39
+ >
40
+ > ```bash
41
+ > conda activate my-torch-env
42
+ > python -m pip install cuda-doctor
43
+ > cuda-doctor
44
+ > ```
45
+ >
46
+ > For the same reason, prefer `pip install` over [pipx](https://pipx.pypa.io):
47
+ > a pipx install runs in its own isolated environment and cannot see the
48
+ > PyTorch installed in your conda/venv environment — it would report
49
+ > "torch not installed" even when it is.
50
+
51
+ ```text
52
+ CUDA Doctor v0.1.2
53
+
54
+ System
55
+ OS Linux Ubuntu 22.04.5 LTS (kernel 5.15.0-91-generic)
56
+ ...
57
+ NVIDIA Driver
58
+ Version 580.126.09
59
+ Reported CUDA 13.0
60
+ ...
61
+ Summary
62
+ Status: HEALTHY (2 info)
63
+ ```
64
+
65
+ ## Commands
66
+
67
+ | Command | What it does |
68
+ | --- | --- |
69
+ | `cuda-doctor` | Same as `cuda-doctor diagnose` |
70
+ | `cuda-doctor diagnose` | Full diagnosis, terminal report |
71
+ | `cuda-doctor diagnose --verbose` | Also show info-level notes and probe errors |
72
+ | `cuda-doctor diagnose --format json` | Machine-readable report (schema v1) |
73
+ | `cuda-doctor diagnose --format markdown --output report.md` | Write a shareable report |
74
+ | `cuda-doctor info` | Tool metadata: version, checks, issue codes |
75
+ | `cuda-doctor --version` | Version |
76
+
77
+ `python -m cuda_doctor …` works identically to the `cuda-doctor` entry point.
78
+
79
+ **Exit codes:** `0` the diagnosis ran (regardless of findings) · `2` internal
80
+ fatal error. Findings never change the exit code — this is a diagnostician, not
81
+ a CI gate.
82
+
83
+ ## What it checks (v0.1)
84
+
85
+ | Area | Codes | Highlights |
86
+ | --- | --- | --- |
87
+ | GPU | `GPU001`–`GPU003` | nvidia-smi missing, no GPUs, smi execution failure |
88
+ | Driver | `DRV001`–`DRV002` | unknown driver version; driver below the documented minimum for the toolkit's CUDA generation |
89
+ | CUDA | `CUDA001`–`CUDA006` | no nvcc; CUDA_HOME unset/invalid; multiple toolkits; multiple CUDA bins in PATH; nvcc ≠ CUDA_HOME |
90
+ | PyTorch | `TORCH001`–`TORCH006` | not installed; import failures (with known-signature advice); `is_available()` False; CPU-only wheel; runtime vs toolkit; runtime from a newer CUDA generation than the driver |
91
+ | Compiler | `CMP001`–`CMP002` | no host compiler; gcc/Visual Studio outside the toolkit's supported range |
92
+ | Environment | `ENV001`–`ENV004` | stale CUDA paths; duplicates; conflicting `LD_LIBRARY_PATH`; older CUDA shadowing newer in PATH |
93
+
94
+ Every finding carries a stable issue code, evidence, and concrete
95
+ recommendations. Example reports: [`examples/sample_report.md`](examples/sample_report.md)
96
+ · [`examples/sample_report.json`](examples/sample_report.json).
97
+
98
+ ### The nuance that matters: three different "CUDA versions"
99
+
100
+ A machine reports three unrelated CUDA versions, and most false alarms in CUDA
101
+ debugging tools come from comparing the wrong pair:
102
+
103
+ 1. **The local toolkit** (`nvcc --version`) — what you *compile* with.
104
+ 2. **PyTorch's bundled runtime** (`torch.version.cuda`) — the CUDA libraries
105
+ shipped inside the wheel; official wheels bundle their own runtime, so it
106
+ does not have to match the local toolkit (`TORCH004` stays INFO).
107
+ 3. **The driver's CUDA UMD version** (the `CUDA Version:` line in
108
+ `nvidia-smi`) — the toolkit generation the driver was *validated with*.
109
+ It is **not a hard ceiling**.
110
+
111
+ That third point is the one most tools get wrong. Since CUDA 11, NVIDIA
112
+ supports **CUDA minor-version compatibility**: within a CUDA major family
113
+ (e.g. any CUDA 12.x), applications built with a newer minor release run on
114
+ older drivers of the same generation, as long as the driver meets the
115
+ documented family minimum (Linux 525.60.13 / Windows 528.33 for CUDA 12.x;
116
+ for CUDA 13.x the documented rule is the R580 driver branch, i.e. >= 580).
117
+ So "toolkit 12.6, nvidia-smi says 12.2" is at most an informational note
118
+ (`DRV002` INFO), not an error — with the caveats that newer
119
+ driver-dependent features and newer PTX may still need a driver update.
120
+
121
+ What *is* a genuine error is a **generation gap** — a CUDA 13 toolkit or
122
+ PyTorch runtime on a CUDA 12-generation driver (`DRV002`/`TORCH006`) — and
123
+ even then only when CUDA is not observed working: if
124
+ `torch.cuda.is_available()` is `True`, observed runtime success always
125
+ overrides the static version comparison.
126
+
127
+ ## Platforms
128
+
129
+ - **Linux** — first-class; developed and continuously smoke-tested on Ubuntu
130
+ 22.04 with NVIDIA H20 GPUs and 4 parallel CUDA toolkit installations.
131
+ - **Windows** — supported (separate code paths for `CUDA_PATH*` variables,
132
+ Visual Studio detection via vswhere, `CREATE_NO_WINDOW` on subprocesses).
133
+ Automated tests cover the Windows code paths with simulated environments;
134
+ real-hardware validation is ongoing.
135
+ - **macOS** — runs and reports "no NVIDIA driver" as informational (Apple
136
+ Silicon is out of scope for v0.1).
137
+
138
+ ## Privacy
139
+
140
+ Reports are designed to be shareable:
141
+
142
+ - your home directory is rewritten to `~`, leftover usernames to `<user>`;
143
+ - hostname and username are never collected in the first place;
144
+ - `PATH`/`LD_LIBRARY_PATH` are shown only as the CUDA-relevant subset, never
145
+ dumped in full;
146
+ - nvidia-smi output excerpts are truncated.
147
+
148
+ Still, a JSON report describes your hardware and software stack — read it
149
+ before posting publicly.
150
+
151
+ ## Architecture
152
+
153
+ ```
154
+ CLI (Typer) ─ CollectionRunner ─▶ Collectors (facts only)
155
+ │ subprocess (no shell, timeouts),
156
+ │ filesystem, env, torch import
157
+ ▼
158
+ EnvironmentSnapshot
159
+ (dataclasses; absence = None)
160
+ │
161
+ DiagnosisEngine (24 checks)
162
+ + bundled compatibility JSON
163
+ ▼
164
+ Issues + Summary
165
+ ▼
166
+ Reporters: terminal / JSON / Markdown
167
+ ```
168
+
169
+ Key invariants (see `AGENTS.md`):
170
+
171
+ - **Collectors never judge; checks never collect.** Rules are pure functions of
172
+ the snapshot (+ compatibility data), which makes them unit-testable without
173
+ hardware.
174
+ - **Safe failure over crashes.** Every external probe is guarded; a failing
175
+ collector surfaces as data, not an exception.
176
+ - **Compatibility knowledge is data**, versioned JSON inside the package
177
+ (`src/cuda_doctor/data/`), updatable without touching logic.
178
+ - **Read-only, always.** v0.1 executes no command that modifies the system.
179
+
180
+ ## Limitations (v0.1)
181
+
182
+ - Single-user, single-machine scope; no container/WSL-specific detection.
183
+ - Compatibility decisions are deliberately **conservative**: driver minimums
184
+ follow NVIDIA's documented CUDA minor-version-compatibility baselines per
185
+ major family, and anything the bundled knowledge does not cover — a future
186
+ CUDA major (e.g. CUDA 14 before the data ships), an unlisted toolkit minor
187
+ for compiler rules, or an unreported driver version — is reported as
188
+ **unknown**, never guessed from older versions.
189
+ - Compiler compatibility tables are coarse and worded as *potential* issues;
190
+ the definitive source is always the CUDA Installation Guide for your
191
+ toolkit version.
192
+ - No conda-environment awareness beyond what `PATH`/env vars imply.
193
+ - nvidia-smi is the only GPU source; `NVML`/`lspci` fallbacks are future work.
194
+ - Chinese localization is planned (the maintainers are bilingual); v0.1 output
195
+ is English.
196
+
197
+ ## Development
198
+
199
+ ```bash
200
+ bash scripts/dev_install.sh # Linux/macOS (pip install -e ".[dev]")
201
+ # or: pwsh scripts/dev_install.ps1 (Windows)
202
+
203
+ pytest # 310 tests: unit + integration (hermetic)
204
+ ruff check src tests # lint
205
+ mypy # types (strict-ish: disallow_untyped_defs)
206
+ ```
207
+
208
+ CI runs the same commands on Ubuntu and Windows across Python 3.10–3.13
209
+ (`.github/workflows/ci.yml`) — no GPU, driver, CUDA, or PyTorch required.
210
+
211
+ The test suite needs **no GPU and no CUDA**: collectors run against an injected
212
+ fake command runner, and real parser fixtures captured from actual H20 /
213
+ RTX 4090 machines live under `tests/fixtures/`.
214
+
215
+ ### Repository layout
216
+
217
+ ```
218
+ src/cuda_doctor/
219
+ ├── cli.py # Typer app: diagnose / info / --version
220
+ ├── core/ # models, enums, CollectionRunner, exceptions
221
+ ├── collectors/ # one module per fact source
222
+ ├── checks/ # 24 diagnostic rules (pure)
223
+ ├── diagnosis/ # engine, Issue/Summary, recommendations
224
+ ├── compatibility/ # driver/compiler/torch knowledge + JSON loading
225
+ ├── reporters/ # terminal (Rich), JSON, Markdown
226
+ ├── data/ # bundled compatibility tables
227
+ └── utils/ # commands, parsing, paths, redaction, versions
228
+ ```
229
+
230
+ ## Roadmap (v0.2+)
231
+
232
+ - NVML and `lspci` fallbacks when nvidia-smi is absent or broken.
233
+ - Conda-aware environment inspection.
234
+ - `--json-schema` self-description and a stable JSON schema contract test.
235
+ - WSL detection and WSL-specific driver mismatch explanations.
236
+ - Chinese output (`--lang zh`).
237
+ - `cuda-doctor fix --dry-run` advisory mode (still no modifications in v0.2).
238
+
239
+ ## License
240
+
241
+ MIT — see `LICENSE`.
@@ -0,0 +1,99 @@
1
+ [build-system]
2
+ requires = ["setuptools>=77.0.3"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "cuda-doctor"
7
+ description = "Local CUDA / PyTorch development environment diagnostic tool"
8
+ readme = "README.md"
9
+ requires-python = ">=3.10"
10
+ license = "MIT"
11
+ license-files = ["LICENSE"]
12
+ authors = [{ name = "cuda-doctor contributors" }]
13
+ keywords = ["cuda", "pytorch", "nvidia", "gpu", "diagnostics", "developer-tools"]
14
+ classifiers = [
15
+ "Development Status :: 3 - Alpha",
16
+ "Environment :: Console",
17
+ "Intended Audience :: Developers",
18
+ "Operating System :: Microsoft :: Windows",
19
+ "Operating System :: POSIX :: Linux",
20
+ "Programming Language :: Python :: 3",
21
+ "Programming Language :: Python :: 3.10",
22
+ "Programming Language :: Python :: 3.11",
23
+ "Programming Language :: Python :: 3.12",
24
+ "Programming Language :: Python :: 3.13",
25
+ "Topic :: Software Development :: Debuggers",
26
+ "Topic :: System :: Systems Administration",
27
+ ]
28
+ dependencies = [
29
+ "typer>=0.9",
30
+ "rich>=13.0",
31
+ ]
32
+ dynamic = ["version"]
33
+
34
+ [project.urls]
35
+ Homepage = "https://github.com/TheManWhoIsStupid/cuda-doctor"
36
+ Issues = "https://github.com/TheManWhoIsStupid/cuda-doctor/issues"
37
+ Changelog = "https://github.com/TheManWhoIsStupid/cuda-doctor/blob/main/CHANGELOG.md"
38
+
39
+ [project.optional-dependencies]
40
+ dev = [
41
+ "pytest>=7.0",
42
+ "pytest-cov",
43
+ "ruff>=0.4",
44
+ "mypy>=1.8",
45
+ "pre-commit",
46
+ ]
47
+
48
+ [project.scripts]
49
+ cuda-doctor = "cuda_doctor.cli:main"
50
+
51
+ [tool.setuptools.dynamic]
52
+ version = { attr = "cuda_doctor.version.__version__" }
53
+
54
+ [tool.setuptools.packages.find]
55
+ where = ["src"]
56
+
57
+ [tool.setuptools.package-data]
58
+ cuda_doctor = ["py.typed", "data/*.json"]
59
+
60
+ [tool.pytest.ini_options]
61
+ testpaths = ["tests"]
62
+ addopts = "-q"
63
+ # Tests import each other as `tests.*` (namespace package); bare `pytest`
64
+ # does not put the repo root on sys.path the way `python -m pytest` does.
65
+ pythonpath = ["."]
66
+
67
+ [tool.coverage.run]
68
+ source = ["cuda_doctor"]
69
+
70
+ [tool.ruff]
71
+ line-length = 100
72
+ src = ["src", "tests"]
73
+
74
+ [tool.ruff.lint]
75
+ select = [
76
+ "E", # pycodestyle errors
77
+ "W", # pycodestyle warnings
78
+ "F", # pyflakes
79
+ "I", # isort
80
+ "UP", # pyupgrade
81
+ "B", # bugbear
82
+ "C4", # comprehensions
83
+ "SIM", # simplify
84
+ "RUF", # ruff-specific
85
+ ]
86
+
87
+ [tool.ruff.lint.per-file-ignores]
88
+ # typer.Option() in parameter defaults is the framework's intended idiom.
89
+ "src/cuda_doctor/cli.py" = ["B008"]
90
+
91
+ [tool.mypy]
92
+ python_version = "3.10"
93
+ mypy_path = "src"
94
+ files = ["src"]
95
+ warn_unused_ignores = true
96
+ warn_redundant_casts = true
97
+ no_implicit_optional = true
98
+ disallow_untyped_defs = true
99
+ check_untyped_defs = true
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,5 @@
1
+ """cuda-doctor: local CUDA / PyTorch development environment diagnostics."""
2
+
3
+ from cuda_doctor.version import __version__
4
+
5
+ __all__ = ["__version__"]
@@ -0,0 +1,6 @@
1
+ """`python -m cuda_doctor` support."""
2
+
3
+ from cuda_doctor.cli import main
4
+
5
+ if __name__ == "__main__":
6
+ main()