Routines
Routines are named workflows that run multiple cli4ai commands (and optionally other executables) in sequence.
Use them to make “run these 4 commands” repeatable, parameterized, and easy for agents to execute.
Quick Start
# Run a routine (local-first)
cli4ai routines run daily-report --var lang=rust
# Use global routines only
cli4ai routines run daily-report --global
# Debug without running
cli4ai routines run daily-report --dry-run --var lang=rust Where routines live
Routines are stored as files, either local to a project or globally in your home directory:
# Local (project-specific)
./.cli4ai/routines/
daily-report.routine.json
daily-report.routine.sh
# Global (personal)
~/.cli4ai/routines/
daily-report.routine.json
daily-report.routine.sh Resolution is local-first by default:
# Resolution order (default)
1) ./.cli4ai/routines/.routine.json
2) ./.cli4ai/routines/.routine.sh
3) ~/.cli4ai/routines/.routine.json
4) ~/.cli4ai/routines/.routine.sh
# With --global
1) ~/.cli4ai/routines/.routine.json
2) ~/.cli4ai/routines/.routine.sh Managing routines
# List routines (local + global)
cli4ai routines list
# Create routines
cli4ai routines create daily-report --type json
cli4ai routines create scratchpad --type bash --global
# Edit/view/remove
cli4ai routines edit daily-report
cli4ai routines show daily-report
cli4ai routines remove daily-report
# Run
cli4ai routines run daily-report --var lang=rust Two routine types
1) Script routines (.routine.sh)
Script routines are the fastest way to get started. They run via bash. Any --var KEY=value flags are
exposed as environment variables like CLI4AI_VAR_KEY.
- Args: any extra arguments after the routine name are passed through to the script.
- Output: in a TTY, stdio is inherited; in non‑TTY, stdout/stderr are captured and returned as one JSON summary.
#!/usr/bin/env bash
set -euo pipefail
# Vars passed via --var KEY=value are available as env vars:
# CLI4AI_VAR_LANG=rust
# Routine metadata is also exposed:
# CLI4AI_ROUTINE_NAME=daily-report
# CLI4AI_ROUTINE_PATH=/absolute/path/to/daily-report.routine.sh
lang="${CLI4AI_VAR_LANG:-rust}"
# Chain cli4ai commands
cli4ai run github trending "$lang"
# Example of using other tools
git status --porcelain 1>&2 2) Structured routines (.routine.json)
Structured routines are designed for orchestration: each step can capture stdout, parse JSON, and pass data to later steps via templates.
Note: extra positional args after the routine name are currently only passed to script routines; structured routines use --var.
{
"version": 1,
"name": "daily-report",
"description": "Example: chain cli4ai + exec steps",
"vars": {
"lang": { "default": "rust" },
"channel": { "default": "claude" }
},
"steps": [
{
"id": "trending",
"type": "cli4ai",
"package": "github",
"command": "trending",
"args": ["{{vars.lang}}"],
"capture": "json"
},
{
"id": "pickRepo",
"type": "set",
"vars": {
"repo": "{{steps.trending.json.0.fullName}}"
}
},
{
"id": "issues",
"type": "cli4ai",
"package": "github",
"command": "issues",
"args": ["{{vars.repo}}"],
"capture": "json"
},
{
"id": "post",
"type": "cli4ai",
"package": "slack",
"command": "post",
"args": [
"{{vars.channel}}",
"Top repo: {{vars.repo}}"
],
"capture": "json"
}
],
"result": {
"repo": "{{vars.repo}}",
"issues": "{{steps.issues.json}}",
"slack": "{{steps.post.json}}"
}
} Execution model (structured routines)
┌────────────────────────────────────────────────────────────┐
│ cli4ai routines run daily-report --var lang=rust │
└────────────────────────────────────────────────────────────┘
1) Resolve file (.cli4ai/routines → ~/.cli4ai/routines)
2) Parse + validate JSON schema (version 1, unique step ids)
3) Init context
- vars = defaults + --var overrides
- steps = {}
4) Execute steps in order
a) Render templates against { vars, steps }
b) Run step
- type: cli4ai → runs a cli4ai tool (same resolver + secrets injection as cli4ai run)
- type: exec → spawn(cmd, args, shell:false) (captures stdout/stderr)
- type: set → assigns vars from rendered templates
c) Save result to steps. for later templates
d) Stop on non-zero exit unless continueOnError=true
5) Emit final output
- stdout: single JSON summary
- stderr: streamed progress/stderr from steps Templating
Templates reference vars and prior steps. Missing paths are hard errors during an actual run.
--dry-run is lenient and leaves unresolved {{...}} placeholders intact.
# Vars
{{vars.lang}}
# Step stdout/stderr
{{steps.trending.stdout}}
{{steps.trending.stderr}}
# Step JSON (capture: "json")
{{steps.trending.json}}
{{steps.trending.json.0.fullName}} Output
Structured routine runs emit a single JSON summary on stdout. Step stderr is streamed to stderr so agents can ignore it.
{
"kind": "json",
"scope": "local",
"path": "/path/to/.cli4ai/routines/daily-report.routine.json",
"routine": "daily-report",
"version": 1,
"status": "success",
"exitCode": 0,
"durationMs": 1234,
"vars": { "lang": "rust", "repo": "owner/name" },
"steps": [
{ "id": "trending", "type": "cli4ai", "status": "success", "exitCode": 0, "json": [/* ... */] }
],
"result": { "repo": "owner/name" }
} Examples
Ready-to-use routines you can copy and customize. See the Examples section for complete walkthroughs.
Notes
- Local by default: routines are usually project-specific; use
--globalfor personal utilities. - No composition (v1): if you want nesting, use a bash routine that calls
cli4ai routines run. - Exec safety:
execsteps spawn withshell: false; usebash -lcif you need shell features. - AI integration: pipe data to
claude --print,llm, or any CLI tool for AI-powered processing.