DocsScripts
Usage
zirv help (also zirv h, zirv --help, zirv -h) lists every available
script and shortcut, local and global.
Initialize a Project#
Run:
zirv initCreates a .zirv/ directory, its .zirv/commands/ subdirectory (where you
will define your scripts, as of zirv 3.0), and a default .shortcuts.yaml.
The .zirv/ directory is created in the current working directory or in the
HOME directory depending on the commandline interactions.
Creating a New Script#
zirv createInteractively asks for the script name, an optional shortcut key, and whether
to create it locally or in the global ~/.zirv folder, then writes a
template script into .zirv/commands/ (or ~/.zirv/commands/), plus a
shortcut entry in .zirv/.shortcuts.yaml if one was given.
To script the creation (e.g. in CI or setup scripts), pass any of the three answers as flags to skip the corresponding prompt; passing all three skips every prompt:
zirv create --name build --shortcut b --global false--name <name>— the script name (file is written as<name>.yaml).--shortcut <key>— a shortcut key, or an empty string for "no shortcut".--global— create in~/.zirvinstead of the current directory. Bare--globalmeans true; pass--global falseto answer "no" without a prompt.
If the name or shortcut collides with a reserved command name, zirv warns and asks for confirmation before creating an unreachable script; in non-interactive mode (all three flags given) a collision is an error instead, since there is no prompt to fall back on.
Running Scripts#
Place your script files in .zirv/commands/ (e.g., build.yaml):
name: Build
description: Build the application.
commands:
- command: cargo build --release
options:
proceed_on_failure: false
- command: cargo test
options:
proceed_on_failure: falseExecute the script with:
zirv buildIf the name doesn't match any script or shortcut (checked locally in
.zirv/commands/, then globally in ~/.zirv/commands/), zirv suggests up to
3 close matches by edit distance and points you to zirv help. If a script
was left at the .zirv root instead of moved into commands/ (the pre-3.0
layout), the error names it and says where it needs to move — there is no
fallback lookup at the old location:
error: No script or shortcut found for 'buld'. Did you mean: build? Run `zirv help` to see available scripts and shortcuts.Passing Parameters#
If a script declares parameters;
name: Commit Changes
params:
- commit_message
commands:
- command: git add .
- command: git commit -m "${commit_message}"
- command: git push originRun with:
zirv commit "Your commit message here"Optional Parameters#
A parameter name ending in ? is optional and resolves to an empty string
when omitted. Optional parameters must be declared after all required ones:
name: Greet
params:
- name
- greeting?
commands:
- command: echo "${greeting} ${name}"zirv greet Alice # greeting = "" -> prints " Alice"
zirv greet Alice "Welcome" # greeting = "Welcome" -> prints "Welcome Alice"Declaring an optional parameter before a required one, giving fewer
arguments than there are required parameters, giving more than the total
number of declared parameters, or reusing a parameter name (with or without
the trailing ?) are all rejected with an error.
Capture Output#
To capture the output of a command, use the capture option:
name: Capture Test
commands:
- command: "echo hello"
capture: greeting
options:
proceed_on_failure: false
- command: "echo Got: ${greeting}"First step stores hello in the variable ${greeting}, which is then used in the second step to print Got: hello.
Failure Hooks#
Declare a failure hook for a command using fallback:
name: OnFailure Demo
commands:
- command: "sh -c 'exit 1'"
options:
proceed_on_failure: true # don't stop the script once fallback succeeds
fallback:
- command: "echo 'Fallback action'"If the command fails, every fallback command runs, in order, once — the
original command is never retried. If any fallback command itself fails,
the step fails immediately with an error naming both the original and the
failing fallback command. Otherwise, whether the step's own failure stops the
script is controlled separately by proceed_on_failure: true continues to
the next step, false (the default) stops the script with an error, even
though every fallback succeeded.
Dry Run#
Pass --dry-run to preview a script without running anything:
zirv build --dry-runEach step is printed with its ${...} parameters substituted, instead of
being executed, so you can check what a script would do first.
Chaining Scripts#
You can chain scripts by calling one script from another. For example, if you have a script build.yaml and want to call it from deploy.yaml:
name: Deploy
description: Deploy the application.
commands:
- command: zirv test
options:
proceed_on_failure: false
- command: zirv build
options:
proceed_on_failure: falseRun the deploy script with:
zirv deployConcurrent Shells#
You can open multiple terminals at once by nesting lists. For example:
name: Parallel Commands
commands:
- - command: "echo 'Running Task A'"
- command: "echo 'Running Task B'"
- - command: "echo 'Running Task 1'"
- command: "echo 'Running Task 2'"Each nested list spawns its own shell window. Every window executes the commands listed in that group and stays open until they finish.
This needs a desktop/GUI session: macOS uses osascript to drive Terminal,
Windows opens a new cmd window, and Linux tries gnome-terminal, then
x-terminal-emulator, then xterm. Over a headless or SSH-only connection —
or on Linux specifically, whenever neither DISPLAY nor WAYLAND_DISPLAY is
set — zirv returns a clear error naming what it tried, instead of failing
cryptically or hanging.
The built-in cd command updates the working directory for any following
commands in the same window, allowing scripts like:
commands:
- - command: "cd backend"
- command: "cargo run"Agent Steps#
A command step can run a supervised AI-agent task instead of a shell command,
using agent and prompt in place of command:
commands:
- command: cargo test
- agent: claude
prompt: "Fix the failing tests in ${dir}"
# optional:
flags: ["--model", "sonnet"]
- command: cargo testruntime selects which machinery runs the step: harness (the default, and
what every existing script keeps doing) or native — zirv conducts the
conversation itself over a direct provider route, with no coding harness
installed:
commands:
- agent: fast-route # a [route] name, not an adapter name
runtime: native
prompt: "Summarise the failing checks in ${dir}"Under runtime: native the agent value names a provider route from
~/.zirv/native.toml (the reserved value native means "use the [roles]
entry for the worker role"), and flags are refused rather than silently
ignored — they exist to reach a vendor CLI and there is none. An unrecognised
runtime fails at load time, so --dry-run and the real run reject the same
script. Everything else — ${var} substitution, secrets, operating_system,
proceed_on_failure, delay_ms, fallback and the exit-code contract — is
identical on both runtimes.
prompt gets the same ${var} substitution as command, including the
unresolved-placeholder error if a variable is missing. flags are passed
straight through to the agent CLI. operating_system, proceed_on_failure,
delay_ms and fallback work the same as they do for a regular command;
capture and interactive are not supported and fail the step if set.
The step runs in-process through the same supervision zirv ctx exec uses:
pacing against your usage windows, rot detection, and automatic restart with a
distilled handoff if the session rots. A non-zero outcome fails the step like
any other command. Only Claude Code is supported today (see Context
Management below); naming any other agent fails
with that adapter's own error.