How the AxiOwl CLI Works With Flags

AxiOwl's command line interface is intentionally plain. It does not hide its work behind a shell wrapper or a large option framework. The executable receives command-line tokens, dispatches on the first token after axiowl, and then each command handler reads the flags it understands. That simple design matters because AxiOwl is often moving messages between provider sessions where target identity, sender identity, and delivery proof need to be explicit.

Sources read

The CLI starts as an argv dispatcher

The AxiOwl executable entry point in main.cpp does one small job: it copies every argument after the executable name into a std::vector<std::string> and passes that vector to axiowl::run_cli.

From there, run_cli dispatches by args[0]. If the first token is send, AxiOwl runs the send handler. If it is create, it runs the create handler. The same pattern covers rename, discover, list, doctor, provider, registry, node, relay-session, mcp-server, mcp-self-test, delivery-worker, license, and status.

Two top-level shortcuts are handled before subcommands:

axiowl --help
axiowl -h
axiowl --version
axiowl version

The version string in the current source is axiowl 0.1.0.

Flags are exact tokens

The main CLI parser in cli.cpp has two helper functions. One helper looks for an exact flag token and returns the next token as its value. The other checks whether an exact flag token appears anywhere in the argument vector.

That gives AxiOwl a predictable rule:

The handlers decide which flags are required. Missing values are not silently replaced with hardcoded behavior. For example, create fails loudly when --provider or --name is missing, and registry add-agent fails when --name, --provider, or --session is missing.

Send flags define the message boundary

The common user-facing command is:

axiowl send --to "Target chat name" --body "Message text"

The send handler reads these fields:

