The env for AI coding agents — a tiny shebang dispatcher. Write a
prompt spec once; swap the backend agent with one line.
#!/usr/bin/env airan
---
backend: claude
---
Refactor src/parser into async/await. Don't touch the public API.
chmod +x build.agent
./build.agent # runs the prompt through `claude -p`Change backend: claude to fir or aider, or set
AIRAN_BACKEND=aider, and the same file runs through a different agent —
zero other edits.
airan FILE reads the file, resolves a backend, and execs the
matching agent CLI with the whole file (frontmatter included) as the
prompt. The frontmatter is read for routing but never stripped, so the
agent sees its own constraints.
Backend resolution, in precedence order:
- The frontmatter
backend:key (wins). - The
AIRAN_BACKENDenvironment variable. - The configured default backend (
airan config NAME).
Built-in backends: claude (claude -p), fir (fir -p), aider
(aider --message). You can also define your own — see Custom backends.
airan FILE # dispatch the agent file (the primary use)
airan --prepend TEXT FILE # dispatch, inserting TEXT ahead of the file body
airan backends # list backends + $PATH availability, marking the default
airan backends add NAME CMD… # define / replace a custom backend
airan backends remove NAME # delete a custom backend
airan config # show config path, default + custom backends
airan config NAME # set NAME as the default backend
airan help # full synopsis
airan version # print the airan versionA static agent file often needs a caller-supplied instruction. --prepend
adds one without rewriting the file:
airan --prepend "Apply this to the current host. Report what changed." skill.mdThe text is inserted after the frontmatter block, not before it, so the
composed prompt is still a well-formed frontmatter document — byte 0 remains
the --- fence (or the shebang), and backend resolution is unaffected.
Repeat the flag to add several blocks, in order. Without frontmatter, the
text simply leads.
This is what lets a caller keep the real file path (useful for error messages and logging) instead of materialising a temporary file just to glue an instruction onto the front.
Config lives in one XDG-standard file —
$XDG_CONFIG_HOME/airan/config, else ~/.config/airan/config.
Not limited to the built-ins: declare your own adapter and airan will
route to it. The command line carries a {{prompt}} placeholder that is
replaced with the whole agent file at dispatch time.
airan backends add mycli mycli --message {{prompt}}
airan backends # mycli now shows up, with availabilityThis writes a line to the config file, which you can also edit directly:
# airan config
backend: mycli
backend.mycli: mycli --message {{prompt}}
A custom backend shadows a built-in of the same name, so you can override
how claude/fir/aider are invoked without recompiling. airan backends checks each backend's command against $PATH and reports it as
available or missing.
See docs/DESIGN.md for the full design and rationale.
macOS (Homebrew):
brew install kfet/ai/airanAny Unix (curl — downloads a pre-built binary, no Go needed):
curl -fsSL https://raw.githubusercontent.com/kfet/airan/main/install.sh | shAny Unix (from source — requires Go):
make install # builds and installs (PREFIX overridable)Go:
go install github.com/kfet/airan/cmd/airan@latestmake all # gofmt + vet + staticcheck + race tests + 100% coverage gate + buildMIT — see LICENSE.