Open source mission control for your AI agents.
ClawTrol is a kanban-style dashboard for managing AI coding agents. Track tasks, assign work to agents, monitor their activity in real-time, and collaborate asynchronously. Forked from ClawDeck with extended agent integration features.
๐ง Early Development โ ClawTrol is under active development. Expect breaking changes.
Self-host (recommended)
Clone this repo and run your own instance. See Self-Hosting below.
Contribute
PRs welcome! See CONTRIBUTING.md.
- OpenClaw Gateway โ Instant wake via webhook when tasks are assigned
- Real-time Triggers โ No polling delay for agent activation
- Command Injection Prevention โ Validation commands sandboxed with Shellwords + allowlist
- API Token Hashing โ Tokens stored as SHA-256 hashes, never plaintext
- AI Key Encryption โ
ai_api_keyencrypted at rest with Rails credentials - Settings Page โ Tabbed layout (Profile / Agent / AI / Integration)
- You create tasks and organize them on boards.
- You move work to
up_nextand assign it to the agent queue. - ClawTrol auto-runner wakes runnable work with nightly gating and in-progress guardrails (base cap 4, burst cap 8 only when queue pressure is high and no recent errors/rate-limits).
- OpenClaw is the orchestrator: it picks claimed work, routes model/persona, and executes.
- OpenClaw must always report structured outcome via
POST /api/v1/hooks/task_outcome. - OpenClaw must always persist execution output via
POST /api/v1/hooks/agent_complete. - Task moves to
in_review; follow-up isYES/NOplus recommendation, never silent. - If follow-up is needed, requeue happens only after explicit human approval, using the same card (
POST /api/v1/tasks/:id/requeue). - If no follow-up is needed, task remains in
in_reviewand the human decides next action.
- Main guide:
docs/OPENCLAW_ONBOARDING.md - Fast path in UI:
Settings -> Integration -> Agent Install Prompt - Contract summary:
- OpenClaw executes work; ClawTrol stores state and reporting.
- Every completed run sends both hooks:
task_outcomethenagent_complete. - Follow-up recommendation is mandatory (
needs_follow_up: true|false). - Same-task follow-up is preferred to avoid kanban bloat.
- Nightly window for Argentina:
23:00-08:00(America/Argentina/Buenos_Aires, UTC-3).
ClawTrol works best when your orchestrator has an explicit "tooling + reporting contract" prompt so it:
- knows which endpoints exist and how to authenticate
- always reports back deterministically at the end of each run
- can requeue the same task for follow-ups (no kanban bloat)
In your running instance, open http://<host>:<port>/settings โ Integration and use Agent Install Prompt.
If you're integrating manually:
- API endpoints live under
/api/v1/*(Bearer token) - Completion hooks live under
/api/v1/hooks/*(X-Hook-Token) - Follow-up is signaled via
POST /api/v1/hooks/task_outcomewithrecommended_action="requeue_same_task"
- Ruby 3.3.1 / Rails 8.1
- PostgreSQL with Solid Queue, Cache, and Cable
- Solid Queue โ Background jobs for validation, async processing, and webhook-driven workflows
- ActionCable โ WebSocket for real-time kanban + agent activity
- Hotwire (Turbo + Stimulus) + Tailwind CSS v4
- Propshaft โ Asset pipeline with importmap-rails
- 45+ Stimulus Controllers โ Full client-side interactivity
- Authentication via GitHub OAuth or email/password
- Docker Compose โ Production-ready setup with
install.sh
- Ruby 3.3.1
- PostgreSQL
- Bundler
git clone https://github.com/wolverin0/clawtrol.git
cd clawtrol
chmod +x install.sh
./install.sh
install.shis safe to re-run and appendsSECRET_KEY_BASEto.env.productiononly when missing.
Visit http://localhost:4001
git clone https://github.com/wolverin0/clawtrol.git
cd clawtrol
bundle install
bin/rails db:prepare
bin/devVisit http://localhost:3000
ClawTrol supports two authentication methods:
- Email/Password โ Works out of the box
- GitHub OAuth โ Optional, recommended for production
- Go to GitHub Developer Settings
- Click New OAuth App
- Fill in:
- Application name: ClawTrol
- Homepage URL: Your domain
- Authorization callback URL:
https://yourdomain.com/auth/github/callback
- Add credentials to environment:
GITHUB_CLIENT_ID=your_client_id
GITHUB_CLIENT_SECRET=your_client_secretConfigure webhook in Settings โ OpenClaw Integration:
- Gateway URL: Your OpenClaw gateway endpoint
- Gateway Token: Your authentication token
- Agent Prompt: copy from
Settings -> Integration -> Agent Install Prompt - Onboarding + self-heal:
docs/OPENCLAW_ONBOARDING.md
bin/rails test
bin/rails test:system
bin/rubocopHave an AI assistant with shell access (OpenClaw, Claude Code, Codex)? Give it the prompt below to install ClawTrol and fully configure itself as your agent โ API tokens, webhook hooks, heartbeat polling, and auto-runner included.
Copy this entire prompt to your AI assistant:
Install and configure ClawTrol (AI agent mission control) for me. Do ALL steps โ don't stop until you've verified everything works.
Step 1 โ Clone & Install
cd ~ && git clone https://github.com/wolverin0/clawtrol.git clawdeck cd clawdeck chmod +x install.sh && ./install.shIf Docker isn't available, fall back to manual:
bundle install && bin/rails db:prepare && bin/devStep 2 โ Wait for server
- Docker: port 4001
- Manual: port 3000
- Health check:
curl -sf http://localhost:PORT/up(retry up to 30s)Step 3 โ Create user account
cd ~/clawdeck && bin/rails runner " User.create!( email: 'MY_EMAIL', password: 'MY_PASSWORD', name: 'MY_NAME' ) puts 'โ User created' "Step 4 โ Generate API token + Hooks token
cd ~/clawdeck && bin/rails runner " user = User.find_by!(email: 'MY_EMAIL') api_token = user.api_tokens.create!(name: 'Agent') puts 'API_TOKEN=' + api_token.token puts 'HOOKS_TOKEN=' + Rails.application.config.hooks_token.to_s "Save both tokens โ the API token is only shown once.
Step 5 โ Create a default board
curl -s -X POST http://localhost:PORT/api/v1/boards \ -H "Authorization: Bearer API_TOKEN" \ -H "Content-Type: application/json" \ -d '{"name": "Main", "icon": "๐"}' | jq .Step 6 โ Configure yourself as the ClawTrol agent
Add these to your workspace TOOLS.md (or equivalent config):
### ClawTrol (Task Dashboard / Mission Control) | Key | Value | |-----|-------| | URL | http://HOST:PORT | | API Token | API_TOKEN | | Hooks Token | HOOKS_TOKEN | | Agent Name | YOUR_AGENT_NAME | | Agent Emoji | YOUR_EMOJI |Add these env vars (e.g.,
~/.openclaw/.envor your agent's env):CLAWTROL_API_TOKEN=API_TOKEN CLAWTROL_HOOKS_TOKEN=HOOKS_TOKEN
APP_BASE_URL=http://HOST:PORT # Used for webhook callbacks and links
**Step 7 โ Set up heartbeat polling** Add to your HEARTBEAT.md (or equivalent periodic check): ```markdown ### ClawTrol Tasks # Health check first curl -sf http://HOST:PORT/up >/dev/null 2>&1 || echo "โ ๏ธ ClawTrol DOWN" # Poll for assigned tasks source ~/.openclaw/.env # or wherever your env is curl -s -H "Authorization: Bearer $CLAWTROL_API_TOKEN" \ http://HOST:PORT/api/v1/tasks?assigned=true&status=up_nextStep 8 โ Set up the completion contract
After EVERY task you complete, fire these two hooks IN ORDER:
Hook 1 โ
task_outcome(structured result):curl -s -X POST http://HOST:PORT/api/v1/hooks/task_outcome \ -H "X-Hook-Token: $CLAWTROL_HOOKS_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "version": "1", "task_id": TASK_ID, "run_id": "SESSION_UUID", "ended_at": "ISO8601_TIMESTAMP", "needs_follow_up": false, "recommended_action": "in_review", "summary": "What was accomplished", "achieved": ["item 1", "item 2"], "evidence": ["proof 1"], "remaining": [] }'Hook 2 โ
agent_complete(saves output + transitions status):curl -s -X POST http://HOST:PORT/api/v1/hooks/agent_complete \ -H "X-Hook-Token: $CLAWTROL_HOOKS_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "task_id": TASK_ID, "session_id": "SESSION_UUID", "findings": "Detailed summary of work done", "output_files": ["file1.rb", "file2.js"] }'Step 9 โ Verify the full loop
Create a test task, execute it, fire both hooks, confirm it reaches
done(orin_review):# Create TASK=$(curl -s -X POST http://HOST:PORT/api/v1/tasks \ -H "Authorization: Bearer $CLAWTROL_API_TOKEN" \ -H "Content-Type: application/json" \ -d '{"name":"Test: onboarding verification","board_id":BOARD_ID,"status":"up_next","tags":["test","quick-fix"],"assigned_to_agent":true}') TASK_ID=$(echo $TASK | jq -r .id) # Move to in_progress curl -s -X PATCH http://HOST:PORT/api/v1/tasks/$TASK_ID \ -H "Authorization: Bearer $CLAWTROL_API_TOKEN" \ -H "Content-Type: application/json" \ -d '{"status":"in_progress"}' # Fire hooks (use a random UUID as run_id) # ... (fire task_outcome + agent_complete as above) # Verify final status curl -s -H "Authorization: Bearer $CLAWTROL_API_TOKEN" \ http://HOST:PORT/api/v1/tasks/$TASK_ID | jq .status # Should be "done" (auto-review: quick-fix + output) or "in_review"Step 10 โ Report to me
Tell me:
- โ Dashboard URL
- โ Board created
- โ API + Hooks tokens saved
- โ Heartbeat configured
- โ Completion hooks tested
- โ Test task verified end-to-end
Replace before pasting:
| Placeholder | Description |
|---|---|
MY_EMAIL |
Your login email |
MY_PASSWORD |
Secure password (12+ chars) |
MY_NAME |
Display name |
HOST:PORT |
Your server address (e.g., localhost:4001) |
YOUR_AGENT_NAME |
What your agent calls itself |
YOUR_EMOJI |
Agent's signature emoji |
BOARD_ID |
Board ID from Step 5 (usually 1) |
Requirements:
- Docker (recommended) or Ruby 3.3+ with PostgreSQL
- AI assistant with shell/exec access (OpenClaw, Claude Code, Codex CLI, etc.)
- 5 minutes
ClawTrol exposes a REST API for agent integrations. Get your API token from Settings.
Include your token in every request:
Authorization: Bearer YOUR_TOKEN
Include agent identity headers:
X-Agent-Name: Otacon
X-Agent-Emoji: ๐
# List boards
GET /api/v1/boards
# Get board
GET /api/v1/boards/:id
# Create board
POST /api/v1/boards
{ "name": "My Project", "icon": "๐" }
# Update board
PATCH /api/v1/boards/:id
# Delete board
DELETE /api/v1/boards/:id# List tasks (with filters)
GET /api/v1/tasks
GET /api/v1/tasks?board_id=1
GET /api/v1/tasks?status=in_progress
GET /api/v1/tasks?assigned=true # Your work queue
# Get task
GET /api/v1/tasks/:id
# Create task
POST /api/v1/tasks
{ "name": "Research topic X", "status": "inbox", "board_id": 1 }
# Update task (with optional activity note)
PATCH /api/v1/tasks/:id
{ "status": "in_progress", "activity_note": "Starting work on this" }
# Delete task
DELETE /api/v1/tasks/:id
# Complete task
PATCH /api/v1/tasks/:id/complete
# Assign/unassign to agent
PATCH /api/v1/tasks/:id/assign
PATCH /api/v1/tasks/:id/unassign# Create task ready for agent (auto-routes to board based on name)
POST /api/v1/tasks/spawn_ready
{ "name": "ProjectName: Task title", "description": "...", "model": "opus" }
# Link agent session to task
POST /api/v1/tasks/:id/link_session
{ "agent_session_id": "uuid", "agent_session_key": "key" }
# Save agent output and complete (legacy/manual path)
POST /api/v1/tasks/:id/agent_complete
{ "output": "Task completed successfully", "status": "in_review" }
# Recover missing output from transcript (.jsonl)
POST /api/v1/tasks/:id/recover_output
# Get live agent activity log
GET /api/v1/tasks/:id/agent_log
# Check session health
GET /api/v1/tasks/:id/session_health# Generate AI-suggested follow-up
POST /api/v1/tasks/:id/generate_followup
# Create follow-up task
POST /api/v1/tasks/:id/create_followup
{ "name": "Follow-up task name", "description": "..." }POST /api/v1/hooks/agent_complete
Primary endpoint for autonomous agents to self-report completion and persist output. This is the recommended integration path for production agents.
Authentication
Send webhook token in header:
X-Hook-Token: YOUR_HOOKS_TOKEN
Request Body (JSON)
| Field | Type | Required | Description |
|---|---|---|---|
task_id |
integer | โ | Target task ID to update |
findings |
string | โ | Work summary; stored under ## Agent Output |
session_id |
string | optional | Agent session UUID for transcript/activity linking |
session_key |
string | optional | Session key used by terminal/transcript viewer |
output_files |
array[string] | optional | Explicit output file list (merged with auto-extracted files) |
Example Request
curl -s -X POST http://YOUR_HOST:4001/api/v1/hooks/agent_complete \
-H "X-Hook-Token: YOUR_HOOKS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"task_id": 302,
"findings": "Implemented feature X and updated docs.",
"session_id": "sess_123",
"session_key": "agent:main:subagent:abc",
"output_files": ["README.md", "app/controllers/tasks_controller.rb"]
}'Behavior
- Auto-appends/updates
## Agent Outputin task description - Auto-transitions task status to
in_review - Links session metadata when provided
- Auto-extracts output files from findings text and transcript commit data
- Merges + deduplicates discovered files and provided
output_files
Success Response
200 OKwith updated task payload
Error Responses
401 Unauthorizedโ missing/invalidX-Hook-Token404 Not Foundโ task not found422 Unprocessable Entityโ invalid payload (e.g., missing required fields)
# Get all models status
GET /api/v1/models/status
# Get best available model
POST /api/v1/models/best
{ "preferred": "opus" }
# Record rate limit for a model
POST /api/v1/models/:name/limit
{ "duration_minutes": 60 }# List tonight's mission selections
GET /api/v1/nightshift/selections
# Update mission status (for agents reporting back)
PATCH /api/v1/nightshift/selections/:id
{ "status": "completed", "result": "All checks passed" }
# List all available missions
GET /api/v1/nightshift/tasks
# Launch selected missions
POST /api/v1/nightshift/launch
{ "task_ids": [1, 3, 5] }# List saved links
GET /api/v1/saved_links
# Create saved link
POST /api/v1/saved_links
{ "url": "https://github.com/example/repo", "title": "Example Repo" }
# Update saved link
PATCH /api/v1/saved_links/:id
# Get pending links
GET /api/v1/saved_links/pending# List swarm ideas
GET /api/v1/swarm_ideas
# Create swarm idea
POST /api/v1/swarm_ideas
{ "swarm_idea": { "title": "Fix auth bugs", "description": "...", "category": "bug-fix", "suggested_model": "codex" } }
# Update swarm idea
PATCH /api/v1/swarm_ideas/:id
# Delete swarm idea
DELETE /api/v1/swarm_ideas/:id
# Launch idea as task
POST /api/v1/swarm_ideas/:id/launch
{ "board_id": 1, "model": "codex" }# Pipeline status overview
GET /api/v1/pipeline/status
# Enable pipeline on a board
POST /api/v1/pipeline/enable_board/:board_id
# Disable pipeline on a board
POST /api/v1/pipeline/disable_board/:board_id
# Get pipeline log for a task
GET /api/v1/pipeline/task/:id/log
# Reprocess a task through the pipeline
POST /api/v1/pipeline/reprocess/:id
# Route a specific task through pipeline
POST /api/v1/tasks/:id/route_pipeline
# Get pipeline info for a task
GET /api/v1/tasks/:id/pipeline_info# List agent personas
GET /api/v1/agent_personas
# Create persona
POST /api/v1/agent_personas
{ "name": "Security Bot", "board_id": 1, "model": "codex" }
# Import personas
POST /api/v1/agent_personas/import
# Update persona
PATCH /api/v1/agent_personas/:id
# Delete persona
DELETE /api/v1/agent_personas/:id# List factory loops
GET /api/v1/factory/loops
# Create factory loop
POST /api/v1/factory/loops
{ "name": "Nightly bugs", "board_id": 1 }
# Control loop
POST /api/v1/factory/loops/:id/play
POST /api/v1/factory/loops/:id/pause
POST /api/v1/factory/loops/:id/stop
# Loop metrics
GET /api/v1/factory/loops/:id/metrics
# Complete a factory cycle
POST /api/v1/factory/cycles/:id/complete# List recurring task templates
GET /api/v1/tasks/recurring| Status | Description |
|---|---|
inbox |
New, not prioritized |
up_next |
Ready to be assigned |
in_progress |
Being worked on |
in_review |
Done, needs human review |
done |
Complete |
unstarted, triaged, context_ready, routed, executing, verifying, completed, failed
none, low, medium, high
opus, codex, gemini, glm, sonnet, flash
- Tabbed Interface โ Multiple agent sessions in tabs
- Hover Preview โ Quick preview on card hover
- Pin to Terminal โ Lock a task's output in view
- Live Streaming โ Real-time agent activity via WebSocket
- Session Transcript โ Full conversation log with role icons and tool calls
- WebSocket Updates โ Real-time via ActionCable (polling fallback)
- Spinner Indicator โ Shows active agent on card
- Context Menu โ Right-click to move between boards/statuses
- Board Tabs โ Quick navigation between projects
- Drag & Drop โ SortableJS with delete drop zone
- Dependency Blocking โ ๐ badge prevents moving blocked tasks
- Two-Column Layout โ Details left, agent activity + files right (desktop)
- Auto-Save โ Debounced 500ms save on field changes
- File Viewer โ Browse output files with syntax highlighting + fullscreen
- Agent Activity โ Live session log with WebSocket updates
- Priority Selector โ Visual fire icon buttons
- Validation Output โ View command results inline
This project uses Conventional Commits. A git hook validates your commit messages automatically.
Format: <type>[optional scope]: <description>
Types: feat, fix, docs, chore, refactor, test, ci, style, perf, build
Setup the hook:
ln -sf ../../bin/commit-msg-hook .git/hooks/commit-msgGenerate changelog:
bin/changelogThe changelog is also auto-generated on pushes to main via GitHub Actions.
We welcome contributions! Please see CONTRIBUTING.md for guidelines.
MIT License โ see LICENSE for details.
- ๐ GitHub: wolverin0/clawtrol
- ๐ฆ Upstream: clawdeckio/clawdeck
ClawTrol stores routing metadata on each task and always routes completion output to the task origin.
origin_chat_id(string) โ Telegram chat/group ID where the task originatedorigin_thread_id(integer) โ Telegram topic/thread ID where the task originatedorigin_session_key(string, optional) โ OpenClaw session for direct session-delivery
- Task created from a Telegram topic โ output is sent back to that same topic.
- Task created from chat root (no topic) โ output is sent to chat root.
- No
origin_chat_idโ Telegram delivery is skipped (no fallback to default chat/topic). - There is no default-thread fallback in strict mode.
- Set
CLAWTROL_TELEGRAM_BOT_TOKENenv var with your Telegram bot token. - Ensure task creation always includes
origin_chat_idand, for forum topics,origin_thread_id.
curl -X POST http://localhost:4001/api/v1/tasks \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"task": {"name": "Fix bug", "origin_chat_id": "-100123456789", "origin_thread_id": 42}}'- On
in_review/done, completion notification is delivered to the stored origin. - Webhook notifications (
webhook_notification_url) still work as a secondary mechanism.
Built with ๐ฆ by the OpenClaw community.