Flag What the current code does
--to <agent> Primary target name lookup.
--target <agent> Fallback target flag if --to was not provided.
--body <message> Inline message body.
--stdin Reads the full message body from standard input and overrides the earlier --body value.
--from <agent> Explicit sender agent identity for CLI-originated sends.
--from-node <node> Explicit sender node; defaults are resolved downstream if possible.
--strict Sets the request's strict flag.
--run-id <uuid> Supplies a correlation id; otherwise the pipeline generates one.
`–delivery-method <cursor-method A
--source-context <value> Parsed into the message request source context field.

The important detail is what a successful send receipt means. The architecture docs and message_pipeline.cpp separate AxiOwl acceptance from provider delivery proof. A normal send can return accepted_by_axiowl after AxiOwl validates the request and starts delivery handoff. That receipt does not by itself prove the provider displayed the message or replied. The stronger proof is a provider reply through AxiOwl MCP with provider-owned sender identity.

That is why --from and --from-node are not cosmetic. They are part of the identity path for CLI-originated messages. The source tests also assert that final visible reply bodies should not fall back to old shell-command return recipes using axiowl send --from; current reply guidance is centered on the MCP tool path.

For multiline bodies, --stdin is the safer shape:

@'
Line one
Line two
'@ | axiowl send --to "Target chat name" --stdin

Because the handler reads all of standard input when --stdin is present, this avoids quoting problems and keeps the body intact.

Create flags start a provider session

The current create usage is:

axiowl create --provider <provider> --name <agent> [--body <message> | --stdin] [--from <agent>] [--from-node <node>] [--model <model>] [--cwd <cwd>]

The handler requires --provider and --name. It accepts an inline initial message with --body or reads that initial message from standard input with --stdin. It also accepts --model and --cwd, which are passed into the provider create request for providers that can use them.

When a create command includes an initial message, AxiOwl usually needs sender identity before it can build the final visible body. The code resolves that identity from the registry or from explicit --from and --from-node flags. If it cannot resolve the sender, the raw CLI create fails with a message telling the operator to use the MCP create tool from the provider host or pass --from for a CLI-only test.

There is one provider-specific exception in the current handler: antigravity_cli create with an initial body logs a raw provider create prompt policy instead of wrapping the body through the same final visible body builder path.

The parser canonicalizes provider spellings. For example, codex-cli becomes codex_cli, vscode-native becomes vscode_native, vscode-copilot becomes vscode_copilot_backed, copilot-cli becomes copilot_cli, claude-code-cli becomes claude_code_cli, opencode-cli becomes opencode_cli, antigravity-cli and agy become antigravity_cli, and cursor-cli becomes cursor_cli.

Discover flags repair the registry

Discovery is shaped as:

axiowl discover <provider-scope> [--target <agent>] [--json]

The provider scope is the second token. Current scopes handled by the code include:

codex
codex-cli
codex_cli
vscode-native
vscode-copilot
copilot-cli
copilot_cli
antigravity
antigravity-cli
antigravity_cli
agy
cursor
cursor-cli
cursor_cli
claude-code-cli
claude_code_cli
opencode-cli
opencode_cli
opencode
remote
all

--target narrows discovery toward a specific agent name. If --target is absent, the handler also accepts --name as a fallback. --json switches discovery output to JSON-lines formatting through the discovery report formatter.

Discovery also merges discovered rows into the local registry. The current docs describe that as a repair mechanism, not as proof of provider delivery. The provider support matrix sets the higher bar: discovery, install/config, send, receive, MCP reply, and correct provider-owned sender identity.

That distinction matters for flags. A provider name can appear in a command parser before that provider is fully supported. The support matrix is the current status source, not the mere presence of a flag.

Registry and node flags are explicit on purpose

Manual registry operations use value flags because the registry needs stable identity fields:

axiowl registry add-agent --name "Agent" --provider codex --session "<provider-session-id>"

registry add-agent reads --name, --provider, --session, optional --node, optional --source, optional --alias, optional --sender-address, and optional --raw-meta. It defaults the node to local and the source to manual when those values are not provided. It refuses to add a row without name, provider, and session.

registry remove-agent reads --name, optional --provider, optional --session, and optional --node. It requires the name plus either provider or session so removal is not too broad.

Node commands use a separate node registry:

axiowl node add --id "front" --host "example.invalid" --ssh-user "ubuntu" --key "C:\path\key.pem"
axiowl node verify --id "front"
axiowl node list

node add reads --id, --host, --ssh-user, optional --user as a fallback for SSH user, optional --key, optional --name, and optional --alias. node verify requires --id and runs an SSH identity check for the saved node.

Current source still contains node and remote-related command surfaces, but the provider support matrix marks remote unsupported and explicitly out of scope for local-provider remediation builds. In other words, the flag surface can preserve operational machinery without making remote delivery a supported fallback.

MCP and delivery-worker flags are helper surfaces

The MCP server command is an internal integration surface used by providers and by tests:

axiowl mcp-server --host codex --provider codex

mcp_server.cpp reads --host, --provider, --provider-session-id, and --sender-name. It also reads environment values such as AXIOWL_MCP_HOST, AXIOWL_MCP_PROVIDER, AXIOWL_PROVIDER_SESSION_ID, and AXIOWL_SENDER_NAME. The MCP conformance test starts the process with mcp-server --host codex --provider codex and checks both line-delimited and Content-Length framed MCP messages.

The delivery worker is another helper surface:

axiowl delivery-worker --request <request-json-file> [--validate-only]

--request is required. --validate-only switches the worker mode to validation. The normal send path can start the delivery worker in the background after AxiOwl has already accepted the request boundary.

License and smoke-test flags

Activation commands have their own small flag set:

axiowl license status
axiowl license activate --key <license-key> [--endpoint <url>]
axiowl license refresh [--endpoint <url>]
axiowl license deactivate [--endpoint <url>]

--endpoint overrides the configured activation endpoint for status, activate, refresh, and deactivate. activate also reads --key.

Provider smoke testing is shaped as:

axiowl provider smoke-test --all-local [--run-id <uuid>] [--wait-seconds <n>]

The handler requires --all-local, uses --run-id if provided, and bounds --wait-seconds between 0 and 600 seconds with a 120-second default. It writes Markdown and JSONL report files under the AxiOwl state log directory. The usage banner currently mentions --report, but the handler does not branch on that token; report files are written regardless.

Why this flag design is useful

AxiOwl's flags make the boundary between operator intent and provider state visible. --to chooses the target. --from and --from-node make a CLI sender explicit when MCP metadata is not present. --stdin protects multiline message bodies from shell quoting. --json makes discovery output machine-readable. --run-id ties smoke tests and delivery logs together. Registry and node flags force the operator to name identity fields instead of relying on positional guesses.

The tradeoff is that the CLI is literal. It does not interpret --flag=value, infer missing required values, or turn a listed provider name into a support guarantee. That is a good fit for AxiOwl's current architecture. The product is coordinating provider sessions, registry rows, delivery workers, and MCP identity. In that environment, explicit flags are not just command-line decoration. They are part of how AxiOwl keeps routing decisions inspectable.

Practical closing

When using the current AxiOwl CLI, start with the shape of the operation:

Then pass flags as separate tokens, keep values explicit, and use --stdin for anything larger than a short one-line message. That is the CLI's contract in the current C++ implementation.

Image prompt:

Create a polished graphic image related to: how the AxiOwl CLI works with flags.

Subject: a clean command-line terminal panel connected to separate floating flag-shaped option chips and structured routing blocks, with no readable text on any surface.
Style: halfway between a clean symbolic icon and a realistic product/technical illustration; professional SaaS/technical marketing style; crisp edges; high detail; no text; no logos.
Background: solid #00ff00 chroma key green screen background covering the full canvas edge to edge.
Restrictions: no owl, no axolotl, no birds, no animals, no mascot, no text, no watermark.