Clawback is a Claude Code channel plugin. It connects to a hosted server via WebSocket and delivers events — webhooks and crons — directly into your Claude Code session.
A webhook hits the server or a cron fires. The server verifies the signature, extracts the event type, and matches it to a route.
The event is pushed to your connected session over WebSocket. If you're offline, it queues until you reconnect.
Claude receives the event with the matched skill, processes it, and acknowledges. The next event arrives only after the current one is done.
git clone https://github.com/clawback-io/clawback.git ~/.config/claude/channels/clawback-plugin cd ~/.config/claude/channels/clawback-plugin bun install
From whichever project directory you want to use Clawback in:
# Add to current project claude mcp add -s project clawback -- bun run \ --cwd ~/.config/claude/channels/clawback-plugin --shell=bun --silent start # Or add globally (all projects) claude mcp add clawback -- bun run \ --cwd ~/.config/claude/channels/clawback-plugin --shell=bun --silent start
Visit getclawback.io/auth/cli to log in with GitHub. You'll get a shell command to save your connection config. Paste it in your terminal.
The plugin connects automatically on startup. Once connected, you manage everything through Claude in natural language.
Claude will create the source, configure event routing, and give you the webhook URL to paste into your GitHub repo's webhook settings.
Claude will set up a persistent cron job that fires into your session on schedule.
After authenticating, your config is saved at ~/.config/claude/channels/clawback/config.json (or ~/.claude/channels/clawback/config.json depending on your system):
{
"remote": "wss://getclawback.io/ws",
"connectionToken": "cbt_your_token_here",
"notifications": true
}
| Field | Required | Description |
|---|---|---|
remote | Yes | WebSocket URL of the Clawback server |
connectionToken | Yes | Connection token (starts with cbt_) |
notifications | No | Desktop notifications when events are processed (notify-send on Linux, osascript on macOS). Default: false |
dataDir | No | Local data directory override |
| Variable | Description |
|---|---|
CLAWBACK_SESSION | Set session tag for multi-instance routing |
CLAWBACK_CONFIG | Override config file path |
A webhook source is an endpoint on the Clawback server that accepts incoming webhooks from an external service. Each source has a slug (used in the URL), a verification type, and optional route mappings that tell Claude what to do with each event type.
Claude will create the source and give you a webhook URL to paste into your service's webhook settings.
When a webhook arrives, Clawback needs to know two things: what kind of event is it, and what should Claude do with it.
Different services put the event type in different places. You tell Clawback where to look:
| Service | Where the event type lives | Example value |
|---|---|---|
| GitHub | X-GitHub-Event header + action field in body | pull_request.opened |
| Stripe | type field in body | payment_intent.succeeded |
| Shopify | X-Shopify-Topic header | orders/create |
Once Clawback can extract the event type, you map specific events to skills or prompts. When an event matches, that skill is prepended to the payload before delivering it to Claude.
With this setup:
pull_request.opened webhook arrives — Claude gets /review with the full payloadissues.opened webhook arrives — Claude gets /triage with the payloadpush event arrives — silently dropped (no matching route)You can also use * as a catch-all to handle any events that don't have a specific route.
Clawback supports HMAC signature verification for incoming webhooks. When creating a source, you specify the verification type:
github — verifies the X-Hub-Signature-256 header using your webhook secretstripe — verifies Stripe's Stripe-Signature headergeneric — HMAC-SHA256 verification with a configurable headernone — no signature verification (for services that don't support it)Webhook secrets are encrypted at rest with AES-256-GCM. The plaintext secret is never stored — only the encrypted form.
Clawback crons are persistent scheduled jobs stored on the server. Unlike Claude Code's built-in /schedule which expires after 7 days, Clawback crons run forever until you delete them. They survive session restarts, disconnections, and machine reboots.
Tell Claude what schedule you want in natural language:
Crons use standard 5-field cron expressions under the hood (minute hour day-of-month month day-of-week), but you don't need to know the syntax — Claude will translate for you.
event_ack after handling each cron event before the next one arrivesThe cron prompt can be anything:
/catchup, /review-prs, /deploy-check — Claude invokes the skill directly"Check if there are any open PRs that need review" — Claude treats it as a promptChannels like Telegram deliver messages directly into Claude's context — if two arrive at once, they compete for attention and can interrupt each other mid-task. There's no ordering, no queue, and no guarantee that Claude finishes one thing before starting the next.
Clawback is different. Events go through a managed queue — one at a time, each fully processed and acknowledged before the next one starts. If events arrive while Claude is busy, they wait. If you're offline, they queue on the server until you reconnect. Nothing is lost, nothing is interrupted (unless you explicitly use interrupt priority).
This makes Clawback the right choice for anything that needs reliable, sequential processing: webhook handlers, cron jobs, automated workflows, and multi-agent coordination.
| Scenario | Result |
|---|---|
Event tagged deploys, session deploys connected | Delivered immediately |
Event tagged deploys, session deploys not connected | Queued until it reconnects |
Event tagged deploys, only oncall connected | Not delivered (wrong tag) |
| Untagged event, untagged session connected | Delivered immediately |
| Untagged event, only tagged sessions connected | Not delivered |
The key rule: tagged sessions only receive events with their tag, and untagged sessions only receive untagged events.
Sessions can send messages directly to each other — no webhook setup needed. Each session can discover other connected sessions and start a conversation.
Here's a real example. You have two tagged sessions — deploys managing releases and oncall handling alerts:
Claude in deploys discovers oncall via session_list, sends a message, and they coordinate directly:
deploys → oncall: "Hey, we're about to push v2.4.0. Any open incidents or blockers I should know about?"
oncall → deploys: "There's a memory leak in the payments service — found it an hour ago, patch is ready but not merged. Hold the deploy until I confirm the fix is in."
deploys → oncall: "Got it, holding deploy. Let me know when the fix lands and I'll include it."
Each message is delivered as an event in the receiving session. Claude processes it, decides how to respond, and sends a reply back — all without any user involvement after the initial prompt.
You can also broadcast to every connected session at once:
Messages to offline sessions are durably queued and delivered when they reconnect. Broadcasts (*) go only to currently connected sessions.
Disable inter-agent messaging per-session with "sessionMessaging": false in config.
| Tool | Description |
|---|---|
source_create | Create a webhook source with optional HMAC verification (github, stripe, generic, none), event type extraction, route mapping, and session targeting |
source_list | List all configured webhook sources with their slugs, verification types, routes, and session tags |
source_delete | Delete a webhook source by ID |
| Tool | Description |
|---|---|
cron_create | Create a persistent cron job with a 5-field schedule, prompt/skill, optional label, and session targeting |
cron_list | List all cron jobs with their schedules, prompts, labels, and session tags |
cron_delete | Delete a cron job by ID |
| Tool | Description |
|---|---|
event_ack | Acknowledge the current event with a summary of what was done. Required after every webhook and cron event — the next event won't arrive until you ack |
| Tool | Description |
|---|---|
account_info | Show your webhook base URL, profile ID, connected client count, and current session tag |
event_history | View recent event processing history — source, skill, summary, duration, and whether it timed out |
token_create | Create an additional connection token for use on another machine — does not affect the current connection |
token_list | List all connection tokens with labels and last seen times. Marks which token is currently in use. Does not reveal token values |
token_rotate | Rotate your connection token — creates a new one, revokes the old, and updates your local config file |
| Tool | Description |
|---|---|
session_send | Send a message to another session by tag. Supports comma-separated targets or * to broadcast to all connected sessions |
session_list | List all currently connected sessions for your account, with session tags |
Webhook sources, crons, and session messages support a priority parameter:
| Level | Behavior |
|---|---|
normal | Default. Added to the back of the queue. |
priority | Jumps to the front of the queue. Still waits for the current event to finish. |
interrupt | Immediately stops the current event (re-queues it to the front) and dispatches. Use for production emergencies. |