Doctor CLI Reference

Command reference for stella doctor — the Stella Ops self-service diagnostics CLI.

This page is for operators, DevOps engineers, and support staff who run Doctor from a shell or wire it into CI/CD. For an overview of what Doctor is and how it works, see the Doctor Overview; for the full technical design, see the Doctor Capabilities Specification.

Commands

stella doctor

Run diagnostic checks. stella doctor is shorthand for stella doctor run; the two are interchangeable.

stella doctor [options]

Options

OptionShortTypeDefaultDescription
--format-fstringtexttext, json or markdown
--mode-mstringnormalquick, normal or full
--category-cstringallFilter by a category shown in the plugin catalog
--tag-tstring[]allFilter by tags; may be repeated
--checkstringallRun one check by ID
--timeoutinteger30Per-check timeout in seconds
--parallel-pinteger4Maximum parallel check executions
--output-opathstdoutWrite the report to a file
--fail-on-warnflagfalseReturn a nonzero exit status for warnings
--watch-wflagfalseRepeat checks
--intervalinteger60Watch interval in seconds
--env-estringconfiguredTarget environment
--verbose-vflagfalseDetailed output

Use category and check IDs reported by stella doctor list. The run/list commands operate on the local plugin engine; service-owned checks use the HTTP surfaces linked below.

Examples

# Quick health check
stella doctor

# Full diagnostic
stella doctor --mode full

# Database checks only
stella doctor --category database

# Checks tagged for quick execution
stella doctor --tag quick

# Single check
stella doctor --check check.core.disk

# JSON output (for CI/CD)
stella doctor --format json

# Treat warnings as a failed automation check
stella doctor --fail-on-warn

# Markdown report
stella doctor --format markdown > doctor-report.md

# Verbose with all evidence
stella doctor --verbose

# Custom timeout and parallelism
stella doctor --timeout 60 --parallel 2

stella doctor fix

Apply non-destructive fixes from a Doctor report.

stella doctor fix --from report.json [--apply]

Options

OptionTypeDefaultDescription
--frompathrequiredPath to JSON report with how_to_fix commands
--applyflagfalseExecute fixes (default is dry-run preview)

The doctor fix command executes only permitted non-destructive commands. Other fixes are printed as guidance. The separate doctor remediate command follows the execution gates in ADR-026.

Examples

# Preview fixes (dry-run)
stella doctor fix --from doctor-report.json

# Apply safe fixes
stella doctor fix --from doctor-report.json --apply

stella doctor remediate

Run a check’s declared self-healing remediation through the gated runner (ADR-026 D5). This is the gated-runner path; stella doctor fix remains the report-replay path. The verb resolves the failing check’s declared heal, then plans/executes it under the gate (off by default; per-action opt-in; non-destructive only within a maintenance window + rate-limit; destructive only behind approval token + dry-run preview + active window + durable audit + the doctor:remediate scope, else manual guidance). Execution is local-only (air-gap). Run by the CLI in-process; the equivalent HTTP surface is POST /api/v1/doctor/remediate.

stella doctor remediate --check <id> [--action <id>] [--dry-run] [--approval-token <tok>]

Options

OptionTypeDefaultDescription
--checkstringrequiredThe failing check id to remediate (e.g. check.servicegraph.valkey)
--actionstringRestrict to a single declared heal-action id within the check’s declaration
--dry-runflagfalseProduce a non-mutating preview only (no changes)
--approval-tokenstringExplicit per-run approval token required for a destructive (or approval-requiring) action

The CLI runs DB-less, so the durable-audit gate element is absent: a destructive heal always falls back to manual guidance from the CLI. Use the POST /api/v1/doctor/remediate endpoint (durable Postgres audit) to execute a gated destructive heal.

Examples

# Dry-run preview of a check's declared heal
stella doctor remediate --check check.servicegraph.valkey --dry-run

# Attempt a single non-destructive action (auto-runs only if opted-in + in maintenance window)
stella doctor remediate --check check.servicegraph.valkey --action heal.servicegraph.valkey.restart

stella doctor export

Generate a diagnostic bundle for support.

stella doctor export [options]

Options

OptionTypeDefaultDescription
--outputpathdiagnostic-bundle.zipOutput file path
--include-logsflagfalseInclude recent log files
--log-durationduration1hDuration of logs to include
--no-configflagfalseExclude configuration

Duration Format

Duration values can be specified as:

Examples

# Basic export
stella doctor export --output diagnostic.zip

# Include logs from last 4 hours
stella doctor export --include-logs --log-duration 4h

# Without configuration (for privacy)
stella doctor export --no-config

# Full bundle with logs
stella doctor export \
  --output support-bundle.zip \
  --include-logs \
  --log-duration 24h

Bundle Contents

The export creates a ZIP archive containing:

diagnostic-bundle.zip
+-- README.md                 # Bundle contents guide
+-- doctor-report.json        # Full diagnostic report
+-- doctor-report.md          # Human-readable report
+-- environment.json          # Environment information
+-- system-info.json          # System details
+-- config-sanitized.json     # Configuration (secrets redacted)
+-- logs/                     # Log files (if --include-logs)
    +-- stellaops-*.log

stella doctor list

List checks available to the local plugin engine. This command does not fetch service doctor-check/v1 results or list owned-state size/budget checks. Use the owned-state HTTP surfaces for installed service storage measurements.

stella doctor list [options]

Options

OptionTypeDescription
--categorystringFilter by category
--tag, -tstring[]Filter by tag
--verboseflagInclude description, plugin, tags and estimated duration

Examples

# List local plugin checks
stella doctor list

# List database checks
stella doctor list --category database

