Manual

Running

What run passes to ansible-playbook, where it builds, how a run is recorded and shown again, and the output other programs read.

ansible-playbook arguments#

run [PLAYBOOK] builds the tree into a temporary directory and runs ansible-playbook (default: site.yml). It takes the common arguments directly, and anything after -- is passed through verbatim:

$ python site.py run -C -D -l web -t nginx -e env=prod -vv
$ python site.py run --install --keep
$ python site.py run -- --vault-id dev@prompt

-C/--check, -D/--diff, -l/--limit, -t/--tags, --skip-tags, -b/--become, -u/--user, -c/--connection, -e/--extra-vars (repeatable), -i/--inventory, --start-at-task, --step, --list-tasks, --list-hosts, --syntax-check, --vault-password-file, -v (repeat for -vvv).

run builds into a temporary directory that is removed afterwards; --keep keeps it, --dir DIR builds somewhere durable. The exit code is ansible’s.

Before it starts anything, run says where ansible comes from (and so do install, lint and test):

instamix: ansible-core 2.21.3 on Python 3.13.13, from the environment ~/.cache/instamix/envs/b3a74bc5109a4ae4
instamix: galaxy and pip through http://127.0.0.1:8470/webserver2
instamix: settings from ~/.config/instamix/config

Recording and replaying runs#

run --record FILE (and container --record FILE) also writes the run’s events to FILE, while ansible’s output stays on the terminal as it is: what ran and when, where ansible came from, each play and task, every host’s result, and the recap. imix replay FILE shows such a file again, flattened for reading:

$ python site.py run --record run.jsonl
$ imix replay run.jsonl            # --failed, --host HOST, --results
site.py run --record run.jsonl  (2026-09-27T17:22:52+00:00)
ansible-core 2.21.4 on Python 3.13.13, from PATH (~/.local/bin/ansible-playbook)

PLAY Try things [localhost]
  TASK Change something  (site.yml:5)
    localhost: changed
  TASK Fail, and carry on  (site.yml:7)
    localhost: failed ignored
      msg: The command exited with a non-zero return code.

RECAP
  localhost: ok=3 changed=2 unreachable=0 failures=0 skipped=0 rescued=0 ignored=1

It reads saved --jsonl output as well (- for stdin). In a container, the events come back through a file mounted into it, so container --jsonl reports results too, once the run is over.

Machine-readable output#

Every command takes --jsonl (before or after the command name), or reads INSTAMIX_JSONL=1. stdout then carries one JSON object per line, each with an event field; stderr keeps its human messages, and the exit code is unchanged. Locally nothing changes unless you ask for it.

$ python site.py run --jsonl -C
{"event":"exec","cmd":["ansible-playbook","-i","inventory","--check","site.yml"],"cwd":"/tmp/instamix-..."}
{"event":"output","stream":"stdout","line":"PLAY [localhost] ****..."}
{"event":"exited","cmd":["ansible-playbook","-i","inventory","--check","site.yml"],"status":0}

Output of the programs instamix starts is wrapped line by line in output events, so it cannot break the stream. generate - is refused under --jsonl, since the events own stdout. lsp speaks its own protocol and has no --jsonl.

Each event and its fields is in the reference: Events.

The contract#

imix spec prints an OpenAPI 3.2 document, checked in as api/openapi.json (download it), describing instamix to other programs:

  • each command is an operation whose request body holds its options, with an x-cli note saying how each becomes argv, and whose response is application/jsonl, one Event per line;
  • each declaration call (file, role, requires_ansible, …) is a Declaration schema, and a Script is a list of them. A program can build a script from data, check it against the schema before anything runs, and write it out as a real instamix script that still runs locally.

The operations are read from the commands themselves; the tests check the events every command emits, and the declarations against their Python signatures, so the document cannot drift. Regenerate it with imix spec -o api/openapi.json.

The source of this page

    Type to search. ↑ ↓ to move, enter to open.