Preskoči na vsebino

`colibri doctor` — self-diagnosis & self-upgrade

index

Status: Shipped (v0.12.0+). 10 checks, two auto-fixable targets, client-side colibri upgrade. Cross-platform (Linux + FreeBSD, one #[cfg] for service restart).

status is a passive snapshot (counts). doctor is a battery of active checks — each verifies one thing that has to be true for the control plane to work, and reports PASS/WARN/FAIL. It’s the task-dispatch-flow “why won’t my task run?” checklist, executable. Scope is concrete — check only what we actually have, never claim a check we can’t back with a data source.

struct CheckResult {
check: String, // e.g. "database", "registration_linkage"
status: String, // "pass" | "warn" | "fail"
detail: String, // human-readable one-liner
hint: Option<String>, // optional operator-facing tip (→ displayed)
fixable: bool, // can `colibri doctor --fix` act on it?
}

hint is always displayed as a → tip in table output. fixable is the hinge between diagnosis and action: only fixable: true checks are acted on by --fix. Today two checks are fixable: binary_vs_git_versioncolibri upgrade, registration_linkagecolibri agents prune.

CheckWhat it verifiesfixable
databaseStore opens and queries cleanlyno
providersAt least one cloud provider key setno
agentsAt least one live agent handleno
dispatch_readinessAgents are in RPC mode (can receive tasks)no
registration_linkageStore agents map to live handles (stale if not)yescolibri agents prune
model_selectionPhase 3 model selection enabled/disabledno
local_evalollama available for local-llm evalno
disk_freedf -k on data_dir — <100MiB FAIL, <1GiB WARNno
binary_vs_git_versionBinary version matches git tag at build timeyescolibri upgrade
doas_nopasswd (FreeBSD) / sudo_nopasswd (Linux)Passwordless escalation configured for daemon controlno
git_behindClient-side: commits behind origin/mainno (shown by client, not daemon)

The daemon emits 10 checks. git_behind is client-side only — the client runs git rev-list --count HEAD..origin/main after fetching. The escalation check (doas_nopasswd on FreeBSD, sudo_nopasswd on Linux) was added after real-world testing showed colibri upgrade failing mid-flight when the escalation tool required a password.

  • DNS resolution — daemon has no DNS config; would need a /etc/resolv.conf or host probe.
  • TLS/ACME cert expiry — no cert knowledge in the daemon; an nginx concern.
  • PostgreSQL health — not in the colibri installer scope.
  • Mother reachablessh colibri@mother requires key setup that isn’t guaranteed on every node.

The doctor never prints a check it can’t back. Adding one of these means adding its data source first.

The upgrade flow is entirely client-side. The daemon never touches its own binary.

colibri upgrade --check # just the git-behind count, no build
colibri upgrade --yes # git pull → cargo build --release → stop → install → start
colibri upgrade # interactive (prompts before build)

Platform restart: service colibri_daemon restart (FreeBSD rc.d) vs systemctl restart colibri-daemon (Linux) — one #[cfg] block.

Binary install uses install(1) (not cp) to avoid ETXTBSY (“Text file busy”) when overwriting the running client binary on FreeBSD.

Passwordless escalation requirement (doas on FreeBSD, sudo on Linux)

Razdelek z naslovom „Passwordless escalation requirement (doas on FreeBSD, sudo on Linux)”

colibri upgrade needs passwordless escalation for the daemon stop/install/start cycle. The doas_nopasswd (FreeBSD) / sudo_nopasswd (Linux) check detects this.

The check (and the upgrade pre-flight) probe the scoped service-status commanddoas -n service colibri_daemon status (FreeBSD) / sudo -n systemctl status colibri-daemon (Linux) — not esc -n true. The installer writes command-limited rules, so a blanket true probe would fail even on a correctly-configured host.

Preferred provisioning — the clawdie installer writes the scoped rules for you. Run it with the operator account that should control upgrades:

Terminal window
clawdie apply --operator-user YOUR_ACCOUNT --yes

FreeBSD (rc.d + doas) — the installer appends permit nopass rules to /usr/local/etc/doas.conf for the operator account:

/usr/local/etc/doas.conf
permit nopass YOUR_ACCOUNT cmd service
permit nopass YOUR_ACCOUNT cmd install

Linux (systemd + sudo) — the installer writes a NOPASSWD drop-in for the operator account:

/etc/sudoers.d/colibri
YOUR_ACCOUNT ALL=(root) NOPASSWD: /usr/bin/systemctl * colibri-daemon
YOUR_ACCOUNT ALL=(root) NOPASSWD: /usr/bin/install *

The rules are scoped by command, not blanket — doas matches by command name (service covers any service invocation), while sudoers uses arg wildcards.

colibri doctor --fix

Runs all checks, then acts on fixable: true ones:

  1. binary_vs_git_versioncolibri upgrade (pull + build + restart). Forces rebuild even when git is at origin/main — the binary can be stale from a pre-tag build.
  2. registration_linkagecolibri agents prune — removes store agents that have no live daemon handle. Stale agents accumulate on every daemon restart because agent IDs are ephemeral.

After fixes, re-runs doctor to show the new state.

colibri doctor # run all checks, print table with → hints
colibri doctor --json # machine-readable (MCP / dashboard)
colibri doctor --fix # run checks + act on fixable ones
colibri upgrade # interactive self-rebuild
colibri upgrade --check # git-behind count only
colibri upgrade --yes # non-interactive self-rebuild
PieceWherePlatform
Checks enginecrates/colibri-daemon/src/doctor.rscross-platform
Client displaycolibri-client (colibri doctor)cross-platform
Self-upgradecolibri-client (colibri upgrade)one #[cfg] block
Stale-agent prunecrates/colibri-daemon/src/daemon.rscross-platform

The daemon gets exactly one command: DoctorVec<CheckResult>. The client formats it and runs fixes. Upgrade and prune are separate — they compose through --fix, not through a shared daemon API.

Each node runs colibri doctor locally. Mother queries all nodes with ssh <node> colibri doctor --json — the SSH keychain + MCP-over-SSH already carry arbitrary socket commands.