# Include plugin metadata in the text listing
stella doctor list --verbose

Exit Codes

CodeNameDescription
0SuccessAll checks passed
1WarningsOne or more warnings, no failures
2FailuresOne or more checks failed
3EngineErrorDoctor engine error
4InvalidArgsInvalid command arguments
5TimeoutTimeout exceeded

Using Exit Codes in Scripts

#!/bin/bash

stella doctor --format json > report.json
exit_code=$?

case $exit_code in
    0)
        echo "All checks passed"
        ;;
    1)
        echo "Warnings detected - review report"
        ;;
    2)
        echo "Failures detected - action required"
        exit 1
        ;;
    *)
        echo "Doctor error (code: $exit_code)"
        exit 1
        ;;
esac

CI/CD Integration

GitHub Actions

- name: Run Stella Doctor
  run: |
    stella doctor --format json --fail-on-warn > doctor-report.json
    exit_code=$?
    if [ $exit_code -eq 2 ]; then
      echo "::error::Doctor checks failed"
      cat doctor-report.json
      exit 1
    fi

GitLab CI

doctor:
  stage: validate
  script:
    - stella doctor --format json > doctor-report.json
  artifacts:
    when: always
    paths:
      - doctor-report.json
  allow_failure:
    exit_codes:
      - 1  # Allow warnings

Jenkins

stage('Health Check') {
    steps {
        script {
            def result = sh(
                script: 'stella doctor --format json',
                returnStatus: true
            )
            if (result == 2) {
                error "Doctor checks failed"
            }
        }
    }
}

Output Formats

Text Format (Default)

Human-readable console output with colors and formatting.

Stella Ops Doctor
=================

Running 47 checks across 8 plugins...

[PASS] check.config.required
  All required configuration values are present

[FAIL] check.database.migrations.pending
  Diagnosis: 3 pending migrations in schema 'auth'

  Fix Steps:
    # Restart the owning service; it converges its own schema at startup
    docker compose up -d --force-recreate authority

--------------------------------------------------------------------------------
Summary: 46 passed, 0 warnings, 1 failed (47 total)
Duration: 8.3s
--------------------------------------------------------------------------------

JSON Format

Machine-readable format for automation:

{
  "summary": {
    "total": 47,
    "passed": 46,
    "warnings": 0,
    "failures": 1,
    "skipped": 0,
    "duration": "PT8.3S"
  },
  "executedAt": "2026-01-12T14:30:00Z",
  "checks": [
    {
      "checkId": "check.config.required",
      "pluginId": "stellaops.doctor.core",
      "category": "Core",
      "severity": "Pass",
      "diagnosis": "All required configuration values are present",
      "evidence": {
        "description": "Configuration validated",
        "data": {
          "configSource": "appsettings.json",
          "keysChecked": "42"
        }
      },
      "duration": "PT0.012S"
    },
    {
      "checkId": "check.database.migrations.pending",
      "pluginId": "stellaops.doctor.database",
      "category": "Database",
      "severity": "Fail",
      "diagnosis": "3 pending migrations in schema 'auth'",
      "evidence": {
        "description": "Migration status",
        "data": {
          "schema": "auth",
          "pendingCount": "3"
        }
      },
      "remediation": {
        "runbookUrl": "https://docs.stella-ops.org/runbooks/database-pending-migrations",
        "steps": [
          {
            "order": 1,
            "description": "Restart the owning service; it converges its own schema at startup",
            "command": "docker compose up -d --force-recreate authority",
            "commandType": "Shell"
          }
        ]
      },
      "duration": "PT0.234S"
    }
  ]
}

Markdown Format

Formatted for documentation and reports:

# Stella Ops Doctor Report

**Generated:** 2026-01-12T14:30:00Z
**Duration:** 8.3s

## Summary

| Status | Count |
|--------|-------|
| Passed | 46 |
| Warnings | 0 |
| Failures | 1 |
| Skipped | 0 |
| **Total** | **47** |

## Failed Checks

### check.database.migrations.pending

**Status:** FAIL
**Plugin:** stellaops.doctor.database
**Category:** Database

**Diagnosis:** 3 pending migrations in schema 'auth'

**Evidence:**
- Schema: auth
- Pending count: 3

**Fix Steps:**
1. Restart the owning service; it converges its own schema at startup
   ```bash
   docker compose up -d --force-recreate authority

Passed Checks


## Environment Variables

| Variable | Description |
|----------|-------------|
| `STELLAOPS_DOCTOR_TIMEOUT` | Default per-check timeout |
| `STELLAOPS_DOCTOR_PARALLEL` | Default parallelism |
| `STELLAOPS_DOCTOR_OFFLINE_PROFILE` | Force Doctor to behave as sealed/offline even before AirGap policy reports sealed. External probe checks skip or use local/offline-kit data and include `airGapSealed=true` evidence. |
| `STELLAOPS_CONFIG_PATH` | Configuration file path |

When `STELLAOPS_DOCTOR_OFFLINE_PROFILE=true`, Doctor reads the value once at startup and reports the effective offline source in the startup log. Use it during disconnected commissioning to prevent external Rekor, OIDC, debuginfod, notification, observability, TSA, EU Trust List, CRL, OCSP, and NTP probes from failing only because egress is intentionally disabled.

## See Also

- [Doctor Overview](./README.md) - what Doctor is, quick start, and exit codes
- [Doctor Capabilities Specification](./doctor-capabilities.md) - full technical design and check catalog
- [Plugins Reference](./plugins.md) - built-in plugins, their checks, and configuration
- [Evidence Schemas](./evidence-schemas.md) - standardized evidence fields per check