@youwangd/sage
v1.1.0
Published
⚡ Simple Agent Engine — Orchestrate AI coding agents from your terminal. No frameworks, just bash, jq, and tmux.
Downloads
180
Maintainers
Readme
Why sage?
Every AI coding agent framework wants you to learn a new language, install a runtime, and buy into an ecosystem. sage takes a different approach:
Agents are processes. Messages are files. The terminal is your IDE.
sage create worker --runtime claude-code
sage send worker "Build a REST API with auth, tests, and docs"
sage peek worker # watch it work in real-timeThat's it. Three commands. Your agent is running in a tmux pane, writing files, calling tools, and you can watch every step.
Design Principles
- Unix-native — Agents are tmux windows. Messages are JSON files in directories. No daemons, no databases, no Docker.
- Runtime-agnostic — Plug in Claude Code, Cline, or any ACP agent. Adding a new runtime is one file with two functions.
- Mechanical, not behavioral — Task tracking, parent-child relationships, and tracing are handled by the engine, not by asking LLMs to remember protocols.
- Observable — Real-time streaming,
peekinto any agent,tracethe full call tree. You always know what's happening. - Zero lock-in — It's a single bash script. Read it, fork it, modify it. Your agents' state is plain files on disk.
Install
Homebrew (macOS & Linux):
brew tap youwangd/sage
brew install sagenpm (cross-platform):
npm install -g @youwangd/sagecurl (one-liner):
curl -fsSL https://raw.githubusercontent.com/youwangd/SageCLI/main/install.sh | bashManual:
git clone https://github.com/youwangd/SageCLI.git
cd SageCLI
ln -s $(pwd)/sage ~/bin/sage # or /usr/local/bin/sage
sage initRequirements: bash 4.0+, jq 1.6+, tmux 3.0+
Optional runtimes: Claude Code CLI, Cline CLI, or any ACP-compatible agent
Quick Start
# Create an agent and give it work
sage create worker --runtime claude-code
sage send worker "Build a Python CLI that converts CSV to JSON"
# Watch it work
sage peek worker # live tool calls + output
sage attach worker # full tmux terminal access
# Get the result
sage tasks worker # task status + elapsed time
sage result <task-id> # structured outputsage start is optional — send and call auto-start agents that aren't running.
Messages can be inline text or loaded from files:
sage send worker "Quick task" # inline
sage send worker @prompt.md # from file
sage send worker @~/tasks/big-project.md # ~ expansion supportedUse Cases
🔨 Single Agent — Code Generation
Point an agent at a task and let it build:
sage create dev --runtime claude-code
sage send dev "Create a Node.js Express API with JWT auth, rate limiting, and Swagger docs"
sage peek dev # watch files appear in real-time🏗️ Multi-Agent Orchestration
One agent delegates to specialists:
sage create orch --runtime claude-code
sage send orch "Build a full-stack todo app. Create sub-agents for frontend and backend."
sage status
# orch claude-code running 45s
# └─ frontend claude-code running 30s
# └─ backend claude-code running 28s
sage trace --tree
# t-001 cli → orch "Build a full-stack todo app" (120s) ✓
# ├─ t-002 orch → frontend "Build React UI with..." (45s) ✓
# └─ t-003 orch → backend "Build Express API with..." (52s) ✓⚡ Parallel Workstreams
Run independent orchestrators simultaneously:
sage create orch-api --runtime claude-code
sage create orch-ui --runtime claude-code
sage create orch-infra --runtime claude-code
sage send orch-api "Build REST API with FastAPI"
sage send orch-ui "Build React dashboard"
sage send orch-infra "Write Terraform for AWS ECS"
sage tasks # track everything
sage status # full tree view🎯 Course Correction
Steer agents without losing progress:
# Soft steer — guidance for the next task
sage steer orch "Use PostgreSQL instead of SQLite"
# Hard steer — stop everything, restart with new direction
sage steer orch "Switch to Go instead of Python" --restart
# Cascades: stops all children → restarts orch with context🔄 Mixed Runtimes
Use the right tool for each job:
sage create planner --runtime claude-code # strong reasoning
sage create coder --runtime cline # fast execution
sage create scripts --runtime bash # custom handlers📋 Sync Calls
When you need the answer right now:
# Blocks until done (60s default timeout)
sage call worker "What's the time complexity of merge sort?" 30
# Perfect for scripting
RESULT=$(sage call analyzer "Review this PR" 120)
echo "$RESULT"Live Monitoring
Both CLI runtimes stream events in real-time. Tool calls, text responses, and progress appear as they happen:
sage peek master --lines 20 ⚡ peek: master
Live output:
I'll create a professional restaurant template with modern design...
Runner log:
[22:15:28] master: invoking claude-code...
I'll create a professional restaurant template...
→ ToolSearch
→ TodoWrite
→ Write
→ TodoWrite
→ Write
Workspace: 4 file(s)
22:17 19889 styles.css
22:16 23212 index.htmlsage attach drops you into the tmux session for full terminal access.
Task Tracking
Every task gets a trackable ID. Status transitions are mechanical — no LLM behavior dependency.
queued → running → donesage send worker "Build the entire app"
# ✓ task t-1710347041 → worker
sage tasks worker
# TASK AGENT STATUS ELAPSED FROM
# t-1710347041 worker running 45s cli
sage result t-1710347041 # structured output when done
sage wait worker # block until agent finishesTracing
Full observability into how agents collaborate:
# Timeline
sage trace
# 17:00:40 send cli → orch "Build the app..."
# 17:01:02 send orch → sub1 "Write fibonacci..."
# 17:01:20 done sub1 ✓ 18s
# 17:02:08 done orch ✓ 88s
# Call hierarchy
sage trace --tree
# t-123 cli → orch "Build the app" (88s) ✓
# ├─ t-456 orch → sub1 "Write fibonacci..." (18s) ✓
# └─ t-789 orch → sub2 "Write factorial..." (16s) ✓
# Filter
sage trace orch # events for one agent
sage trace --tree -n 50 # last 50 events as treeRuntimes
| Runtime | Backend | Streaming | How it works |
|---|---|---|---|
| claude-code | Claude Code CLI | ✅ stream-json | Real-time tool calls + text via --output-format stream-json |
| cline | Cline CLI | ✅ json | Real-time events via --json |
| acp | Agent Client Protocol | ✅ JSON-RPC | Universal bridge — any ACP agent via stdio. Persistent sessions with live steering. |
| bash | Shell script | — | Custom handler.sh processes messages |
The acp runtime speaks JSON-RPC 2.0 over stdio and works with any ACP-compatible agent:
sage create worker --agent cline # Cline via ACP
sage create worker --agent claude-code # Claude Code via ACP (needs claude-agent-acp adapter)
sage create worker --agent goose # Goose via ACP
sage create worker --agent kiro # Kiro via ACP
sage create worker --agent gemini # Gemini CLI via ACPUnlike the dedicated cline/claude-code runtimes (one-shot per task), ACP maintains a persistent session — follow-up messages go into the same conversation, enabling true live steering.
Adding a runtime is one file with two functions (runtime_start + runtime_inject). See DEVELOPMENT.md.
Architecture
sage CLI
│
├─ sage create <name> → ~/.sage/agents/<name>/{inbox,workspace,results}
├─ sage send <name> msg → writes JSON to inbox/, auto-starts if needed
│
└─ runner.sh (per agent, in tmux window)
├─ polls inbox/ every 300ms
├─ sources runtimes/<runtime>.sh
├─ calls runtime_inject() per message
├─ streams events to tmux pane (live monitoring)
└─ writes task status + results mechanicallyEverything is a file:
~/.sage/
├── agents/<name>/
│ ├── inbox/ # incoming messages
│ ├── workspace/ # agent's working directory
│ ├── results/ # task status + output
│ ├── steer.md # steering context
│ └── .live_output # current task's live output
├── runtimes/ # bash, cline, claude-code
├── tools/ # shared utilities
├── trace.jsonl # append-only event log
└── runner.sh # agent process loopCommands
AGENTS
init [--force] Initialize ~/.sage/
create <name> [--runtime R] Create agent (bash|cline|claude-code)
start [name|--all] Start in tmux
stop [name|--all] Stop (kills process group)
restart [name|--all] Restart
status Tree view of all agents
ls List agent names
rm <name> Remove agent
clean Clean stale files
MESSAGING & TASKS
send <to> <message|@file> Fire-and-forget (returns task ID)
call <to> <message|@file> [t] Sync request/response (default 60s)
tasks [name] List tasks with status
result <task-id> Get task result
wait <name> [--timeout N] Wait for agent to finish
peek <name> [--lines N] Live output + workspace
steer <name> <msg> [--restart] Course-correct agent
inbox [--json] [--clear] View/clear CLI messages
DEBUG & OBSERVABILITY
logs <name> [-f|--clear] View/tail/clear logs
trace [name] [--tree] [-n N] Agent interaction trace
attach [name] Attach to tmux session
TOOLS
tool add <name> <path> Register a tool
tool ls List toolsConfiguration
Agents are configured via runtime.json:
{
"runtime": "claude-code",
"model": "claude-sonnet-4-6",
"parent": "orch",
"workdir": "/path/to/project",
"created": "2026-03-13T22:00:00Z"
}Customize agent behavior by editing instructions.md in the agent directory.
Contributing
sage is a single bash script. Read it, understand it, improve it.
# The entire engine
wc -l sage # ~1500 lines
# Run from source
./sage init --force
./sage create test --runtime bashSee DEVELOPMENT.md for architecture details, runtime interface, and how to add new runtimes.
License
MIT — see LICENSE.
