> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ziro-agent.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Command line reference

> Every flag on the ziro entry point, the front-end dispatch rule, and the other module entry points.

Ziro installs a single console script, `ziro`, which is the same entry point as
`python -m app.main`. Everything else is a module you run with `python -m`.

## The main entry point

<CodeGroup>
  ```bash Installed theme={"theme":{"light":"github-light","dark":"github-dark"}}
  ziro
  ```

  ```bash From a checkout theme={"theme":{"light":"github-light","dark":"github-dark"}}
  python -m app.main
  ```
</CodeGroup>

### Subcommands

| Command         | What it does                                                                                                                    |
| --------------- | ------------------------------------------------------------------------------------------------------------------------------- |
| `ziro`          | Start a chat session. First run walks the setup wizard, then the user, flavour, thread, and agent pickers.                      |
| `ziro setup`    | Re-open the setup wizard even when a key is already configured, to re-key, switch model, or switch theme. Fields are prefilled. |
| `ziro upgrade`  | Pip-upgrade the installed `ziro` distribution from its release index (`ZIRO_PYPI_HOST`, default `test.pypi.org`).               |
| `ziro plugin …` | Install and manage plugins and marketplaces. See [plugin CLI](/reference/plugin-cli).                                           |
| `ziro agents …` | Alias for `python -m app.cli.manage_agents`. See [manage agents](/reference/manage-agents).                                     |
| `ziro init`     | Scaffold a project, optionally seeded from a flavour with `--flavour`.                                                          |

<Note>
  `ziro setup` and `ziro flavour` strip their subcommand and keep parsing the normal
  flags, so `ziro setup --theme nord` works.
</Note>

## Flags

All of these apply to `ziro` and `python -m app.main` equally.

<ParamField path="--user" type="string">
  User ID. Scopes long-term memory. Omit it to reuse the last-used user, or to get
  the first-run picker.
</ParamField>

<ParamField path="--agent" type="string">
  Agent ID to run. Omit it to pick interactively. An agent that is disabled, or that
  falls outside the active flavour, is rejected or corrected to the flavour's
  default agent.
</ParamField>

<ParamField path="--flavour" type="string">
  Flavour to launch. Scopes which agents are visible, which threads exist, and which
  shared memory is used. Omit it to pick interactively when several are configured,
  or to resume the last one. Bundled flavours are `chat`, `engineering`, `research`,
  and `safe`.
</ParamField>

<ParamField path="--thread" type="string">
  Thread ID to resume a previous session. Alias: `--resume`.
</ParamField>

<ParamField path="--no-tui" type="boolean" default="false">
  Force the plain rich REPL instead of the Textual TUI.
</ParamField>

<ParamField path="--voice" type="boolean" default="false">
  Enable push-to-talk voice I/O. Requires the agent's `voice_policy.yaml` to have
  `enabled: true`. Implies the rich REPL.
</ParamField>

<ParamField path="-p, --print" type="string">
  Headless: run one turn and print the reply, then exit. `-p "message"` sends that
  message; a bare `-p` reads the message from stdin.
</ParamField>

<ParamField path="--json" type="boolean" default="false">
  With `-p`, emit the `chat_once` JSON line instead of plain text.
</ParamField>

<ParamField path="--attach" type="path">
  Path to an image to attach to the **first** message. Repeatable. A text-only model
  receives a graceful notice instead of the image.
</ParamField>

<ParamField path="--theme" type="string">
  UI theme name for this launch, overriding the saved preference. Bundled themes are
  `ziro` (the default), `carbon`, `nord`, and `gruvbox`.
</ParamField>

<ParamField path="--think" type="string">
  Seed the reasoning effort for this session: `high`, `medium`, `low`, or `off`.
  Change it live with `/think`.
</ParamField>

## Which front end you get

The entry point picks one of three front ends. The rule is short:

<Steps>
  <Step title="-p is present">
    Run exactly one turn headless, print the reply (or the JSON line with
    `--json`), and exit. Textual is never imported. The wizard and pickers never
    run: the user is resolved from `--user` or the last-used user, and a missing
    user or missing API key fails fast to stderr.
  </Step>

  <Step title="A TTY with Textual available">
    Launch the Textual TUI. The shell paints in roughly 1.6 seconds and is usable
    immediately; anything you type before the engine finishes building is queued
    and runs in order once it is ready.
  </Step>

  <Step title="Anything else">
    Fall back to the rich REPL. This is also what `--no-tui` and `--voice` force,
    and what you get when Textual is not installed or stdout is not a terminal.
  </Step>
