# 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 ```fleet-synopsis mosaic fleet get mosaic fleet plan create --expected-generation --agent '' mosaic fleet plan update --expected-generation --agent '' mosaic fleet plan delete --expected-generation ``` 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 ```fleet-command 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 ```fleet-synopsis mosaic fleet update --expected-generation --agent '' mosaic fleet delete --expected-generation ``` 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 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: ```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 /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.