Installation
Installation has two parts:
- Install the
claudiobinary. - Register hooks for the agent you want Claudio to listen to.
Install The Binary
Prebuilt Binary
Download the matching asset from GitHub Releases:
| Platform | Asset |
|---|---|
| Windows x64 | claudio-windows-amd64.exe |
| Linux x64 | claudio-linux-amd64 |
| macOS Apple Silicon | claudio-darwin-arm64 |
Rename it to claudio (claudio.exe on Windows) and place it in a directory
on PATH. On Linux and macOS, run chmod +x on the downloaded binary.
Release binaries are built with CGO_ENABLED=0 and include the native audio
backend.
Put the binary where it will stay before you install hooks. Hooks record the
absolute path of the claudio that installed them, so if you move the binary
later, run claudio install again from the new location.
Build From Source
Claudio requires Go 1.25.13 or newer. With Go’s default automatic toolchain
selection, commands run from this repository use the Go 1.26.6 toolchain
declared in go.mod. No C compiler is needed; native audio builds with
CGO_ENABLED=0.
go install claudio.click/cmd/claudio@latest
The binary lands in $(go env GOBIN), or $(go env GOPATH)/bin when GOBIN
is unset. Make sure that directory is on PATH:
go env GOBIN GOPATH
Audio Runtime
The default auto backend picks oto, Claudio’s built-in player, on Windows,
macOS, and Linux. Under WSL it picks system_command instead when one of
paplay, ffplay, aplay, or afplay is on PATH, and falls back to oto
otherwise.
On Linux, Oto first connects to a PulseAudio-compatible server (PulseAudio or
PipeWire’s Pulse layer), honoring PULSE_SERVER. If none is reachable it falls
back to ALSA, which needs libasound.so.2 at runtime. Neither path needs
development headers to build.
claudio status shows which backend auto resolved to:
audio backend: auto -> oto (available; playback not tested)
“Available” means the backend is compiled in, or for system_command that a
player is on PATH. It does not open the audio device.
Auto Install
Install global hooks for every detected supported agent:
claudio install
This is the default: --agent auto --scope global. An agent counts as
detected when its command (claude, codex, gemini, qwen, copilot,
commandcode, or opencode)
is on PATH, its settings directory exists, or its settings file already
contains Claudio hooks. Every detected agent gets its hook set. If nothing is
detected, the command fails and asks you to pick an agent with --agent.
To force every supported hook target:
claudio install --agent all --scope global
Use project scope only when hooks should live under the current repository:
claudio install --scope project
Claude Code Hooks
Install global Claude Code hooks:
claudio install --agent claude --scope global
Install hooks only for the current project:
claudio install --agent claude --scope project
Global scope writes ~/.claude/settings.json, or
$CLAUDE_CONFIG_DIR/settings.json when CLAUDE_CONFIG_DIR is set, matching
where Claude Code reads its settings. On Windows ~ is %USERPROFILE%.
Project scope writes ./.claude/settings.json.
Codex Hooks
Install global Codex hooks:
claudio install --agent codex --scope global
Install hooks only for the current project:
claudio install --agent codex --scope project
Global scope uses $CODEX_HOME/hooks.json when CODEX_HOME is set, otherwise
~/.codex/hooks.json.
Project scope writes ./.codex/hooks.json.
Each Codex hook entry carries both a POSIX command and a PowerShell command,
so the same hooks.json works on Windows and Unix.
After installing Codex hooks, run /hooks in Codex and trust the Claudio hook.
Codex does not run untrusted hooks.
Gemini Hooks
Install global Gemini hooks:
claudio install --agent gemini --scope global
Install hooks only for the current project:
claudio install --agent gemini --scope project
Global scope writes ~/.gemini/settings.json.
Project scope writes ./.gemini/settings.json.
Qwen Code Hooks
Install global Qwen Code hooks:
claudio install --agent qwen --scope global
Install hooks only for the current project:
claudio install --agent qwen --scope project
Global scope writes ~/.qwen/settings.json.
Project scope writes ./.qwen/settings.json.
GitHub Copilot CLI Hooks
Install global GitHub Copilot CLI hooks:
claudio install --agent copilot --scope global
Install hooks only for the current project:
claudio install --agent copilot --scope project
Global scope writes ~/.copilot/settings.json, or $COPILOT_HOME/settings.json
when COPILOT_HOME is set.
Project scope writes ./.github/copilot/settings.local.json. If that file
does not exist but ./.github/copilot/settings.json does, Claudio writes to the
existing file instead.
Command Code Hooks
Install global Command Code hooks:
claudio install --agent commandcode --scope global
Install hooks only for the current project:
claudio install --agent commandcode --scope project
Global scope writes ~/.commandcode/settings.json. Project scope writes
./.commandcode/settings.json. Command Code supports PreToolUse,
PostToolUse, Stop, and SessionStart; Claudio installs all four without a
matcher, because Command Code never fires a Stop or SessionStart group
that has one. Restart Command Code after installing. Non-interactive
commandcode -p runs do not fire SessionStart.
OpenCode Plugin
OpenCode has no settings hooks, so Claudio installs a small JavaScript plugin instead:
claudio install --agent opencode --scope global
claudio install --agent opencode --scope project
Global scope writes ~/.config/opencode/plugins/claudio.js, or
$OPENCODE_CONFIG_DIR/plugins/claudio.js when OPENCODE_CONFIG_DIR is set.
Project scope writes ./.opencode/plugins/claudio.js. The plugin maps
OpenCode events to Claude Code hook events and pipes them to Claudio:
session.created becomes SessionStart (or SubagentStart for a child
session), chat.message becomes UserPromptSubmit, tool.execute.before and
tool.execute.after become PreToolUse and PostToolUse (a non-zero bash
exit plays the error sound), permission.asked becomes PermissionRequest,
session.compacted becomes PostCompact, session.idle becomes Stop (or
SubagentStop), and session.error becomes StopFailure. It also forwards
experimental.session.compacting as PreCompact, command.execute.before as
UserPromptExpansion, session.deleted as SessionDelete, a rejected
permission.replied as PermissionDenied, and new or newly completed todos
in todo.updated as TodoCreated and TodoCompleted. When both a global
and a project plugin are installed, only one plays. Uninstall deletes the file
only if Claudio wrote it. Restart OpenCode after installing.
Inspect Before Writing
Dry run, which prints the target settings path and the hooks that would be installed:
claudio install --dry-run
claudio install --agent claude --scope global --dry-run
claudio install --agent codex --scope global --dry-run
claudio install --agent gemini --scope global --dry-run
claudio install --agent qwen --scope global --dry-run
claudio install --agent copilot --scope global --dry-run
claudio install --agent commandcode --scope global --dry-run
claudio install --agent opencode --scope global --dry-run
Print only the target agent and settings path:
claudio install --print
Quiet mode:
claudio install --quiet
The installer holds an advisory lock while it reads, merges, writes, and verifies the settings file. Hooks from other tools are left alone; earlier Claudio entries are replaced with the current form, and Claudio entries under events it no longer installs are removed, so reinstalling is safe.
Installed Hook Sets
Each agent’s event list comes from the event catalog in Captain Hook, which records the docs or source version it was checked against. The catalog also supplies where each agent keeps its hooks, and Captain Hook reads what each agent sends a hook: its field names, its tool names and how it reports a failed tool.
Claude Code defaults:
| Hook | Category |
|---|---|
SessionStart |
system |
Setup |
system |
UserPromptSubmit |
interactive |
UserPromptExpansion |
interactive |
PreToolUse |
loading |
PermissionRequest |
interactive |
PermissionDenied |
error |
PostToolUse |
success or error |
PostToolUseFailure |
error |
PostToolBatch |
success |
Notification |
interactive |
SubagentStart |
loading |
SubagentStop |
completion |
TaskCreated |
loading |
TaskCompleted |
completion |
Stop |
completion |
StopFailure |
error |
TeammateIdle |
interactive |
InstructionsLoaded |
system |
ConfigChange |
system |
CwdChanged |
system |
DirectoryAdded |
system |
PreCompact |
system |
PostCompact |
system |
PreModelSwitch |
system |
PostModelSwitch |
system |
Elicitation |
interactive |
ElicitationResult |
interactive |
SessionEnd |
interactive |
MessageDisplay and FileChanged are known to Claudio but not installed, for
Claude Code or for Qwen Code. Add them to your settings by hand only if you
want audio for streamed text or broad file change events.
WorktreeCreate and WorktreeRemove are never installed, and must not be
added by hand. Claude Code does not just report these two events: when a
WorktreeCreate hook is configured it stops running git worktree add and
expects the hook to create the worktree and print its path, and a
WorktreeRemove hook that exits 0 counts as having removed the worktree.
Claudio only plays a sound, so with it there every claude --worktree,
EnterWorktree and isolation: "worktree" subagent fails with
WorktreeCreate hook failed: hook succeeded but returned no worktree path.
Claudio 1.15.0 and earlier installed both. Run claudio install again to
remove them; hooks from other tools under those events are kept.
Codex defaults:
| Hook | Category |
|---|---|
PreToolUse |
loading |
PermissionRequest |
interactive |
PostToolUse |
success or error |
PreCompact |
system |
PostCompact |
system |
SessionStart |
system |
SessionEnd |
interactive |
UserPromptSubmit |
interactive |
SubagentStart |
loading |
SubagentStop |
completion |
Stop |
completion |
Interrupt |
interactive |
Gemini defaults:
| Hook | Category |
|---|---|
BeforeTool |
loading |
AfterTool |
success or error |
BeforeAgent |
interactive |
AfterAgent |
completion |
BeforeModel |
silent no-op |
AfterModel |
silent no-op |
BeforeToolSelection |
silent no-op |
SessionStart |
system |
SessionEnd |
interactive |
Notification |
interactive |
PreCompress |
system |
Qwen Code defaults:
| Hook | Category |
|---|---|
PreToolUse |
loading |
PostToolUse |
success |
PostToolUseFailure |
error |
PostToolBatch |
success |
Notification |
interactive |
UserPromptSubmit |
interactive |
UserPromptExpansion |
interactive |
SessionStart |
system |
Stop |
completion |
SubagentStart |
loading |
SubagentStop |
completion |
PreCompact |
system |
PostCompact |
system |
SessionEnd |
interactive |
SessionDelete |
interactive |
PermissionRequest |
interactive |
PermissionDenied |
error |
StopFailure |
error |
TodoCreated |
loading |
TodoCompleted |
completion |
InstructionsLoaded |
system |
GitHub Copilot CLI defaults. PascalCase keys get VS Code-compatible snake_case payloads; the three camelCase keys have no PascalCase form, so Claudio passes their event name on the command line:
| Hook | Category |
|---|---|
SessionStart |
system |
SessionEnd |
interactive |
UserPromptSubmit |
interactive |
userPromptTransformed |
silent |
PreToolUse |
loading |
PostToolUse |
success |
PostToolUseFailure |
error |
Stop |
completion |
subagentStart |
loading |
SubagentStop |
completion |
ErrorOccurred |
error |
PreCompact |
system |
PermissionRequest |
interactive |
notification |
interactive |
userPromptTransformed fires right after every UserPromptSubmit, so it is
installed silent rather than playing the prompt sound twice.
Optional Agent Commands
These commands install control artifacts so you can ask an agent to adjust Claudio without leaving the session.
claudio install-commands --agent claude
claudio install-commands --agent codex
claudio install-commands --agent antigravity
Artifacts:
| Agent | Installed artifact |
|---|---|
| Claude Code | ~/.claude/commands/claudio.md ($CLAUDE_CONFIG_DIR/commands/claudio.md when set) |
| Codex | $HOME/.agents/skills/claudio/SKILL.md |
| Antigravity | ~/.gemini/config/skills/claudio/SKILL.md and ~/.gemini/antigravity-cli/skills/claudio.md |
If an artifact already exists and you have edited it, install-commands
refuses to overwrite it and uninstall-commands refuses to delete it. Move
your copy aside first if you want the stock version back.
Remove them with:
claudio uninstall-commands --agent claude
claudio uninstall-commands --agent codex
claudio uninstall-commands --agent antigravity
Verify
Check effective config:
claudio status
Run one hook payload manually:
echo '{"session_id":"test","cwd":".","hook_event_name":"PostToolUse","tool_name":"Bash","tool_input":{"command":"git status"},"tool_response":{"stdout":"ok","stderr":"","interrupted":false}}' | claudio
If you do not want audio during a test run:
echo '{"session_id":"test","cwd":".","hook_event_name":"PostToolUse","tool_name":"Bash","tool_response":{"stdout":"ok","stderr":"","interrupted":false}}' | claudio --silent
Uninstall Hooks
claudio uninstall --agent all --scope global
claudio uninstall --agent claude --scope global
claudio uninstall --agent codex --scope global
claudio uninstall --agent gemini --scope global
claudio uninstall --agent qwen --scope global
claudio uninstall --agent copilot --scope global
Like install, uninstall defaults to --agent auto --scope global and
accepts --dry-run, --print, and --quiet.