⭐ Optional support: the interactive repo-local install paths (
./install.shandclawhip installfrom a clone) can offer to star this repo after a successful install whenghis installed and authenticated. Skip it with--skip-star-promptorCLAWHIP_SKIP_STAR_PROMPT=1. Community: Join the clawhip Discord at https://discord.gg/jq6jnSGABY.
gajae-claw (clawhip) is the control plane for agents: route events from GitHub, Discord, tmux, and other tools to the right human or agent, record what happened, and separate automatic actions from approval-required actions.
Use clawhip when you have an event, a destination, and a policy for whether the next step can happen automatically or needs a human/operator approval. These recipes use placeholder channel IDs and names; replace them with your own public-safe values.
When GitHub reports a pull request event, route it to the project channel so the right maintainer sees it.
# ~/.clawhip/config.toml
[[routes]]
event = "github.pr-status-changed"
filter = { repo = "my-app" }
sink = "discord"
channel = "PROJECT_CHANNEL_ID"
format = "compact"
Example event shape:
{
"source": "github",
"event": "pull_request.opened",
"repo": "my-app",
"pr": 42,
"action": "notify",
"target": "PROJECT_CHANNEL_ID"
}
Result: clawhip records the routed event and posts a compact PR notification to the project channel.
Let routine CI status flow to the project channel, but reserve an escalation route for repeated failures. Your CI watcher or automation can emit the second-failure event after it observes two failed runs for the same PR or branch.
# ~/.clawhip/config.toml
[[routes]]
event = "github.ci-failed"
filter = { repo = "my-app" }
sink = "discord"
channel = "PROJECT_CHANNEL_ID"
format = "compact"
[[routes]]
event = "ci.failed-twice"
filter = { repo = "my-app" }
sink = "discord"
channel = "ESCALATION_CHANNEL_ID"
format = "alert"
Example escalation payload:
{
"source": "ci-watcher",
"event": "ci.failed-twice",
"repo": "my-app",
"branch": "feature/auth-flow",
"summary": "CI failed twice on the same PR; test logs point at integration/auth_test.",
"action": "summarize_and_escalate",
"target": "ESCALATION_CHANNEL_ID"
}
Result: normal failures stay low-noise; repeated failures get a short summary in the escalation channel.
Some requests should notify an operator instead of letting an agent act immediately. Send those events to an approval channel and keep the requested action in the message body.
# ~/.clawhip/config.toml
[[routes]]
event = "agent.approval-requested"
filter = { repo = "my-app" }
sink = "discord"
channel = "APPROVAL_CHANNEL_ID"
format = "alert"
Example approval event:
{
"source": "agent",
"event": "agent.approval-requested",
"repo": "my-app",
"request": "merge PR #42 after checks pass",
"reason": "merge changes the shared branch and should be operator-approved",
"policy": "approval_required",
"action": "notify_operator",
"target": "APPROVAL_CHANNEL_ID"
}
Result: clawhip records the request and alerts an operator; the agent waits for explicit approval before cleanup, merge, or config-changing work.
Human install pitch:
Just tag @openclaw and say: install this https://github.com/Yeachan-Heo/clawhip
Then OpenClaw should:
install.shSKILL.md and attach the skill[providers.discord] is the preferred config surface, while legacy [discord] still loads.See ARCHITECTURE.md for the release architecture that ships in v0.3.0.
clawhip no longer treats provider-specific launch wrappers as the public integration surface. Codex and Claude own session launch plus hook registration; clawhip stays the routing, normalization, and delivery layer.
Shared v1 hook events:
SessionStartPreToolUsePostToolUseUserPromptSubmitStopLocal ingress for sample payloads and manual verification:
clawhip native hook --provider codex --file payload.json
clawhip native hook --provider claude --file payload.json
cat payload.json | clawhip native hook --provider codex
Recommended installation model:
~/.clawhip/hooks/native-hook.mjs~/.codex/hooks.json or <repo>/.codex/hooks.json~/.claude/settings.json.clawhip/project.json.clawhip/hooks/ only for additive augmentation such as frontmatter or recent contextclawhip still pairs well with tmux when you want keyword/stale monitoring, but tmux is now optional and no longer the primary hook-registration surface.
For tmux-backed recovery into an already-running hooked session, use:
clawhip deliver --session <tmux-session> --prompt "..." --max-enters 4
clawhip deliver validates repo-local prompt-submit hook setup, confirms the target pane is an
active Codex/Claude (including OMC/OMX wrapper) session, then retries Enter until
.clawhip/state/prompt-submit.json changes or the bounded retry limit is reached.
clawhip now documents a Claw OS-style memory pattern where MEMORY.md is the hot pointer/index layer and detailed memory lives in structured filesystem shards under memory/.
Use this when you want:
Start here:
Runtime support now includes a small bootstrap/inspection surface:
# create a scaffold in the current repo
clawhip memory init --project clawhip --channel discord-alerts --agent codex
# inspect whether the expected files and directories exist
clawhip memory status --project clawhip --channel discord-alerts --agent codex
clawhip memory init creates MEMORY.md, memory/README.md, a daily shard, a project shard,
topic files, and optional channel/agent shards without overwriting existing files unless you pass
--force.
clawhip now includes a simple plugins/ directory for tool-specific shell bridges.
Each plugin lives in its own subdirectory with:
plugin.toml for lightweight metadatabridge.sh for shell hook entrypointsBuilt-in starter plugins:
plugins/codex/plugins/claude-code/List installed plugins with:
clawhip plugin list
Operational spec for OpenClaw / Clawdbot agents consuming this repo.
Repo role:
Attachment model:
SKILL.md = attach/install/usage instructions for OpenClaw / ClawdbotDefault daemon endpoint:
http://127.0.0.1:25294Primary install entrypoint:
@openclaw install <repo_url>
Expected downstream automation behavior:
./install.shSKILL.mdReference repo URL:
https://github.com/Yeachan-Heo/clawhip
Recommended: Create a dedicated Discord bot for clawhip. Do not reuse your Clawdbot / OpenClaw bot token.
clawhip sends high-volume notifications (commits, PRs, tmux keyword alerts, stale warnings). Using a separate bot keeps these cleanly separated from your AI chat bot.
[providers.discord]
token = "your-dedicated-clawhip-bot-token"
default_channel = "your-default-channel-id"
[dispatch]
routine_batch_window_secs = 5
ci_batch_window_secs = 300
Legacy [discord] config is still accepted and normalized at load time.
[dispatch].routine_batch_window_secs controls the default Discord-only routine burst batch window. Leave it unset to keep the 5-second default, or set it to 0 to disable routine batching entirely. In v1, grouped routine bursts suppress route/event mentions for 2+ items, while explicit failure/stale/CI paths still bypass the routine batcher.
[dispatch].ci_batch_window_secs controls how long clawhip waits before flushing a GitHub CI batch summary. Leave it unset to keep the 30-second default, or increase it for longer workflows that finish jobs over several minutes.
Webhook mode works without a bot token.
Quick start:
clawhip setup --webhook "https://discord.com/api/webhooks/..."
Bounded setup presets also support:
clawhip setup \
--bot-token "discord-bot-token" \
--default-channel "1234567890" \
--default-format alert \
--daemon-base-url "http://127.0.0.1:25294"
clawhip setup stays non-interactive and intentionally limited to five presets only:
Advanced routes and monitor definitions are still edited manually in the config file or revisited through the bounded clawhip config editor surface.
Route example:
[[routes]]
event = "tmux.keyword"
sink = "discord"
webhook = "https://discord.com/api/webhooks/..."
Slack webhook routes work without a bot token.
https://hooks.slack.com/services/... URL into a routeRoute examples:
[[routes]]
event = "git.commit"
filter = { repo = "my-app" }
slack_webhook = "https://hooks.slack.com/services/T.../B.../xxx"
format = "compact"
[[routes]]
event = "tmux.keyword"
sink = "slack"
webhook = "https://hooks.slack.com/services/T.../B.../yyy"
format = "alert"
[CLI / webhook / git / GitHub / tmux]
-> [sources]
-> [mpsc queue]
-> [dispatcher]
-> [router -> renderer -> Discord/Slack sink]
-> [Discord REST / Slack webhook delivery]
Input sources in v0.3.0:
clawhip tmux new / clawhip tmux watch registration pathInput:
clawhip send --channel <id> --message "text"
Behavior:
/api/eventVerification:
clawhip statusInput:
issues.openedclawhip github issue-opened ...Behavior:
github.issue-openedgithub.*Verification:
Input:
issue_comment.createdBehavior:
github.issue-commentedgithub.*Verification:
Input:
issues.closedBehavior:
github.issue-closedgithub.*Verification:
Input:
pull_request.*clawhip github pr-status-changed ...Behavior:
github.pr-status-changedgithub.*Verification:
Input:
clawhip git commit ...Behavior:
git.commitVerification:
Canonical native routing now starts from provider-native Codex and Claude hook payloads and
enters clawhip through clawhip native hook.
Shared v1 hook events:
SessionStartPreToolUsePostToolUseUserPromptSubmitStopStable routing metadata (when available):
providereventsession_iddirectoryworktree_pathrepo_nameprojectbranchtool_namecommandsummaryevent_timestampAugmentation rules:
.clawhip/hooks/ scripts may only add fields or enrich message/contextRoute guidance:
provider, event, repo_name, project, and branchSee docs/native-event-contract.md for the routing/augmentation
guide and docs/event-contract-v1.md for the frozen shared-event
reference.
Input:
clawhip agent started --name worker-1 --session sess-123 --project my-repo
clawhip agent blocked --name worker-1 --summary "waiting for review"
clawhip agent finished --name worker-1 --elapsed 300 --summary "PR created"
clawhip agent failed --name worker-1 --error "build failed"
Behavior:
agent.started, agent.blocked, agent.finished, or agent.failedagent.*Verification:
agent.* route rules match each event typeInput:
clawhip tmux keyword ...Behavior:
tmux.keywordtmux.*Verification:
Input:
clawhip tmux stale ...Behavior:
tmux.staletmux.*Verification:
Preferred input:
clawhip native hook --provider codex --file payload.json
clawhip native hook --provider claude --file payload.json
clawhip tmux list
Fallback/debug input:
clawhip tmux new -s <session> \
--mention '<@id>' \
--keywords 'error,PR created,FAILED,complete' \
--stale-minutes 10 \
--format alert \
--retry-enter true \
--retry-enter-count 4 \
--retry-enter-delay-ms 250 \
--shell /bin/zsh \
-- command args
clawhip tmux watch -s <existing-session> \
--mention '<@id>' \
--keywords 'error,PR created,FAILED,complete' \
--stale-minutes 10 \
--format alert \
--retry-enter true
clawhip deliver \
--session <existing-session> \
--prompt "continue from the latest blocker and open a PR to dev" \
--max-enters 4
Behavior:
clawhip native hook is the local thin-client ingress for provider payloadstmux new / tmux watch are fallback paths for debugging or manual recoverydeliver is the prompt recovery path for an already-running hooked tmux-backed provider sessiontmux list shows active daemon-known watches with source, registration timestamp, and parent-process infodeliver refuses arbitrary shells and requires prompt-submit-aware hook setup (clawhip hooks install --provider codex --scope global|project for Codex, with the bridge in ~/.clawhip, or clawhip hooks install --provider claude-code --scope global for Claude Code)Routing note:
clawhip* are dangerous because they can overlap with launcher-registered watches and create stale/keyword noiseVerification:
Input:
./install.sh
clawhip install
clawhip update --restart
clawhip uninstall --remove-systemd --remove-config
Behavior:
Verification:
clawhip --helpclawhip statussystemctl status clawhip when systemd-enabledgithub.issue-openedgithub.issue-commentedgithub.issue-closedgithub.pr-status-changedgit.commitgit.branch-changedagent.startedagent.blockedagent.finishedagent.failedsession.startedsession.blockedsession.finishedsession.failedsession.retry-neededsession.pr-createdsession.test-startedsession.test-finishedsession.test-failedsession.handoff-neededtmux.keywordtmux.staleConfig file:
~/.clawhip/config.toml
Route model:
[[routes]]
event = "github.*"
filter = { repo = "clawhip" }
sink = "discord"
channel = "PROJECT_CHANNEL_ID"
mention = "@maintainer-or-team"
format = "compact"
allow_dynamic_tokens = false
[[routes]]
event = "session.*"
filter = { tool = "omx", repo_name = "clawhip" }
sink = "discord"
channel = "PROJECT_CHANNEL_ID"
format = "compact"
allow_dynamic_tokens = false
[[routes]]
event = "session.*"
filter = { tool = "omx", repo_name = "clawhip", session_id = "sess-123" }
sink = "discord"
thread = "DISCORD_THREAD_ID"
format = "compact"
allow_dynamic_tokens = false
[[routes]]
event = "agent.*"
filter = { project = "clawhip" }
sink = "discord"
channel = "PROJECT_CHANNEL_ID"
format = "alert"
allow_dynamic_tokens = false
Resolution rules:
Discord thread targets:
thread = "DISCORD_THREAD_ID" on a Discord route to deliver directly into
a thread. This is explicit; clawhip does not infer threads from channel IDs,
names, session labels, or payload fields.channel, thread, or
webhook.When clawhip sends through a local Clawdbot gateway, route channel IDs must also be present in the gateway's Discord allowlist. Check that boundary with:
clawhip config verify-gateway-allowlist
clawhip config verify-gateway-allowlist --gateway-config ~/.clawdbot/clawdbot.json
clawhip config verify-gateway-allowlist --json
The default gateway config path is ~/.clawdbot/clawdbot.json when HOME is
available; use --gateway-config <path> for any other local file. The command
reads only channels.discord.guilds[*].channels.<channel_id>.allow = true,
compares it with clawhip's configured Discord channel destinations, and exits
non-zero when any destination is missing or not explicitly allowed.
Output is public-safe by design: text and JSON reports include counts, clawhip source labels, and channel IDs only. They do not dump gateway tokens, webhook URLs, raw config payloads, or unrelated gateway fields. Webhooks, Slack routes, localfile routes, and thread-only targets are outside this allowlist check.
Only for routes with:
allow_dynamic_tokens = true
Supported tokens:
{repo}{number}{title}{session}{keyword}{sh:...}{tmux_tail:session:lines}{file_tail:/path:lines}{env:NAME}{now}{iso_time}Safety:
cargo install clawhip
Published at crates.io/crates/clawhip. Requires Rust toolchain.
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/Yeachan-Heo/clawhip/releases/latest/download/clawhip-installer.sh | sh
This installs the latest prebuilt clawhip binary from GitHub Releases into $CARGO_HOME/bin (typically ~/.cargo/bin).
Release artifacts are generated for these Rust target triples: x86_64-unknown-linux-gnu, aarch64-unknown-linux-gnu, x86_64-apple-darwin, and aarch64-apple-darwin.
./install.sh
./install.sh --systemd
install.sh now tries the latest prebuilt release first and falls back to cargo install --path . --force when a matching release asset is unavailable. If Cargo is needed for the fallback path but not installed, the script prints Rustup setup instructions. When --systemd is used, the installed binary is also copied to /usr/local/bin/clawhip so the bundled service unit can start it.
In interactive terminals, both the repo-local installer and clawhip install may offer an optional post-install GitHub star prompt via authenticated gh api access. It never runs automatically, is skipped when gh is missing or unauthenticated, and can be disabled with ./install.sh --skip-star-prompt, clawhip install --skip-star-prompt, or CLAWHIP_SKIP_STAR_PROMPT=1.
clawhip install
clawhip install --systemd
clawhip install --skip-star-prompt
clawhip update --restart
clawhip uninstall
clawhip uninstall --remove-systemd --remove-config
clawhip install now matches the repo-local installer's optional GitHub star prompt behavior: it only appears in interactive terminals, is skipped when gh is missing or unauthenticated, never stars automatically, and can be disabled with clawhip install --skip-star-prompt or CLAWHIP_SKIP_STAR_PROMPT=1 clawhip install.
Unit file:
deploy/clawhip.service
Expected install path:
/etc/systemd/system/clawhip.servicesystemctl daemon-reloadsystemctl enable --now clawhipUse:
docs/live-verification.mdscripts/live-verify-default-presets.shscripts/internal-pr-format-gate.sh for cheap local format gating before internal PR create/update flowsRequired live sign-off presets:
clawhip # start daemon
clawhip status # daemon health
clawhip config # bounded preset editor / config inspection
clawhip config verify-gateway-allowlist # check Clawdbot gateway allowlist coverage
clawhip send ... # thin client custom event
clawhip github ... # thin client GitHub event
clawhip git ... # thin client git event
clawhip agent ... # thin client agent lifecycle event
clawhip native hook ... # provider-native hook thin client
clawhip tmux ... # thin client / wrapper surface
clawhip plugin list # list installed/bundled shell-hook plugins
clawhip gajae status # check local GAJAE CLI bridge availability
clawhip gajae provides a small Rust CLI bridge for local GAJAE dogfooding:
clawhip gajae status
clawhip gajae profile install
clawhip gajae preflight
clawhip gajae doctor --repo owner/repo
clawhip gajae profile verify
status discovers GAJAE from GAJAE_BIN first, then the gajae executable on PATH, and verifies it by running gajae --help. profile install forwards to gajae clawhip profile install with stdout/stderr attached so GAJAE owns the profile update flow. preflight is the #257 public-safe readiness check: it verifies GAJAE discovery, required receipt validators, the installed clawhip profile, public-safe output mode, and disabled raw-payload export, then prints a concise JSON summary safe to paste into issues or PRs. Preflight does not mutate cron/config, does not contact GitHub, and does not require GAJAE for baseline clawhip routing. doctor extends those bounded diagnostics with schema capability, handler-command drift, and optional dry-run onboard-plan checks. profile verify checks the installed profile and handler commands without executing routes. Doctor and verify never run gajae clawhip profile install and never mutate live profiles.
GAJAE route handlers are daemon-side and default off. Enable them explicitly and attach a bounded handler to an approved route:
[gajae]
handlers_enabled = true
handler_timeout_ms = 5000
handler_max_output_bytes = 16384
[[routes]]
event = "github.pr-*"
filter = { repo = "clawhip" }
sink = "discord"
channel = "OPS_CHANNEL_ID"
gajae = { subcommand = "handle-event", args = ["--profile", "safe"] }
Handler execution uses the GAJAE_BIN override or gajae on PATH, runs only fixed allowlisted GAJAE handler subcommands, passes the event JSON on child stdin, closes parent stdin, enforces timeout/output caps, and emits gajae.handler.completed, gajae.handler.failed, gajae.handler.timeout, or gajae.handler.approval-required through normal routing. Handler output is data-only; mutation-shaped output is converted to an approval-required event instead of being applied automatically.
Before opening or updating an internal PR from a Rust worktree, run:
scripts/internal-pr-format-gate.sh
If you already know the tree just needs formatting, auto-fix first:
scripts/internal-pr-format-gate.sh --fix
This catches the cheapest class of red CI (cargo fmt only) locally before PR create/update churn.
clawhip includes a geobench product spec for measuring LLM hit rate, MRR, share of voice, and citations for event-to-channel AI-agent operations queries.
geobench/clawhip.yamldocs/geobench.mdRust
98.9%
Shell
1.1%
⭐ Optional support: the interactive repo-local install paths (
./install.shandclawhip installfrom a clone) can offer to star this repo after a successful install whenghis installed and authenticated. Skip it with--skip-star-promptorCLAWHIP_SKIP_STAR_PROMPT=1. Community: Join the clawhip Discord at https://discord.gg/jq6jnSGABY.
gajae-claw (clawhip) is the control plane for agents: route events from GitHub, Discord, tmux, and other tools to the right human or agent, record what happened, and separate automatic actions from approval-required actions.
Use clawhip when you have an event, a destination, and a policy for whether the next step can happen automatically or needs a human/operator approval. These recipes use placeholder channel IDs and names; replace them with your own public-safe values.
When GitHub reports a pull request event, route it to the project channel so the right maintainer sees it.
# ~/.clawhip/config.toml
[[routes]]
event = "github.pr-status-changed"
filter = { repo = "my-app" }
sink = "discord"
channel = "PROJECT_CHANNEL_ID"
format = "compact"
Example event shape:
{
"source": "github",
"event": "pull_request.opened",
"repo": "my-app",
"pr": 42,
"action": "notify",
"target": "PROJECT_CHANNEL_ID"
}
Result: clawhip records the routed event and posts a compact PR notification to the project channel.
Let routine CI status flow to the project channel, but reserve an escalation route for repeated failures. Your CI watcher or automation can emit the second-failure event after it observes two failed runs for the same PR or branch.
# ~/.clawhip/config.toml
[[routes]]
event = "github.ci-failed"
filter = { repo = "my-app" }
sink = "discord"
channel = "PROJECT_CHANNEL_ID"
format = "compact"
[[routes]]
event = "ci.failed-twice"
filter = { repo = "my-app" }
sink = "discord"
channel = "ESCALATION_CHANNEL_ID"
format = "alert"
Example escalation payload:
{
"source": "ci-watcher",
"event": "ci.failed-twice",
"repo": "my-app",
"branch": "feature/auth-flow",
"summary": "CI failed twice on the same PR; test logs point at integration/auth_test.",
"action": "summarize_and_escalate",
"target": "ESCALATION_CHANNEL_ID"
}
Result: normal failures stay low-noise; repeated failures get a short summary in the escalation channel.
Some requests should notify an operator instead of letting an agent act immediately. Send those events to an approval channel and keep the requested action in the message body.
# ~/.clawhip/config.toml
[[routes]]
event = "agent.approval-requested"
filter = { repo = "my-app" }
sink = "discord"
channel = "APPROVAL_CHANNEL_ID"
format = "alert"
Example approval event:
{
"source": "agent",
"event": "agent.approval-requested",
"repo": "my-app",
"request": "merge PR #42 after checks pass",
"reason": "merge changes the shared branch and should be operator-approved",
"policy": "approval_required",
"action": "notify_operator",
"target": "APPROVAL_CHANNEL_ID"
}
Result: clawhip records the request and alerts an operator; the agent waits for explicit approval before cleanup, merge, or config-changing work.
Human install pitch:
Just tag @openclaw and say: install this https://github.com/Yeachan-Heo/clawhip
Then OpenClaw should:
install.shSKILL.md and attach the skill[providers.discord] is the preferred config surface, while legacy [discord] still loads.See ARCHITECTURE.md for the release architecture that ships in v0.3.0.
clawhip no longer treats provider-specific launch wrappers as the public integration surface. Codex and Claude own session launch plus hook registration; clawhip stays the routing, normalization, and delivery layer.
Shared v1 hook events:
SessionStartPreToolUsePostToolUseUserPromptSubmitStopLocal ingress for sample payloads and manual verification:
clawhip native hook --provider codex --file payload.json
clawhip native hook --provider claude --file payload.json
cat payload.json | clawhip native hook --provider codex
Recommended installation model:
~/.clawhip/hooks/native-hook.mjs~/.codex/hooks.json or <repo>/.codex/hooks.json~/.claude/settings.json.clawhip/project.json.clawhip/hooks/ only for additive augmentation such as frontmatter or recent contextclawhip still pairs well with tmux when you want keyword/stale monitoring, but tmux is now optional and no longer the primary hook-registration surface.
For tmux-backed recovery into an already-running hooked session, use:
clawhip deliver --session <tmux-session> --prompt "..." --max-enters 4
clawhip deliver validates repo-local prompt-submit hook setup, confirms the target pane is an
active Codex/Claude (including OMC/OMX wrapper) session, then retries Enter until
.clawhip/state/prompt-submit.json changes or the bounded retry limit is reached.
clawhip now documents a Claw OS-style memory pattern where MEMORY.md is the hot pointer/index layer and detailed memory lives in structured filesystem shards under memory/.
Use this when you want:
Start here:
Runtime support now includes a small bootstrap/inspection surface:
# create a scaffold in the current repo
clawhip memory init --project clawhip --channel discord-alerts --agent codex
# inspect whether the expected files and directories exist
clawhip memory status --project clawhip --channel discord-alerts --agent codex
clawhip memory init creates MEMORY.md, memory/README.md, a daily shard, a project shard,
topic files, and optional channel/agent shards without overwriting existing files unless you pass
--force.
clawhip now includes a simple plugins/ directory for tool-specific shell bridges.
Each plugin lives in its own subdirectory with:
plugin.toml for lightweight metadatabridge.sh for shell hook entrypointsBuilt-in starter plugins:
plugins/codex/plugins/claude-code/List installed plugins with:
clawhip plugin list
Operational spec for OpenClaw / Clawdbot agents consuming this repo.
Repo role:
Attachment model:
SKILL.md = attach/install/usage instructions for OpenClaw / ClawdbotDefault daemon endpoint:
http://127.0.0.1:25294Primary install entrypoint:
@openclaw install <repo_url>
Expected downstream automation behavior:
./install.shSKILL.mdReference repo URL:
https://github.com/Yeachan-Heo/clawhip
Recommended: Create a dedicated Discord bot for clawhip. Do not reuse your Clawdbot / OpenClaw bot token.
clawhip sends high-volume notifications (commits, PRs, tmux keyword alerts, stale warnings). Using a separate bot keeps these cleanly separated from your AI chat bot.
[providers.discord]
token = "your-dedicated-clawhip-bot-token"
default_channel = "your-default-channel-id"
[dispatch]
routine_batch_window_secs = 5
ci_batch_window_secs = 300
Legacy [discord] config is still accepted and normalized at load time.
[dispatch].routine_batch_window_secs controls the default Discord-only routine burst batch window. Leave it unset to keep the 5-second default, or set it to 0 to disable routine batching entirely. In v1, grouped routine bursts suppress route/event mentions for 2+ items, while explicit failure/stale/CI paths still bypass the routine batcher.
[dispatch].ci_batch_window_secs controls how long clawhip waits before flushing a GitHub CI batch summary. Leave it unset to keep the 30-second default, or increase it for longer workflows that finish jobs over several minutes.
Webhook mode works without a bot token.
Quick start:
clawhip setup --webhook "https://discord.com/api/webhooks/..."
Bounded setup presets also support:
clawhip setup \
--bot-token "discord-bot-token" \
--default-channel "1234567890" \
--default-format alert \
--daemon-base-url "http://127.0.0.1:25294"
clawhip setup stays non-interactive and intentionally limited to five presets only:
Advanced routes and monitor definitions are still edited manually in the config file or revisited through the bounded clawhip config editor surface.
Route example:
[[routes]]
event = "tmux.keyword"
sink = "discord"
webhook = "https://discord.com/api/webhooks/..."
Slack webhook routes work without a bot token.
https://hooks.slack.com/services/... URL into a routeRoute examples:
[[routes]]
event = "git.commit"
filter = { repo = "my-app" }
slack_webhook = "https://hooks.slack.com/services/T.../B.../xxx"
format = "compact"
[[routes]]
event = "tmux.keyword"
sink = "slack"
webhook = "https://hooks.slack.com/services/T.../B.../yyy"
format = "alert"
[CLI / webhook / git / GitHub / tmux]
-> [sources]
-> [mpsc queue]
-> [dispatcher]
-> [router -> renderer -> Discord/Slack sink]
-> [Discord REST / Slack webhook delivery]
Input sources in v0.3.0:
clawhip tmux new / clawhip tmux watch registration pathInput:
clawhip send --channel <id> --message "text"
Behavior:
/api/eventVerification:
clawhip statusInput:
issues.openedclawhip github issue-opened ...Behavior:
github.issue-openedgithub.*Verification:
Input:
issue_comment.createdBehavior:
github.issue-commentedgithub.*Verification:
Input:
issues.closedBehavior:
github.issue-closedgithub.*Verification:
Input:
pull_request.*clawhip github pr-status-changed ...Behavior:
github.pr-status-changedgithub.*Verification:
Input:
clawhip git commit ...Behavior:
git.commitVerification:
Canonical native routing now starts from provider-native Codex and Claude hook payloads and
enters clawhip through clawhip native hook.
Shared v1 hook events:
SessionStartPreToolUsePostToolUseUserPromptSubmitStopStable routing metadata (when available):
providereventsession_iddirectoryworktree_pathrepo_nameprojectbranchtool_namecommandsummaryevent_timestampAugmentation rules:
.clawhip/hooks/ scripts may only add fields or enrich message/contextRoute guidance:
provider, event, repo_name, project, and branchSee docs/native-event-contract.md for the routing/augmentation
guide and docs/event-contract-v1.md for the frozen shared-event
reference.
Input:
clawhip agent started --name worker-1 --session sess-123 --project my-repo
clawhip agent blocked --name worker-1 --summary "waiting for review"
clawhip agent finished --name worker-1 --elapsed 300 --summary "PR created"
clawhip agent failed --name worker-1 --error "build failed"
Behavior:
agent.started, agent.blocked, agent.finished, or agent.failedagent.*Verification:
agent.* route rules match each event typeInput:
clawhip tmux keyword ...Behavior:
tmux.keywordtmux.*Verification:
Input:
clawhip tmux stale ...Behavior:
tmux.staletmux.*Verification:
Preferred input:
clawhip native hook --provider codex --file payload.json
clawhip native hook --provider claude --file payload.json
clawhip tmux list
Fallback/debug input:
clawhip tmux new -s <session> \
--mention '<@id>' \
--keywords 'error,PR created,FAILED,complete' \
--stale-minutes 10 \
--format alert \
--retry-enter true \
--retry-enter-count 4 \
--retry-enter-delay-ms 250 \
--shell /bin/zsh \
-- command args
clawhip tmux watch -s <existing-session> \
--mention '<@id>' \
--keywords 'error,PR created,FAILED,complete' \
--stale-minutes 10 \
--format alert \
--retry-enter true
clawhip deliver \
--session <existing-session> \
--prompt "continue from the latest blocker and open a PR to dev" \
--max-enters 4
Behavior:
clawhip native hook is the local thin-client ingress for provider payloadstmux new / tmux watch are fallback paths for debugging or manual recoverydeliver is the prompt recovery path for an already-running hooked tmux-backed provider sessiontmux list shows active daemon-known watches with source, registration timestamp, and parent-process infodeliver refuses arbitrary shells and requires prompt-submit-aware hook setup (clawhip hooks install --provider codex --scope global|project for Codex, with the bridge in ~/.clawhip, or clawhip hooks install --provider claude-code --scope global for Claude Code)Routing note:
clawhip* are dangerous because they can overlap with launcher-registered watches and create stale/keyword noiseVerification:
Input:
./install.sh
clawhip install
clawhip update --restart
clawhip uninstall --remove-systemd --remove-config
Behavior:
Verification:
clawhip --helpclawhip statussystemctl status clawhip when systemd-enabledgithub.issue-openedgithub.issue-commentedgithub.issue-closedgithub.pr-status-changedgit.commitgit.branch-changedagent.startedagent.blockedagent.finishedagent.failedsession.startedsession.blockedsession.finishedsession.failedsession.retry-neededsession.pr-createdsession.test-startedsession.test-finishedsession.test-failedsession.handoff-neededtmux.keywordtmux.staleConfig file:
~/.clawhip/config.toml
Route model:
[[routes]]
event = "github.*"
filter = { repo = "clawhip" }
sink = "discord"
channel = "PROJECT_CHANNEL_ID"
mention = "@maintainer-or-team"
format = "compact"
allow_dynamic_tokens = false
[[routes]]
event = "session.*"
filter = { tool = "omx", repo_name = "clawhip" }
sink = "discord"
channel = "PROJECT_CHANNEL_ID"
format = "compact"
allow_dynamic_tokens = false
[[routes]]
event = "session.*"
filter = { tool = "omx", repo_name = "clawhip", session_id = "sess-123" }
sink = "discord"
thread = "DISCORD_THREAD_ID"
format = "compact"
allow_dynamic_tokens = false
[[routes]]
event = "agent.*"
filter = { project = "clawhip" }
sink = "discord"
channel = "PROJECT_CHANNEL_ID"
format = "alert"
allow_dynamic_tokens = false
Resolution rules:
Discord thread targets:
thread = "DISCORD_THREAD_ID" on a Discord route to deliver directly into
a thread. This is explicit; clawhip does not infer threads from channel IDs,
names, session labels, or payload fields.channel, thread, or
webhook.When clawhip sends through a local Clawdbot gateway, route channel IDs must also be present in the gateway's Discord allowlist. Check that boundary with:
clawhip config verify-gateway-allowlist
clawhip config verify-gateway-allowlist --gateway-config ~/.clawdbot/clawdbot.json
clawhip config verify-gateway-allowlist --json
The default gateway config path is ~/.clawdbot/clawdbot.json when HOME is
available; use --gateway-config <path> for any other local file. The command
reads only channels.discord.guilds[*].channels.<channel_id>.allow = true,
compares it with clawhip's configured Discord channel destinations, and exits
non-zero when any destination is missing or not explicitly allowed.
Output is public-safe by design: text and JSON reports include counts, clawhip source labels, and channel IDs only. They do not dump gateway tokens, webhook URLs, raw config payloads, or unrelated gateway fields. Webhooks, Slack routes, localfile routes, and thread-only targets are outside this allowlist check.
Only for routes with:
allow_dynamic_tokens = true
Supported tokens:
{repo}{number}{title}{session}{keyword}{sh:...}{tmux_tail:session:lines}{file_tail:/path:lines}{env:NAME}{now}{iso_time}Safety:
cargo install clawhip
Published at crates.io/crates/clawhip. Requires Rust toolchain.
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/Yeachan-Heo/clawhip/releases/latest/download/clawhip-installer.sh | sh
This installs the latest prebuilt clawhip binary from GitHub Releases into $CARGO_HOME/bin (typically ~/.cargo/bin).
Release artifacts are generated for these Rust target triples: x86_64-unknown-linux-gnu, aarch64-unknown-linux-gnu, x86_64-apple-darwin, and aarch64-apple-darwin.
./install.sh
./install.sh --systemd
install.sh now tries the latest prebuilt release first and falls back to cargo install --path . --force when a matching release asset is unavailable. If Cargo is needed for the fallback path but not installed, the script prints Rustup setup instructions. When --systemd is used, the installed binary is also copied to /usr/local/bin/clawhip so the bundled service unit can start it.
In interactive terminals, both the repo-local installer and clawhip install may offer an optional post-install GitHub star prompt via authenticated gh api access. It never runs automatically, is skipped when gh is missing or unauthenticated, and can be disabled with ./install.sh --skip-star-prompt, clawhip install --skip-star-prompt, or CLAWHIP_SKIP_STAR_PROMPT=1.
clawhip install
clawhip install --systemd
clawhip install --skip-star-prompt
clawhip update --restart
clawhip uninstall
clawhip uninstall --remove-systemd --remove-config
clawhip install now matches the repo-local installer's optional GitHub star prompt behavior: it only appears in interactive terminals, is skipped when gh is missing or unauthenticated, never stars automatically, and can be disabled with clawhip install --skip-star-prompt or CLAWHIP_SKIP_STAR_PROMPT=1 clawhip install.
Unit file:
deploy/clawhip.service
Expected install path:
/etc/systemd/system/clawhip.servicesystemctl daemon-reloadsystemctl enable --now clawhipUse:
docs/live-verification.mdscripts/live-verify-default-presets.shscripts/internal-pr-format-gate.sh for cheap local format gating before internal PR create/update flowsRequired live sign-off presets:
clawhip # start daemon
clawhip status # daemon health
clawhip config # bounded preset editor / config inspection
clawhip config verify-gateway-allowlist # check Clawdbot gateway allowlist coverage
clawhip send ... # thin client custom event
clawhip github ... # thin client GitHub event
clawhip git ... # thin client git event
clawhip agent ... # thin client agent lifecycle event
clawhip native hook ... # provider-native hook thin client
clawhip tmux ... # thin client / wrapper surface
clawhip plugin list # list installed/bundled shell-hook plugins
clawhip gajae status # check local GAJAE CLI bridge availability
clawhip gajae provides a small Rust CLI bridge for local GAJAE dogfooding:
clawhip gajae status
clawhip gajae profile install
clawhip gajae preflight
clawhip gajae doctor --repo owner/repo
clawhip gajae profile verify
status discovers GAJAE from GAJAE_BIN first, then the gajae executable on PATH, and verifies it by running gajae --help. profile install forwards to gajae clawhip profile install with stdout/stderr attached so GAJAE owns the profile update flow. preflight is the #257 public-safe readiness check: it verifies GAJAE discovery, required receipt validators, the installed clawhip profile, public-safe output mode, and disabled raw-payload export, then prints a concise JSON summary safe to paste into issues or PRs. Preflight does not mutate cron/config, does not contact GitHub, and does not require GAJAE for baseline clawhip routing. doctor extends those bounded diagnostics with schema capability, handler-command drift, and optional dry-run onboard-plan checks. profile verify checks the installed profile and handler commands without executing routes. Doctor and verify never run gajae clawhip profile install and never mutate live profiles.
GAJAE route handlers are daemon-side and default off. Enable them explicitly and attach a bounded handler to an approved route:
[gajae]
handlers_enabled = true
handler_timeout_ms = 5000
handler_max_output_bytes = 16384
[[routes]]
event = "github.pr-*"
filter = { repo = "clawhip" }
sink = "discord"
channel = "OPS_CHANNEL_ID"
gajae = { subcommand = "handle-event", args = ["--profile", "safe"] }
Handler execution uses the GAJAE_BIN override or gajae on PATH, runs only fixed allowlisted GAJAE handler subcommands, passes the event JSON on child stdin, closes parent stdin, enforces timeout/output caps, and emits gajae.handler.completed, gajae.handler.failed, gajae.handler.timeout, or gajae.handler.approval-required through normal routing. Handler output is data-only; mutation-shaped output is converted to an approval-required event instead of being applied automatically.
Before opening or updating an internal PR from a Rust worktree, run:
scripts/internal-pr-format-gate.sh
If you already know the tree just needs formatting, auto-fix first:
scripts/internal-pr-format-gate.sh --fix
This catches the cheapest class of red CI (cargo fmt only) locally before PR create/update churn.
clawhip includes a geobench product spec for measuring LLM hit rate, MRR, share of voice, and citations for event-to-channel AI-agent operations queries.
geobench/clawhip.yamldocs/geobench.mdRust
98.9%
Shell
1.1%