Coordination layer for OpenClaw agent fleets
Project description
clawctl
Coordination layer for OpenClaw agent fleets. Task board, inter-agent messaging, activity feed, and a live web dashboard — all backed by a single SQLite database.
$ clawctl board
═══ CLAWCTL ═══ agent: chat
── ○ pending (2) ──
#4 Summarize weekly spending from transaction exports
#6 Find showtimes for new releases this weekend [movie]
── ▶ in_progress (2) ──
#1 Research best noise-cancelling headphones under $300 [research]
#5 Write a Python script to rename photos by EXIF date [coding]
── ✗ blocked (1) ──
#3 File notes from the headphone research [notes]
── ✓ done (1) ──
#2 Check portfolio risk exposure for earnings week [trading]
Why this exists
Multiple agents working in parallel need a shared source of truth. Without one, you get duplicate work, missed handoffs, and no audit trail.
clawctl is the answer for OpenClaw fleets:
- Zero infrastructure. Local SQLite in WAL mode. No cloud, no signup, no build step.
- SSH-queryable.
ssh your-vps clawctl boardworks out of the box. - Race-safe. Atomic claims and completions via single-UPDATE patterns with WHERE guards. No read-then-write races.
- Auditable. Every mutation hits an append-only activity log with optional JSON metadata for linking PRs, issues, test results.
- OpenClaw-native. Install as a skill, drop into any agent's workflow.
Install
uv pip install clawctl
# or
pip install clawctl
Or from source:
git clone https://github.com/lludlow/clawctl.git
cd clawctl
uv pip install -e .
Requirements: Python >= 3.9
Quick start
# Initialize
clawctl init
# Register the fleet
clawctl register chat --role "everyday triage & delegation"
clawctl register research --role "deep reasoning & web search"
clawctl register coding --role "sandboxed code execution"
clawctl register notes --role "knowledge graph & note-taking"
clawctl register trading --role "read-only market analysis"
clawctl register family --role "mention-gated secure responder"
clawctl register movie --role "watchlists & recommendations"
# Chat agent delegates work to specialists
CLAW_AGENT=chat clawctl add "Research best noise-cancelling headphones under $300" --for research
CLAW_AGENT=chat clawctl add "Write a Python script to rename photos by EXIF date" --for coding -p 1
CLAW_AGENT=chat clawctl add "File notes from the headphone research" --for notes
# Research agent picks up its task
CLAW_AGENT=research clawctl claim 1
CLAW_AGENT=research clawctl start 1
CLAW_AGENT=research clawctl done 1 -m "Top 3 picks with comparison table" \
--meta '{"note":"~/notes/headphone-research.md"}'
# Research hands off to notes for filing
CLAW_AGENT=research clawctl msg notes "Research complete, ready to file" --task 3
# Monitor
clawctl board
clawctl fleet
clawctl feed --last 10
Agent integration
The typical agent loop:
# On startup — check messages, find work
CLAW_AGENT=coding clawctl checkin
CLAW_AGENT=coding clawctl inbox --unread
CLAW_AGENT=coding clawctl next
# Do the work, then close out
CLAW_AGENT=coding clawctl done <id> -m "Script written and tested" \
--meta '{"script":"~/scripts/rename-photos.py","tests":"passed"}'
Add a heartbeat to each agent's cron:
*/10 * * * * CLAW_AGENT=chat clawctl checkin
*/10 * * * * CLAW_AGENT=research clawctl checkin
*/10 * * * * CLAW_AGENT=coding clawctl checkin
Add to each agent's system prompt or AGENTS.md:
Before starting work: clawctl inbox --unread && clawctl list --mine
After completing work: clawctl review <id> (submits for approval)
When approved by coordinator: task auto-moves to done
Only claim tasks assigned to you or matching your role.
If
CLAW_AGENTis not set, clawctl falls back to$USERand prints a one-time warning on identity-sensitive commands.
Commands
Tasks
| Command | Description |
|---|---|
add SUBJECT |
Create a task. Options: -d description, -p 0|1|2 priority, --for AGENT pre-assign, --parent ID subtask |
list |
List active tasks. Options: --mine, --status STATUS, --owner AGENT, --all (include done/cancelled) |
next |
Show the highest-priority actionable task for the current agent |
claim ID |
Claim a task. Options: --force to override, --meta JSON |
start ID |
Begin work (transitions to in_progress). Options: --meta JSON |
done ID |
Complete a task. Options: -m note, --force, --meta JSON |
review ID |
Mark task as ready for review. Options: --meta JSON |
approve ID |
Approve a task in review (moves to done). Options: -m note, --meta JSON |
reject ID |
Reject a task in review (back to pending). Options: -r reason (required), --meta JSON |
reset ID |
Move a done/cancelled/blocked task back to pending. Options: --force, --meta JSON |
cancel ID |
Cancel a task. Options: --meta JSON |
block ID --by OTHER |
Mark task as blocked. Options: --meta JSON |
show ID |
Rich detail view: status grid, description, message thread, blockers |
search QUERY |
Full-text search across task subjects, descriptions, and messages |
board |
Kanban board view grouped by status |
legend |
Quick reference for all status symbols |
Messages
| Command | Description |
|---|---|
msg AGENT BODY |
Send a message. Options: --task ID, --type TYPE |
broadcast BODY |
Message all agents (type: alert) |
inbox |
Read messages. Options: --unread |
Fleet
| Command | Description |
|---|---|
register NAME |
Register an agent. Options: --role TEXT |
checkin |
Heartbeat — update presence, check for unread |
fleet |
Show all agents with status and current task |
whoami |
Show identity, role, and DB path |
Monitoring
| Command | Description |
|---|---|
feed |
Activity log. Options: --last N, --agent NAME, --meta |
summary |
Fleet overview with counts and recent events |
Dashboard
| Command | Description |
|---|---|
dashboard |
Start the web UI. Options: --port INT (default: 3737), --verbose |
dashboard --stop |
Stop the running dashboard |
Task statuses
pending ─→ claimed ─→ in_progress ─→ done
↘ blocked ↗ ↘ cancelled
↘ review ↗
list excludes done/cancelled by default and sorts by status priority (in_progress > claimed > blocked > review > pending), oldest first. Blocked tasks show their blocker IDs inline. --all flips to newest-first for history browsing.
Activity metadata
Mutating commands (claim, start, done, block, approve, reject, reset) accept --meta with a JSON string stored in the activity log. Use it to link back to external artifacts:
clawctl claim 1 --meta '{"source":"whatsapp","channel":"general"}'
clawctl done 1 -m "Top 3 picks with pros/cons" --meta '{"note":"~/notes/headphone-research.md"}'
# Review what happened overnight
clawctl feed --last 50 --agent research --meta
Web dashboard
A live web UI served by Flask with token authentication and SSE for real-time updates.
clawctl dashboard
# Opens at http://localhost:3737/?token=<TOKEN>
Features:
- Live board with SSE push updates (no polling)
- Task detail view with messages, metadata grid, and blocker links
- Approve, reject, and reset actions from the detail sheet
- Search bar (
/to focus) with results overlay for tasks and messages - Activity feed panel (
fto toggle) with per-agent filtering - Agent pills in header showing fleet status (active/idle/offline)
- Status badges and time-in-status on every card
- Blocked task cards show clickable blocker IDs
- Terminal/hacker aesthetic with optional CRT effects
- Keyboard accessible (
Escto close,Tabtrapping in modals,/for search,ffor feed) - Works on narrow viewports
- Token persisted at
~/.openclaw/.clawctl-tokenacross restarts
The dashboard shares the same SQLite database the CLI writes to. The CLI is the primary interface; the dashboard provides a visual overview with full review workflow support.
Architecture
┌─────────────────────────────┐
│ clawctl CLI (Python/Click) │ ← Every agent calls this
├─────────────────────────────┤
│ db.py — all SQL lives here │ ← Shared by CLI + Flask
├─────────────────────────────┤
│ SQLite (WAL mode) │ ← ~/.openclaw/clawctl.db
├─────────────────────────────┤
│ 5 tables + indexes: │
│ tasks task_deps │ ← Board + blocking graph
│ messages agents │ ← Comms + fleet registry
│ activity │ ← Append-only audit log
├─────────────────────────────┤
│ Flask dashboard (optional) │ ← dashboard/server.py
└─────────────────────────────┘
Key design decisions:
- All SQL in
db.py. The CLI and Flask server import it. No queries incli.pyorserver.py. - Race safety.
claim_task()andcomplete_task()use atomic single-UPDATE with WHERE guards and rowcount checks. No read-then-write. - Normalized blocking. Dependencies live in the
task_depsjoin table with a UNIQUE constraint. Not JSON columns. - Parameterized queries. Every query uses
?placeholders. No string interpolation. - Idempotent completions.
doneon an already-done task is a safe no-op.
Environment variables
| Variable | Default | Description |
|---|---|---|
CLAW_AGENT |
$USER (with warning) |
Agent identity for all commands |
CLAW_DB |
~/.openclaw/clawctl.db |
Database file path |
License
MIT
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file clawctl-0.3.2.tar.gz.
File metadata
- Download URL: clawctl-0.3.2.tar.gz
- Upload date:
- Size: 45.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.10.2 {"installer":{"name":"uv","version":"0.10.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f3e82dda32f0433b55f01b3405c26301d14e20bfbe2a21a801fbc58be6a97ac2
|
|
| MD5 |
eb5664968818822c8235201c2d4f53c2
|
|
| BLAKE2b-256 |
92a2a572036c39bc09f5de21a147eced9e67ff96f1f7e6180c3cc26afb5887f5
|
File details
Details for the file clawctl-0.3.2-py3-none-any.whl.
File metadata
- Download URL: clawctl-0.3.2-py3-none-any.whl
- Upload date:
- Size: 33.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.10.2 {"installer":{"name":"uv","version":"0.10.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1588b9a7818c032a7f419be495f330e8b78d0f2dbadc409fc531fb9603feb877
|
|
| MD5 |
796c5da3012859f0ebe05db17917af15
|
|
| BLAKE2b-256 |
a09c806816fa7db9b6775fcf316b9958798790a71f1fd08d582291b0420bfdbf
|