Run apus doctor to repair and migrate an Apus install. This page covers the command, its automation flags, and the read-only lint mode.

You can run Doctor after an update without first starting the Gateway. Plugin health checks use the runtime config prepared by Doctor.

Database migrations use the efficient integrity-check default: whole-database quick_check, full checks of tables the migration rewrites or re-indexes, and foreign-key checks. Use apus doctor --fix --full-integrity-check to check all tables and indexes during migration. Explicit verification, recovery, and compaction keep their existing checks.

If Doctor cannot verify database readiness because a read-only snapshot did not stabilize, let write activity settle and retry the inspection. Doctor still refuses to complete repair, but snapshot contention alone does not call for a database restore. Integrity failures retain backup-restore guidance for the affected database.

When the System agent runs Doctor, it uses a separate process from the same Apus installation. Bulk diagnostic checks can then run without blocking the Gateway's event loop. This uses the existing --non-interactive behavior, including its safe migrations; it does not enable additional repairs. Once started, Doctor finishes and releases its resources before a cancelled caller settles, so cancellation cannot abandon an in-progress migration.

Quick start

apus doctor

Headless and automation modes

--yes

```bash
apus doctor --yes
```

Accept default non-service repairs without prompting and enter maintenance under the [service-preservation and installation-drift rules](/cli/doctor/recovery#gateway-service-recovery).

--fix

```bash
apus doctor --fix
```

Apply recommended non-service repairs without prompting (`--repair` is an alias) and enter maintenance under the [service-preservation and installation-drift rules](/cli/doctor/recovery#gateway-service-recovery).

--lint

```bash
apus doctor --lint
apus doctor --lint --json
```

Run structured health checks for CI or preflight automation. Read-only: no
prompts, repairs, migrations, restarts, or state writes.

--fix --force

```bash
apus doctor --fix --force
```

Apply aggressive config/state repairs too. Repair maintenance uses the same service-preservation and installation-drift rules; use `apus gateway install --force` from the intended installation to replace its launcher and managed environment.

--non-interactive

```bash
apus doctor --non-interactive
```

Run without prompts, applying only safe migrations (config normalization +
on-disk state moves). Skips restart/service/sandbox actions that need human
confirmation. Legacy state migrations still run automatically when detected.
Add `--fix` for all supported startup-blocking repairs without prompts,
including workspace setup, session stores, exec approvals, and audit schema
migrations. Explicit repair checks ownership before database snapshots;
another live owner must stop before repair can proceed. Malformed or
conflicting retained files require the manual recovery named in the error.

When the shared database is already current, preparation leaves the running
Gateway's worker environments available. Actual schema repairs retire the old
database resources before later maintenance continues, including when repair
cleanup fails.

--deep

```bash
apus doctor --deep
```

Scan system services for extra gateway installs (launchd/systemd/schtasks).

If a plugin cannot load because its source capture runs out of disk space, Doctor reports ENOSPC with the underlying filesystem error. Free space on the affected filesystem and rerun Doctor. Standalone --non-interactive Doctor exits with code 1; update-invoked Doctor records the problem as a warning so the update can continue while keeping the diagnostic visible.

With APUS_GATEWAY_STARTUP_TRACE=1, Doctor prints per-phase timings (doctor.* and cli.bootstrap.* lines) to stderr.

To review changes before writing, open the config file first:

cat ~/.apus/apus.json

Read-only lint mode

apus doctor --lint is the automation-friendly sibling of apus doctor --fix. They share the same Doctor rule registry, but they do not select or act on rules in the same way:

Mode Prompts Writes config/state Output Use it for
apus doctor yes yes, safe migrations and confirmed repairs friendly health report guided checks and repairs
apus doctor --json no no JSON advisory report machine-readable operator checks
apus doctor --fix sometimes yes, with repair policy friendly repair log applying approved repairs
apus doctor --lint no no structured findings CI, preflight, and review gates

Default doctor --lint runs the broad-safe automation profile: checks that are static, local, and useful in CI or preflight output. It skips opt-in checks that are advisory, environment-sensitive, live-service dependent, account/workspace inventory, or historical cleanup. Use doctor --lint --all when you want the full registered lint audit, including those opt-in checks, or --only <id> for a targeted check.

doctor --fix does not use the lint default profile and does not accept --all. It runs Doctor's ordered repair path: modern health checks may provide an optional repair() implementation, and older areas still use their legacy Doctor repair flow. Some lint findings are intentionally diagnostic only, so a check appearing in --lint --all does not mean --fix will mutate that area. The contract separates detect() (reports findings) from repair() (reports changes/diffs/side effects), which keeps a path open for a future doctor --fix --dry-run without turning lint checks into mutation planners.

Some built-in checks are default-disabled internally so they stay available to --all, --only, and Doctor repair flows without becoming part of the default doctor --lint automation profile. Finding severity is still emitted per finding (info, warning, or error); default selection is not a severity level.

apus doctor --lint
apus doctor --lint --severity-min warning
apus doctor --lint --json
apus doctor --lint --all
apus doctor --lint --only core/doctor/gateway-config --json

JSON output fields:

Exit codes:

Code Meaning
0 no findings at or above the selected threshold
1 one or more findings met the selected threshold
2 command/runtime failure before findings could be emitted

These threshold-based exit codes belong to explicit --lint mode, with or without --json. Bare apus doctor --json preserves ordinary Doctor's advisory exit 0 after producing its payload; machine consumers should read ok and findings. Fatal errors before output remain nonzero.

During apus update, failure to remove Doctor's disposable lint snapshot is recorded as an update warning and does not block the update. Standalone doctor --lint still reports that cleanup failure as an error. The update keeps the checks' actual findings; cleanup warnings do not hide other failures.

Flags: