init

First-run wizard — preflight this host, detect the OpenClaw instances on it, write the operator-owned fleet config Arguments: [--detect-only] [--force].

SKILL.md

GitHub

Fleet init

Turn "there are OpenClaw instances on this box" into a fleet config every other command can trust. Read-only through step 4; step 5 writes exactly one file. Parse [--detect-only] [--force] from "$ARGUMENTS"; load fleet-model first — it owns the config ladder, the fields and the plan rule.

1. Preflight

uname -s -m
docker version --format 'server {{.Server.Version}}' 2>&1 | tail -1
python3 "${CLAUDE_PLUGIN_ROOT}/scripts/fleet.py" config --show 2>&1 | head -3
git rev-parse --is-inside-work-tree 2>/dev/null || echo "not a git work tree"

Four gates, each fatal alone: unsupported OS or architecture, no docker binary, a daemon that does not answer, no permission on the socket. Report the failing one and stop. Never write the config inside a git work tree — that is how instance names, ports and host paths get committed; there --out must be ~/.config/openclaw-ops/fleet.json (per user) or /etc/openclaw-ops/fleet.json (host-wide, root).

2. Detect

python3 "${CLAUDE_PLUGIN_ROOT}/scripts/fleet.py" config --init --detect-only --json
python3 "${CLAUDE_PLUGIN_ROOT}/scripts/fleet.py" discover --table

Add --prefix <p> when the compose projects do not start with openclaw-. Show the table, name what came back alien or legacy, and stop here if --detect-only was passed.

3. Nothing usable found — diagnose, never retry

Answer as what I saw → the hypothesis → exactly one action for the operator, one action per message. The four cases — wrong machine · different prefix · everything alien · a foreign host_fingerprint — and the single next action for each are in fleet-model → references/fleet-config.md.

4. Ask — only what detection cannot answer

One AskUserQuestion, recommended option first: the reference instance, which instances stay unmanaged (alien and legacy default to manage:false), the canary (least critical, never the reference), and policy — update channel, soak days, stale-log hours. Every answer has a flag in step 5.

5. Write — R2, so the plan is short but complete

  • BACKUP — cp -p <existing-config> <existing-config>.pre-init, only when a config already exists.
  • ROLLBACK — mv <existing-config>.pre-init <existing-config>; with no prior file, rm -f <out-path>.
  • APPLY
(umask 077; python3 "${CLAUDE_PLUGIN_ROOT}/scripts/fleet.py" config --init \
   --reference <name> --canary <name> \
   --update-channel <stable|extended-stable|beta|dev> --soak-days <n> --stale-log-hours <h> \
   [--host-label <text>] [--out <path>] [--force])

Mode 0600, names and ids only, never a secret value. Omit a policy flag to keep its default.

6. Verify, then hand over

python3 "${CLAUDE_PLUGIN_ROOT}/scripts/fleet.py" config --validate
python3 "${CLAUDE_PLUGIN_ROOT}/scripts/fleet.py" config --diff

role, criticality, aliases and the secret ids are guesses — say so, then point at /openclaw-ops:status.