Coding tools · 01
Claude Code
Use Claude Code’s Stop hook to convert the end of a main Agent response into a bluebell completed event. Test locally first, then enable remote delivery.
Current official lifecycle
Why use Stop?
Claude Code defines Stop as a hook that runs when the main Agent finishes responding. It has no matcher. Callback JSON arrives on stdin and includes the session, working directory, and transcript path.
Step 1
Create a local adapter script
Save the following script at a stable path of your own, such as ~/.local/bin/claude-bluebell.py. It does not read transcript contents; it uses the file size and session ID to derive a stable ID for the turn.
#!/usr/bin/env python3
import hashlib, json, os, subprocess, sys
CLI = "/Applications/bluebellMac.app/Contents/Helpers/bluebellctl"
try:
payload = json.load(sys.stdin)
except Exception:
sys.exit(0)
if payload.get("hook_event_name") != "Stop" or payload.get("stop_hook_active"):
sys.exit(0)
session_id = str(payload.get("session_id") or "")
transcript = str(payload.get("transcript_path") or "")
cwd = str(payload.get("cwd") or "")
if not session_id or not transcript:
sys.exit(0)
try:
transcript_size = os.path.getsize(transcript)
except OSError:
sys.exit(0)
signature = f"{session_id}\0{transcript}\0{transcript_size}"
turn_id = hashlib.sha256(signature.encode()).hexdigest()[:24]
workspace_name = os.path.basename(cwd) or "Claude Code"
subprocess.run([
CLI, "emit",
"--source", "Claude Code",
"--workspace-name", workspace_name,
"--session-id", session_id,
"--turn-id", turn_id,
"--dedupe-key", f"claude-code:{session_id}:{turn_id}",
"--local",
], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, timeout=3, check=False) The example keeps --local for local testing. It deliberately discards bluebell output and prevents notification failures from blocking Claude Code.
Step 2
Merge into Claude Code settings
User-level settings are usually at ~/.claude/settings.json. Merge the object below into the existing hooks.Stop; preserve other hooks and replace the example absolute paths.
{
"hooks": {
"Stop": [
{
"hooks": [
{
"type": "command",
"command": "python3 /absolute/path/claude-bluebell.py"
}
]
}
]
}
}Step 3
Confirm one visible completion produces one record
- Keep bluebell Mac running and complete a short Claude Code task.
- After about 2 seconds, check “Recent notifications” for one record with the expected source and project name.
- Test continued execution and a workflow with subtasks. Confirm that neither produces unwanted extra completions.
- Once the behavior is stable, remove
--localfrom the script, enable remote delivery on Mac, and test with real devices.
If your Claude Code version does not provide transcript_path, do not use this example for production deduplication. Use a stable turn ID based on that version’s official payload instead.
Sources
Claude Code official references
- Claude Code hooks guide Hook configuration, input, and Stop examples