doctor
Detect and repair generated artifacts wrongly tracked in git.
doctor scans for generated artifacts that are wrongly tracked in git and, with --fix, untracks them while keeping the files on disk. The _internal/ cache (spec downloads, timestamps, hashes) is machine state that must never be committed — it churns on every fetch and triggers meaningless merge conflicts. In pinned-inputs mode, _generated/ is the same: it's deterministically regenerated from the committed pins, so tracking it causes churn. doctor finds both and repairs the damage.
Usage
chowbea-axios doctor [flags]Requires a git repository. Non-git projects exit cleanly with a message.
What it does
- Detects if you're in a git repository
- Scans
_internal/for tracked files (always checked) - Scans
_generated/for tracked files (only in pinned-inputs mode — non-pinned setups legitimately commit_generated/) - Checks if
.gitignorehas the required ignore rules - Reports problems, or (with
--fix) untracks the artifacts and adds the gitignore rules - Stages the
.gitignorerepair so you can commit it
Without --fix, doctor reports problems and exits non-zero — use it as a CI gate. With --fix, it untracks the files (git rm --cached, keeping them on disk) and ensures the ignore rules exist.
When to use it
- After
init— projects created before the auto-gitignore feature may still track_internal/ - When merge conflicts appear in
_internal/.api-cache.jsonor_internal/openapi.json - After migrating to pinned-inputs mode —
_generated/should stop being committed (see migration guide) - As a CI check —
doctor(without--fix) exits non-zero when artifacts are tracked
Not useful outside git repos.
Flags
| Flag | Short | Description | Default |
|---|---|---|---|
--config | -c | Path to api.config.toml | Auto-detected |
--fix | - | Untrack artifacts and add gitignore rules | false |
--quiet | -q | Suppress non-error output | false |
--verbose | -v | Show detailed output | false |
Examples
Check for problems (report-only)
chowbea-axios doctor
# 3 generated/cache artifact(s) are tracked in git — they churn on every regen and trigger merge conflicts.
# tracked: src/api/_internal/.api-cache.json
# tracked: src/api/_internal/openapi.json
# tracked: src/api/_internal/openapi-normalized.json
# Missing .gitignore rule(s): '_internal/' — regenerable output may get re-committed.
# Run 'chowbea-axios doctor --fix' to untrack the cache and ignore it.Exit code 1 — problems found. The cache files are in the index and will churn on the next fetch, and the gitignore rule is missing.
Note: doctor reports unhealthy even when nothing is tracked but the gitignore rule is missing — --fix adds the rule and stages .gitignore.
Repair (untrack and add gitignore)
chowbea-axios doctor --fix
# Added _internal/ to .gitignore
# Untracked src/api/_internal/ (files kept on disk)
# Repaired. Commit the staged changes to finish.The gitignore rule is added first, then artifacts are removed from the index (git rm --cached) but stay on disk, and .gitignore is staged with the new rule. Commit to finish:
git commit -m "chore: stop tracking _internal cache"Healthy setup
chowbea-axios doctor
# No tracked cache artifacts — generated output is conflict-safe.Exit code 0. Nothing to fix.
Exit codes
| Code | Meaning |
|---|---|
0 | Healthy — no tracked artifacts, or --fix repaired everything |
1 | Problems found (report-only mode), or regeneration failed |
Report-only mode (doctor without --fix) that finds problems exits 1 so it can gate CI. Once --fix repairs them, it succeeds.
What gets checked
Always: _internal/
The cache folder holding:
openapi.json/openapi.yaml— downloaded specopenapi-normalized.json— canonicalized form.api-cache.json— hash + timestamp metadata
These change on every fetch and must never be committed. init gitignores them automatically, but older setups or manual clones may have tracked them.
In pinned-inputs mode only: _generated/
When both api_endpoint and spec_file are set (pinned mode), _generated/ is regenerated from the committed pins (openapi.json, chowbea.bus.json) — tracking it causes the same churn as _internal/. doctor --fix untracks it and adds the _generated/ ignore rule.
Non-pinned setups (no spec_file configured) legitimately commit _generated/ — CI has no pinned spec to regenerate from, so the generated files must be in the repo. doctor skips the _generated/ scan in that mode.
The ignore rules doctor adds are:
_internal/with comment# chowbea-axios cache (timestamps, downloaded specs)_generated/with comment# chowbea-axios generated output (pinned-inputs mode — regenerate with \chowbea-axios generate`)` (only in pinned mode)
How it works
Under the hood, doctor:
- Runs
git ls-files _internal/to list tracked cache files - In pinned mode, also runs
git ls-files _generated/ - Checks if
.gitignorecontains_internal/(and_generated/in pinned mode) - With
--fix:- Runs
git rm --cached _internal/(and_generated/if needed) — files stay on disk - Appends the ignore rules to
.gitignoreif missing - Runs
git add .gitignore
- Runs
The untracked files remain in your working tree — doctor --fix never deletes anything. You can still fetch and generate normally; they just won't be committed anymore.
Pinned-inputs mode detection
Pinned mode is when both api_endpoint and spec_file are configured. When that's true, doctor knows _generated/ is regenerable from the pins and should be gitignored. Otherwise, _generated/ is assumed to be legitimately committed (the "traditional" chowbea-axios setup) and doctor doesn't touch it.
See Pinned Inputs for the full picture.
Error cases
Not a git repository
chowbea-axios doctor
# Not a git repository — nothing to check.Exit code 0. Nothing to do.
--fix fails to untrack
If git rm --cached fails (permissions, locked files, unusual git state), doctor errors and exits non-zero. The error message includes git's output. Fix the underlying issue and re-run.
Related commands
init— auto-gitignores_internal/and_generated/(in pinned mode) from the startresolve— resolves merge conflicts in_generated/fetch— writes to_internal/(the cachedoctorchecks)generate— writes to_generated/sync— the command that updates pinned inputs in pinned mode
CI integration
Use doctor (without --fix) as a CI gate:
# .github/workflows/ci.yml
- name: Check for tracked cache artifacts
run: npx chowbea-axios doctorExits non-zero if someone accidentally committed _internal/ or (in pinned mode) _generated/. The PR goes red, and the commit message is clear: "stop tracking generated artifacts."
Workflow example
Repairing a tracked cache
# Discover the problem
chowbea-axios doctor
# 2 generated/cache artifact(s) are tracked in git...
# Missing .gitignore rule(s): '_internal/' — regenerable output may get re-committed.
# Fix it
chowbea-axios doctor --fix
# Added _internal/ to .gitignore
# Untracked src/api/_internal/ (files kept on disk)
# Commit the repair
git commit -m "chore: stop tracking _internal cache"
# Verify
chowbea-axios doctor
# No tracked cache artifacts — generated output is conflict-safe.Migrating to pinned mode
After you've added the pinned-inputs keys to api.config.toml:
# Stop tracking _generated/ now that it's regenerable from pins
chowbea-axios doctor --fix
# Added _generated/ to .gitignore
# Untracked src/api/_generated/ (files kept on disk)
# Commit as part of the migration
git commit -m "chore: adopt pinned-inputs mode"doctor --fix removes files from the index but keeps them on disk. If you later run git status, they'll appear as untracked (but gitignored) files. That's correct — they're ignored now, so git stops watching them. Don't manually delete them; fetch and generate still need them.