Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@
},
"metadata": {
"description": "AI-operated audio notification system for Claude Code. 26 hooks, native matcher routing, TTS, webhook fan-out, status line, focus flow, rate-limit alerts.",
"version": "5.0.3"
"version": "5.1.1"
},
"plugins": [
{
"name": "audio-hooks",
"source": "./plugins/audio-hooks",
"version": "5.0.3",
"version": "5.1.1",
"description": "Audio notifications + AI-controlled config for every Claude Code event",
"author": {
"name": "Chan Meng",
Expand Down
54 changes: 54 additions & 0 deletions .github/workflows/smoke.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
name: smoke

on:
push:
branches: [master]
pull_request:

jobs:
import-smoke:
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
python-version: ["3.9", "3.12", "3.13"]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4

- uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}

- name: Install Linux audio player
if: runner.os == 'Linux'
run: sudo apt-get update && sudo apt-get install -y mpg123

- name: Import canonical hook_runner
shell: bash
run: |
python -c "import sys; sys.path.insert(0,'hooks'); import hook_runner; print('canonical', hook_runner.HOOK_RUNNER_VERSION)"

- name: Import plugin hook_runner copy
shell: bash
run: |
python -c "import sys; sys.path.insert(0,'plugins/audio-hooks/hooks'); import hook_runner; print('plugin', hook_runner.HOOK_RUNNER_VERSION)"

- name: audio-hooks version / status / diagnose
shell: bash
run: |
python bin/audio-hooks.py version
python bin/audio-hooks.py status
python bin/audio-hooks.py diagnose

- name: audio-hooks test all (every hook dispatches)
shell: bash
run: |
python bin/audio-hooks.py test all

plugin-in-sync:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Verify plugin copy matches canonical sources
run: bash scripts/build-plugin.sh --check
20 changes: 20 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,26 @@ All notable changes to Claude Code Audio Hooks will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [5.1.1] - 2026-04-18

Critical import-time crash fix plus regression-prevention CI. Everyone on v5.0.3 or v5.1.0 should upgrade.

### Fixed

- **`hook_runner.py` crashed on import with `NameError: name 'Tuple' is not defined`** ([#10](https://github.com/ChanMeng666/claude-code-audio-hooks/issues/10)). The file used `Tuple` in module-level type annotations (`SYNTHETIC_EVENT_MAP` and `_resolve_synthetic_event`) but did not import it from `typing`. Because the module has no `from __future__ import annotations`, CPython evaluated the annotations at import time and every `audio-hooks` subcommand (`diagnose`, `status`, `version`, `test`, …) crashed before dispatch. Users on v5.0.3 and v5.1.0 were fully blocked. One-line fix: add `Tuple` to the existing `typing` import.

### Added

- **CI import-smoke workflow** (`.github/workflows/smoke.yml`) to prevent regressions of this class of bug. Runs on every push to `master` and every PR across a 3×3 matrix (Ubuntu / Windows / macOS × Python 3.9 / 3.12 / 3.13) and exercises:
- `import hook_runner` from both the canonical `hooks/` and the synced `plugins/audio-hooks/hooks/` copy
- `audio-hooks version`, `status`, `diagnose`
- `audio-hooks test all` (all 26 hooks dispatch successfully)
- `scripts/build-plugin.sh --check` (the plugin copy is in sync with canonical sources)

### Note on v5.1.0

The `v5.1.0` tag was cut from the "context window monitor" feature commit but the in-tree version strings, CHANGELOG, and release notes were never bumped, so v5.1.0 shipped with the broken import under the 5.0.3 version string. v5.1.1 corrects this: every version reference (`HOOK_RUNNER_VERSION`, `PROJECT_VERSION`, `marketplace.json`, `plugin.json`, `config/default_preferences.json`, `CLAUDE.md` header) is now consistently `5.1.1`.

## [5.0.3] - 2026-04-11

Documentation correction. v5.0.2's README and release notes overclaimed that *"the human never types a command — Claude Code does everything"*. The user immediately caught the overclaim during real testing: the AI inside a Claude Code session **cannot** invoke `/reload-plugins` (or any other slash command) because slash commands are interactive REPL primitives with no CLI equivalent and no tool exposure. The user has to type `/reload-plugins` themselves once after install.
Expand Down
2 changes: 1 addition & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Claude Code Audio Hooks — AI Operator Guide

> **Version:** 5.0.3 | **Last Updated:** 2026-04-11
> **Version:** 5.1.1 | **Last Updated:** 2026-04-18

This document is the canonical machine-facing guide for the claude-code-audio-hooks project. It is written for **Claude Code (and other AI agents) as the operator** — not for humans. A human user says "install audio hooks for me" or "snooze audio for an hour" and you do everything via the project's structured CLI without any human-in-the-loop confirmation, menu navigation, or log file reading.

Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ You type one slash command at install time. Then natural language forever.<br/>
26 hook events, 2 audio themes, rate-limit alerts, webhooks, TTS, context monitor — all operated by Claude Code on your behalf.

[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![Version](https://img.shields.io/badge/version-5.0.3-blue.svg)](https://github.com/ChanMeng666/claude-code-audio-hooks)
[![Version](https://img.shields.io/badge/version-5.1.1-blue.svg)](https://github.com/ChanMeng666/claude-code-audio-hooks)
[![Platform](https://img.shields.io/badge/platform-Windows%20%7C%20Linux%20%7C%20macOS-green.svg)](https://github.com/ChanMeng666/claude-code-audio-hooks)
[![Claude Code](https://img.shields.io/badge/Claude_Code-v2.1.80%2B-brightgreen.svg)](https://claude.ai/download)
[![Plugin](https://img.shields.io/badge/install-just_talk_to_Claude-purple.svg)](#-install-in-60-seconds)
Expand Down Expand Up @@ -286,7 +286,7 @@ sequenceDiagram
You->>CC: Show me the last 20 errors and clear the log.
CC-->>You: 2 errors found (WEBHOOK_TIMEOUT). Log cleared.
You->>CC: What version of audio-hooks am I running?
CC-->>You: v5.0.3, plugin install.
CC-->>You: v5.1.1, plugin install.
You->>CC: Please uninstall audio-hooks completely.
CC-->>You: Plugin uninstalled. All hooks removed.
end
Expand Down Expand Up @@ -505,7 +505,7 @@ Real-time context window and API quota bars — color-coded warnings before Clau
</p>

```text
[Opus] Audio Hooks v5.0.3 | 6/26 Sounds | Webhook: ntfy | Theme: Voice
[Opus] Audio Hooks v5.1.1 | 6/26 Sounds | Webhook: ntfy | Theme: Voice
[MUTED 23m] feat/audio-v5 API Quota: 78% Context: 65% /compact
```

Expand Down
2 changes: 1 addition & 1 deletion bin/audio-hooks.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ def require_project_root() -> int:
# Project state — version, install detection, hook catalogue
# ---------------------------------------------------------------------------

PROJECT_VERSION = "5.0.3"
PROJECT_VERSION = "5.1.1"

# Canonical hook catalogue. Order matches CLAUDE.md and the install scripts.
HOOK_CATALOG: List[Dict[str, Any]] = [
Expand Down
6 changes: 3 additions & 3 deletions config/default_preferences.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
{
"$schema": "./user_preferences.schema.json",
"_comment": "Claude Code Audio Hooks - Default Configuration Template (v5.0.3)",
"_version": "5.0.3",
"_comment": "Claude Code Audio Hooks - Default Configuration Template (v5.1.1)",
"_version": "5.1.1",
"_description": "This file is the default template for user_preferences.json. Plugin installs auto-copy this to ${CLAUDE_PLUGIN_DATA}/user_preferences.json on first read. AI agents should NOT edit this file directly — use 'audio-hooks set <key> <value>' instead.",

"version": "5.0.3",
"version": "5.1.1",

"_comment_audio_theme": "Audio theme: 'default' for voice recordings, 'custom' for non-voice chimes. Change this one line to switch all audio.",
"audio_theme": "default",
Expand Down
2 changes: 1 addition & 1 deletion docs/ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ Native matcher routing happens at the `settings.json` layer (Claude Code's match
Two-line bottom bar registered in `~/.claude/settings.json` via `audio-hooks statusline install`. Reads stdin JSON Claude Code provides (model name, session_id, workspace.git_worktree, rate_limits, context_window) and emits two lines of plain text with ANSI colors:

```text
[Opus] 🔊 Audio Hooks v5.0.3 | 6/26 Sounds | Webhook: ntfy | Theme: Voice
[Opus] 🔊 Audio Hooks v5.1.1 | 6/26 Sounds | Webhook: ntfy | Theme: Voice
[MUTED 23m] 🌿 feat/audio-v5 ████░░░░ API Quota: 78% █████░░░ Context: 65% ⚠️ /compact
```

Expand Down
2 changes: 1 addition & 1 deletion hooks/hook_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@

# Version used for auto-sync: when the installed copy in ~/.claude/hooks/
# detects a newer version in the project directory, it self-updates.
HOOK_RUNNER_VERSION = "5.0.3"
HOOK_RUNNER_VERSION = "5.1.1"

# =============================================================================
# STRUCTURED LOGGING (NDJSON)
Expand Down
2 changes: 1 addition & 1 deletion plugins/audio-hooks/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "audio-hooks",
"version": "5.0.3",
"version": "5.1.1",
"description": "Audio notifications + AI-controlled config for every Claude Code event. 26 hooks, native matcher routing, TTS, webhooks, status line, focus flow, rate-limit alerts.",
"author": {
"name": "Chan Meng",
Expand Down
2 changes: 1 addition & 1 deletion plugins/audio-hooks/bin/audio-hooks.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ def require_project_root() -> int:
# Project state — version, install detection, hook catalogue
# ---------------------------------------------------------------------------

PROJECT_VERSION = "5.0.3"
PROJECT_VERSION = "5.1.1"

# Canonical hook catalogue. Order matches CLAUDE.md and the install scripts.
HOOK_CATALOG: List[Dict[str, Any]] = [
Expand Down
6 changes: 3 additions & 3 deletions plugins/audio-hooks/config/default_preferences.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
{
"$schema": "./user_preferences.schema.json",
"_comment": "Claude Code Audio Hooks - Default Configuration Template (v5.0.3)",
"_version": "5.0.3",
"_comment": "Claude Code Audio Hooks - Default Configuration Template (v5.1.1)",
"_version": "5.1.1",
"_description": "This file is the default template for user_preferences.json. Plugin installs auto-copy this to ${CLAUDE_PLUGIN_DATA}/user_preferences.json on first read. AI agents should NOT edit this file directly — use 'audio-hooks set <key> <value>' instead.",

"version": "5.0.3",
"version": "5.1.1",

"_comment_audio_theme": "Audio theme: 'default' for voice recordings, 'custom' for non-voice chimes. Change this one line to switch all audio.",
"audio_theme": "default",
Expand Down
2 changes: 1 addition & 1 deletion plugins/audio-hooks/hooks/hook_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@

# Version used for auto-sync: when the installed copy in ~/.claude/hooks/
# detects a newer version in the project directory, it self-updates.
HOOK_RUNNER_VERSION = "5.0.3"
HOOK_RUNNER_VERSION = "5.1.1"

# =============================================================================
# STRUCTURED LOGGING (NDJSON)
Expand Down
2 changes: 1 addition & 1 deletion plugins/audio-hooks/skills/audio-hooks/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ The status line displays real-time audio-hooks state and context window usage at

After installing, the status line updates every 60 seconds and shows two lines:
```
[Opus] 🔊 Audio Hooks v5.0.3 | 6/26 Sounds | Webhook: off | Theme: Voice
[Opus] 🔊 Audio Hooks v5.1.1 | 6/26 Sounds | Webhook: off | Theme: Voice
🌿 main ████░░░░ API Quota: 60% █████░░░ Context: 65% ⚠️ /compact
```

Expand Down
Loading