3.9 KiB
Create, Inspect, Update, and Delete a Local Fleet Agent
Use the local roster-v2 control plane only. These commands change desired state and derived environment projections; they never start, stop, reconcile, inspect, or otherwise act on systemd, tmux, sessions, or runtimes.
Read and plan first
mosaic fleet get <name>
mosaic fleet plan create --expected-generation <n> --agent '<json>'
mosaic fleet plan update <name> --expected-generation <n> --agent '<json>'
mosaic fleet plan delete <name> --expected-generation <n>
plan create takes the name from --agent. plan update and plan delete require the target name immediately after the operation. A plan is deterministic and side-effect free: it validates the complete proposed roster and projection targets without changing files. Use --dry-run on create, update, or delete for the same no-write result.
Every successful command prints JSON. get returns { "generation", "agent" }; mutation results contain plan, applied, authoritativeRoster, and projections.
Create safely
mosaic fleet create --expected-generation 7 --agent '{
"name":"coder0",
"alias":"Coder 0",
"className":"code",
"runtime":"pi",
"provider":"openai",
"model":"gpt-5.6-sol",
"reasoning":"high",
"toolPolicy":"code",
"workingDirectory":"/srv/mosaic",
"persistentPersona":false,
"resetBetweenTasks":true,
"launch":{"yolo":true}
}'
Create defaults to enabled: true and desired_state: stopped. It does not start a process. Add --persisted-start only to persist desired_state: running; that still does not start a runtime in this M2 command. The JSON payload is an allowlist of the roster-v2 fields shown above plus launch.yolo; command, channel, secret-reference, and other unknown keys are rejected rather than ignored. The JSON error exposes only a stable code, never the rejected value.
Update and delete safely
mosaic fleet update coder0 --expected-generation 8 --agent '<complete JSON agent payload>'
mosaic fleet delete coder0 --expected-generation 9
Updates require a complete agent JSON payload and preserve the stable name. Delete removes only the exact roster-owned coder0.env.generated projection. It retains coder0.env.local, legacy coder0.env, coder0.env.quarantine, and every unrelated projection. A delete dry-run leaves all of those files byte-identical.
Handle generation conflicts
Every mutation requires the current authoritative --expected-generation. A stale value returns JSON error.code: "stale-generation" with a non-zero exit. Reload with mosaic fleet get <name> or reread the roster, plan again using the returned generation, then retry. A concurrent mutation returns concurrent-mutation; do not force or bypass the lock.
Interpret partial failures
The roster is authoritative and is written before derived projections. A late projection I/O failure returns non-zero with redacted, actionable JSON:
{
"applied": false,
"authoritativeRoster": "committed",
"projections": "incomplete",
"recovery": {
"code": "projection-apply-failed",
"action": "regenerate-projections-from-roster"
}
}
This is not a rollback and not a no-op: reload the roster because its generation and membership were committed, regenerate projections from that roster, then plan a new mutation. Recovery output never contains environment values, credentials, or command text.
Exit and boundary behavior
Handled validation errors and partial projection failures exit non-zero. plan/--dry-run and normal mutation JSON make the state explicit; scripts should use both the exit code and authoritativeRoster/projections, not applied alone.
The commands operate only on <mosaic-home>/fleet/roster.yaml, the local roster desired-state authority. They do not accept arbitrary commands, channels, secrets, remote/connector actions, migration/canary actions, or runtime lifecycle operations.