</Steps>

<Info>
  The TUI is import-guarded. No Textual, or no TTY, degrades to the REPL rather than
  failing.
</Info>

## Examples

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
# First run: wizard, then pickers, then chat
ziro

# Start a specific agent for a specific user
python -m app.main --user alice --agent researcher

# Scope the session to a flavour
python -m app.main --user alice --flavour engineering

# Resume a thread
python -m app.main --user alice --thread 3f2a91c4

# Force the rich REPL
python -m app.main --user alice --no-tui

# One headless turn, plain text
python -m app.main --user alice -p "summarize today's notes"

# One headless turn, JSON on stdout
python -m app.main --user alice -p "list open todos" --json

# Read the message from stdin
echo "what changed in the last commit?" | python -m app.main --user alice -p

# Attach images to the first message
python -m app.main --user alice --attach diagram.png --attach chart.png
```

## Other entry points

| Entry point                         | What it does                                                                                                                                             |
| ----------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `python -m app.cli.chat_once`       | Single-shot JSON invocation, plus the background job queue via `--submit` and `--status`. See [chat-once](/reference/chat-once).                         |
| `python -m app.cli.manage_agents`   | List, scaffold, remove, enable, disable agents and subagents; set the default agent and per-agent models. See [manage agents](/reference/manage-agents). |
| `python -m app.cli.run_scenarios`   | Replay the scenario files in `tmp/`.                                                                                                                     |
| `python -m app.cli.show_graph`      | Visualize the LangGraph state machine. ASCII by default; `--format mermaid` or `--format png`.                                                           |
| `python -m app.cli.startup`         | Pre-cache the embeddings model, spaCy, and the Llama Guard models so later launches can run Hugging Face offline.                                        |
| `python -m ziro.rag.indexer <path>` | Index documents into the `docs` collection. Accepts a directory, a `.txt`, or a `.pdf`.                                                                  |
| `python -m ziro.tools.indexer`      | Re-index tool descriptions into the `tools` collection.                                                                                                  |
| `python -m skills.loader`           | Index every `SKILL.md` under `skills/` into the `skills` collection.                                                                                     |
| `python -m app.tui.demo`            | Scripted TUI demo on a torch-free fake runner. `textual serve "python -m app.tui.demo"` serves it in a browser.                                          |

<Warning>
  The `app.*` to `ziro.*` module alias does not cover `python -m`, because running a
  module needs the real module path. That is why the indexers are spelled
  `python -m ziro.rag.indexer` and `python -m ziro.tools.indexer`, not `app.rag` /
  `app.tools`.
</Warning>

## Supporting commands

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
uv sync                          # install dependencies
uv sync --group voice-local      # add faster-whisper STT and Piper TTS
mypy .                           # type check
docker compose up -d             # PostgreSQL + pgvector (prod mode)
docker compose up -d searxng     # optional SearXNG backend for web_search
docker compose build pdf-sandbox # build the sandbox image for researcher_docker
```

## Dev and prod modes

The runtime mode is selected by one environment variable, not a flag.

| `DATABASE_URL` | Store                                 | Checkpointer                                  | Vectors  |
| -------------- | ------------------------------------- | --------------------------------------------- | -------- |
| Unset          | `SqliteStore` at `./data/memories.db` | `AsyncSqliteSaver` at `./data/checkpoints.db` | FAISS    |
| Set            | `PostgresStore`                       | `AsyncPostgresSaver`                          | PGVector |

See [environment variables](/reference/environment) for the full list.

## Next steps

<Columns cols={2}>
  <Card title="Slash commands" icon="terminal" href="/interfaces/commands">
    Everything you can do once a session is running.
  </Card>

  <Card title="Headless runs" icon="cpu" href="/interfaces/headless">
    The `-p` and `--json` contracts in detail.
  </Card>

  <Card title="Environment" icon="key" href="/reference/environment">
    Keys, providers, model tiers, and the runtime switches.
  </Card>
</Columns>
