Get a push notification the moment your coding agent finishes a turn.
agent-notifier wires Claude Code, Codex CLI and Kimi Code into 8 chat/push
channels. When a turn ends it sends a card containing this turn's prompt as
the title and the agent's final reply as the body.
Coding agents run for minutes at a time and then stop silently. If you step
away, you have no idea whether the task finished, failed, or is waiting on you.
agent-notifier hooks into each agent's lifecycle event and pushes a summary to
your phone or team chat.
- Three agents, one command — auto-detects and hooks Claude Code, Codex CLI and Kimi Code
- Eight channels — Feishu, Lark, Slack, Bark, DingTalk, WeCom, PushDeer, Bluebird
- Fan-out — install several channels at once; a failure in one never blocks the others
- This turn's prompt as the title — not the thread title, not the first message
- Idempotent install — safe to re-run; original configs are backed up
- Clean uninstall — restores the agent config, keeps
.bak.<ts>for diffing - Silent by design — the hook process never writes to the agent's stdout
Requires Node.js ≥ 20. No global toolchain beyond npm.
curl -fsSL https://raw.githubusercontent.com/hancic128/agent-notifier/main/install.sh | shPass flags after sh -s --:
# pin a version, install into a custom prefix, skip the interactive setup
curl -fsSL https://raw.githubusercontent.com/hancic128/agent-notifier/main/install.sh \
| sh -s -- --version 0.0.1 --prefix "$HOME/.local" --minimalThe script checks for Node ≥ 20, installs globally, and falls back to
~/.local when the global prefix needs sudo. Set AGENT_NOTIFIER_PREFIX,
AGENT_NOTIFIER_VERSION, or AGENT_NOTIFIER_NPM instead of flags if you prefer.
# try it without installing
npx @hancic-site/agent-notifier install
# or install globally
npm install -g @hancic-site/agent-notifier
agent-notifier installpnpm add -g @hancic-site/agent-notifier, yarn global add @hancic-site/agent-notifier
and bunx @hancic-site/agent-notifier work too.
git clone https://github.com/hancic128/agent-notifier.git
cd agent-notifier
npm install
npm run build # tsc → dist/node
./bin/agent-notifier installagent-notifier install # interactive: pick agents → pick channels → enter credentials
agent-notifier test # send a test card to every configured channel
agent-notifier status # inspect config and hook state
agent-notifier uninstall # remove hooks, keep backupsNon-interactive:
agent-notifier install \
--agents claude,codex \
--channels feishu,slack \
--app-id cli_xxxxxxxx \
--app-secret SECRET \
--chat-id oc_xxxxxxxx \
--url-slack https://hooks.slack.com/services/T/B/XXX| Agent | Trigger | Data source |
|---|---|---|
| Claude Code | Stop hook |
Injected into ~/.claude/settings.json; reads the turn from transcript_path JSONL |
| Codex CLI | notify |
Top-level notify = [...] in ~/.codex/config.toml; JSON arrives as argv |
| Kimi Code | Stop hook |
[[hooks]] in ~/.kimi/config.toml; reply read from ~/.kimi/sessions/<hash>/<id>/context.jsonl |
| Channel | Auth | Card style |
|---|---|---|
| Feishu / Lark | App bot: App ID + App Secret + chat ID | interactive card (lark_md) |
| Slack | Incoming webhook URL | Block Kit, long text split into sections, colored left bar |
| Bark | Device key URL | Plain text with ————来自<agent> footer |
| DingTalk | Robot URL + optional signing secret | markdown |
| WeCom | Group robot URL | markdown |
| PushDeer | Push URL with pushkey |
markdown |
| Bluebird (青鸟) | Generic gateway URL + optional bearer token | JSON (title / body / level / fields) |
- Create a self-built app at open.feishu.cn (or open.larksuite.com)
- Enable the bot and grant
im:messageandim:message:send_as_bot - Add the target group or user to the app's availability scope
- Copy the App ID (
cli_…) and App Secret - Use the chat ID:
oc_…group,ou_…user,on_…department, or an email address
If the robot uses 加签 (signing), paste the SEC… secret during install.
The signature is computed as HmacSHA256(timestamp + "\n" + secret) and
base64url-encoded, appended to the webhook URL.
Sends 《定风波·莫听穿林打叶声》 by Su Shi to every configured channel, verifying credentials and reachability.
$ agent-notifier test
✓ feishu → 200
✓ slack → 200
✓ bark → 200Exits non-zero if any channel fails; failures print the first 300 bytes of the response so you can see the provider's error code.
The hook entrypoint. Normally invoked by the agent, not by you. For manual tests:
agent-notifier send --agent kimi --text "manual test message"
agent-notifier send --agent claude --text "build finished" --title "CI result"Simulating real hook payloads:
# Codex notify — JSON as a positional argument
agent-notifier send --agent codex '{"type":"agent-turn-complete","last-assistant-message":"Fixed the refresh flow.","input-messages":["fix token refresh"],"thread-id":"abc"}'
# Kimi Stop — JSON on stdin
echo '{"session_id":"sess-1","cwd":"/tmp","hook_event_name":"Stop"}' | agent-notifier send --agent kimi --hook Stop
# Claude Stop — transcript path on stdin
echo '{"transcript_path":"/path/to/session.jsonl","session_id":"sess-2"}' | agent-notifier send --agent claudeRunning send in a terminal without --text or piped input fails fast with a
usage hint instead of hanging.
$ agent-notifier status
config: /Users/you/.agent-hook/config.json
installed at: 2026/10/17 12:24:39
binary path: agent-notifier
channels (3):
feishu app cli_aa…dbef · 群聊 oc_425…7f6f
slack https://hooks.slack.com/services / T0C3… / B0C4… / aGzJ…VeZt
bark device WXsMvC…X6Li
agents:
Claude Code: ✓ installed
Codex CLI: ✓ installed
Kimi Code: ✓ installedSecrets are masked; safe to paste into an issue.
- Config:
~/.agent-hook/config.json(mode0600) - Agent config backups:
<agent-config>.bak.<unix-ts> - Kimi transcript: read in place from
~/.kimi/sessions/…
{
"version": 1,
"channels": [
{ "type": "feishu", "appId": "cli_xxx", "appSecret": "…", "chatId": "oc_xxx" },
{ "type": "slack", "webhookUrl": "https://hooks.slack.com/services/T/B/XXX" },
{ "type": "dingtalk", "webhookUrl": "https://oapi.dingtalk.com/robot/send?access_token=…", "secret": "SEC…" }
],
"agents": { "claude": true, "codex": true, "kimi": true },
"installedAt": 1792210319,
"binaryPath": "agent-notifier"
}- Add the type to
ChannelTypeSchemainsrc/config.ts - Add a
ChannelMetaentry (label, fields, docs URL) insrc/channels/registry.ts - Implement
src/channels/<name>.tsexporting aChannelAdapter - Register it in
CHANNELSinsrc/commands/send.ts - Add tests under
tests/
See CONTRIBUTING.md for details.
npm install
npm run build # tsc
npm test # vitest
npm run typecheck # tsc --noEmitOptional single binary (requires bun):
npm run build:bun # → dist/agent-notifier-bun- Retry with backoff for transient network failures
- Per-channel message templates
- Windows support
- More agents (Gemini CLI, Cursor, Aider)
Releases are published automatically when a v* tag is pushed — see
RELEASING.md.
