diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json
index 2f32b28..8eee1bd 100644
--- a/.claude-plugin/marketplace.json
+++ b/.claude-plugin/marketplace.json
@@ -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",
diff --git a/.github/workflows/smoke.yml b/.github/workflows/smoke.yml
new file mode 100644
index 0000000..9b02fcb
--- /dev/null
+++ b/.github/workflows/smoke.yml
@@ -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
diff --git a/CHANGELOG.md b/CHANGELOG.md
index cb677bb..0e192e1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -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.
diff --git a/CLAUDE.md b/CLAUDE.md
index d6e30f5..55f2b6b 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -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.
diff --git a/README.md b/README.md
index d71c483..c573fff 100644
--- a/README.md
+++ b/README.md
@@ -9,7 +9,7 @@ You type one slash command at install time. Then natural language forever.
26 hook events, 2 audio themes, rate-limit alerts, webhooks, TTS, context monitor — all operated by Claude Code on your behalf.
[](https://opensource.org/licenses/MIT)
-[](https://github.com/ChanMeng666/claude-code-audio-hooks)
+[](https://github.com/ChanMeng666/claude-code-audio-hooks)
[](https://github.com/ChanMeng666/claude-code-audio-hooks)
[](https://claude.ai/download)
[](#-install-in-60-seconds)
@@ -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
@@ -505,7 +505,7 @@ Real-time context window and API quota bars — color-coded warnings before Clau