init
First-run wizard — preflight this host, detect the OpenClaw instances on it, write the operator-owned fleet config Arguments: [--detect-only] [--force].
SKILL.mdopenclaw-ops/skills/init/SKILL.md
GitHubFleet 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.