Lifecycle Hooks
botmux can asynchronously invoke external commands when key lifecycle events occur. If a command fails, times out, or doesn't exist, it only writes to the log and never blocks botmux's main flow.
Configuration Location
In order of precedence (highest to lowest):
- The
BOTMUX_HOOKS_JSONenvironment variable (pass a JSON array directly) - The file path specified by
BOTMUX_HOOKS_FILE - The default
~/.botmux/data/hooks.json
Quick Check: Write to a Local Log
The repo ships an example script you can copy and use right away:
After any hook event fires, you'll see the JSON payload in the log. examples/hooks/ also includes examples for macOS Notification Center (osascript-notify.sh) and HTTP webhooks (http-webhook.sh).
Configuration Fields
Supported Events
Payload Fields
Every payload is written to the hook command via stdin, and the environment variable BOTMUX_HOOK_EVENT is also set. Each payload includes event and emittedAt; the event context may include sessionId, chatId, chatType, larkAppId, scope, anchor, title, cliId, workingDir, hasHistory, spawnedAt, and lastMessageAt.
Different events carry extra fields:
By default, content, message, description, finalOutput, and lastScreenContent are truncated to 600 characters, with xxxLength / xxxTruncated added; only events in redact.fullContentEvents pass through the full text.
Practical: Auto-Update Skills with session.start
botmux natively integrates agentbuddy as a skill source (botmux skills install <agentbuddy-command> to install, botmux skills update <name> to update). Combined with the session.start hook, you can automatically check for and update installed skills on every new session — equivalent to the SessionStart Hook in Relay / Claude Code's settings.json.
Update a Single Skill
Update All Installed Skills
botmux skills update accepts only a single skill name — no * or regex. To update everything, loop in a script:
Call agentbuddy CLI Directly to Update Global Skills
If you prefer running npx agentbuddy update directly (updating the user's global skills rather than botmux-managed skills), be aware of botmux's hook execution constraints: shell: false (no redirection or piping) and a scrubbed environment (only PATH/HOME/TMPDIR/SHELL/USER and a few other basics are preserved). Use a wrapper script:
Notes
- Timeout: The default
timeoutMsis 5000ms. agentbuddy update involves network requests and typically takes longer — set it explicitly (60s+ recommended). On timeout, botmux sendsSIGTERMfirst, thenSIGKILLto the entire process group. - Fire-and-forget: Hooks run asynchronously and never block session startup; updated skills take effect in the next session.
- Filter: Use
filterto limit updates to specificchatIdorsenderOpenId, avoiding unnecessary updates for every session. - Recommended approach: Prefer
botmux skills update(first approach) — it goes through botmux's telemetry scrubbing (clearAgentbuddyTelemetry) and updates the skill versions botmux injects, staying consistent with botmux's skill lifecycle.
Writing Your Own Hook
A hook command can be any executable: a bash / Python / Node / Go binary, an internal company CLI, or an HTTP forwarder. A command that does exit 0 is treated as a success; non-zero exits / timeouts / missing commands only write to the botmux log and never affect message send/receive, scheduled tasks, or the session lifecycle.
