A pluggable executor framework for AI coding agents. Dispatch Claude Code tasks or arbitrary shell commands to remote SSH hosts, Docker containers, or local execution — then monitor, fetch logs, and manage them from one CLI.
cargo build --release
# Binary: target/release/openclaw-agent
cp target/release/openclaw-agent ~/.local/bin/Create ~/.config/openclaw/coding-agent.yaml:
executors:
- name: crib
type: ssh
host: 192.168.0.152
port: 22
user: jimmy
claude_path: /home/jimmy/.npm-global/bin/claude
labels:
- rust
- heavy-compute
- name: builder
type: container
image: claude-code:latest
runtime: docker # or podman
volumes:
- /home/jimmy/repos:/work
labels:
- isolated
- reproducible
- name: local
type: local
labels:
- quick-tasks
- lightweight
defaults:
max_turns: 100
claude_path: claude
webhook_url: https://example.com/webhook # optional: POST completion JSON hereOr generate a sample config:
openclaw-agent config --init# Run on SSH host
openclaw-agent start --executor crib --prompt "Fix the Nix build so nix build .#app works" --workspace ~/lez-hello-world
# Run in Docker container
openclaw-agent start --executor builder --prompt "Add error handling to the API" --workspace /work/myproject
# Run locally
openclaw-agent start --executor local --prompt "Write tests for src/lib.rs" --workspace ~/myproject
# With options
openclaw-agent start --executor crib \
--prompt "Refactor the auth module" \
--workspace ~/myapp \
--max-turns 150Run arbitrary shell commands on any executor backend (not just Claude):
# Build and test on remote host
openclaw-agent run --executor crib --cmd "make build && make test" --workspace ~/myproject
# Run a script locally
openclaw-agent run --executor local --cmd "./deploy.sh staging" --workspace ~/myapp
# Run in container
openclaw-agent run --executor builder --cmd "cargo test --release" --workspace /work/myprojectThe list output shows task type icons: 🤖 for Claude Code, ⚙️ for shell commands.
# Check status
openclaw-agent status --task-id <task-id>
# JSON output (for scripting/dashboard)
openclaw-agent status --task-id <task-id> --json# Last 50 lines (default)
openclaw-agent logs --task-id <task-id>
# Last 100 lines
openclaw-agent logs --task-id <task-id> --lines 100
# Follow (poll every 5 seconds)
openclaw-agent logs --task-id <task-id> --follow 5# All tasks
openclaw-agent list
# Filter by status
openclaw-agent list --status running
openclaw-agent list --status completed
# Filter by executor
openclaw-agent list --executor crib
# JSON/JSONL output
openclaw-agent list --json
openclaw-agent list --jsonlopenclaw-agent kill --task-id <task-id>openclaw-agent cleanup --task-id <task-id># Snapshot of all tasks as JSONL
openclaw-agent dashboard --stream
# Watch mode (refresh every 10 seconds)
openclaw-agent dashboard --watch 10openclaw-agent executors
openclaw-agent executors --json┌─────────────────────────────────────────┐
│ OpenClaw Agent (Brain) │
│ - Decides which executor to use │
│ - Monitors task progress │
│ - Fetches logs & activity │
└──────────────┬──────────────────────────┘
│
┌──────────┼──────────┐
▼ ▼ ▼
┌───────┐ ┌─────────┐ ┌────────┐
│ SSH │ │Container│ │ Local │
│Executor│ │Executor │ │Executor│
└───────┘ └─────────┘ └────────┘
│ │ │
▼ ▼ ▼
┌───────┐ ┌─────────┐ ┌────────┐
│ Crib │ │ Docker │ │ Pi5 │
│(remote│ │(isolated│ │(local │
│ host) │ │ builds) │ │ tasks) │
└───────┘ └─────────┘ └────────┘
| Crate | Purpose |
|---|---|
executor-core |
Shared traits, types, config, metadata |
executor-ssh |
SSH executor (ssh2 crate, nohup + PID tracking) |
executor-container |
Docker/Podman executor |
executor-local |
Local process executor |
executor-cli |
Clap-based CLI binary |
Two payload types are supported:
| Type | CLI Command | Icon | Description |
|---|---|---|---|
claude_code |
start |
🤖 | Runs Claude Code with a prompt |
shell_command |
run |
⚙️ | Runs an arbitrary shell command |
Both types work on all executor backends (SSH, container, local).
Each task writes a .meta.json file tracking:
- Task ID (UUID)
- Executor name + type
- Task type (
claude_codeorshell_command) - PID
- Status (pending / running / completed / failed / killed)
- Start/end timestamps
- Workspace path
- Prompt / command
SSH executor stores metadata at /tmp/openclaw-tasks/<task-id>/ on the remote host, and mirrors it locally at ~/.local/share/openclaw/tasks/.
When a task finishes (success, failure, or kill), a completion record is written to:
~/.openclaw-agent/completions/<task-id>.json
Format:
{
"task_id": "...",
"status": "success|failure",
"exit_code": 0,
"completed_at": "2025-01-15T10:30:00Z",
"executor": "crib"
}If webhook_url is set in config defaults, the completion JSON is also POSTed there via curl.
- Connect to remote host via SSH (key or agent auth)
- Create task directory at
/tmp/openclaw-tasks/<task-id>/ - Launch:
nohup claude --dangerously-skip-permissions --max-turns N -p "..." > task.log 2>&1 & - Write PID to
task.pid, metadata to.meta.json - Log fetching reads
~/.claude/projects/JSONL on the remote host
- jimmy-tools — Original shell script pattern this is based on
- logos-lez-multisig-module — Production Nix example
MIT