Installation

Installation has two parts:

  1. Install the claudio binary.
  2. 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.

Next