commit 62229c6c8372c414838b526d8775bf4fbca5e3ab Author: Zhongwei Li Date: Sat Nov 29 18:47:45 2025 +0800 Initial commit diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json new file mode 100644 index 0000000..b1b5366 --- /dev/null +++ b/.claude-plugin/plugin.json @@ -0,0 +1,16 @@ +{ + "name": "cc-hooks", + "description": "Audio feedback system with multilingual TTS announcements, AI-powered contextual messages, and sound effects for Claude Code. Transform your coding experience with intelligent voice feedback that keeps you informed without breaking your flow.", + "version": "1.0.0", + "author": { + "name": "Husni Adil Makmur", + "email": "husniadil@gmail.com", + "url": "https://github.com/husniadil" + }, + "commands": [ + "./commands" + ], + "hooks": [ + "./hooks" + ] +} \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..7de3697 --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# cc-hooks + +Audio feedback system with multilingual TTS announcements, AI-powered contextual messages, and sound effects for Claude Code. Transform your coding experience with intelligent voice feedback that keeps you informed without breaking your flow. diff --git a/commands/setup.md b/commands/setup.md new file mode 100644 index 0000000..ff73332 --- /dev/null +++ b/commands/setup.md @@ -0,0 +1,493 @@ +--- +allowed-tools: Read, Bash, Edit, Write +description: Setup and configure cc-hooks plugin +argument-hint: [check|apikeys|test] +--- + +# cc-hooks Setup Assistant + +Help the user set up and configure the cc-hooks plugin. Follow these steps: + +## 1. System Requirements Check + +Check if `uv` is installed: + +```bash +uv --version +``` + +If not installed, guide the user to install it: + +- **macOS/Linux**: `curl -LsSf https://astral.sh/uv/install.sh | sh` +- **Windows**: `powershell -c "irm https://astral.sh/uv/install.ps1 | iex"` + +## 2. Shell Alias Setup + +### 2.1. Check `cld` Alias Availability + +Check if `cld` command is available using BOTH methods: + +```bash +# Detect user's shell +echo $SHELL + +# Method 1: Test if cld works in current shell +type cld 2>/dev/null && echo "cld: available in current shell" || echo "cld: not found in current shell" + +# Method 2: Check if cld is configured in shell config files +grep -h "alias cld=" ~/.zshrc ~/.bashrc ~/.bash_profile ~/.profile 2>/dev/null && echo "cld: found in shell config" || echo "cld: not found in shell config" +``` + +**Decision logic:** + +- If **EITHER** method finds `cld` → Skip to checking wrapper alias (Section 2.2) +- If **BOTH** methods fail → Offer to create `cld` alias + +### Creating `cld` Alias (only if not found) + +If `cld` is not available in either current shell or config files, guide the user to add it: + +**For zsh users** (~/.zshrc): + +```bash +alias cld='~/.claude/plugins/marketplaces/cc-hooks-plugin/claude.sh' +``` + +**For bash users** (~/.bashrc or ~/.bash_profile): + +```bash +alias cld='~/.claude/plugins/marketplaces/cc-hooks-plugin/claude.sh' +``` + +Ask the user if they would like to add the `cld` alias to their shell configuration for convenience. + +If the user agrees, add the appropriate alias to their shell config file and remind them to run +`source ~/.zshrc` (or appropriate config file) or restart their terminal. + +### 2.2. Check for Wrapper Alias (Optional) + +After confirming `cld` is available (either in current shell or config files), check if a wrapper +alias already exists: + +```bash +# Check for any alias that wraps cld with arguments +grep -h "alias.*='cld " ~/.zshrc ~/.bashrc ~/.bash_profile ~/.profile 2>/dev/null | grep -v "^#" +``` + +**If wrapper alias exists:** + +- Show the user what's configured (e.g., "Found wrapper alias: cc='cld --audio=gtts --ai=full'") +- Skip to step 3 + +**If no wrapper exists:** + +Inform the user that they can optionally create a convenient wrapper alias with their preferred +default settings. Present the available preset configurations: + +**Preset configurations:** + +1. **Basic**: `alias cc='cld'` - Prerecorded audio only +2. **Enhanced**: `alias cc='cld --audio=gtts --ai=basic'` - Google TTS with AI (requires OpenRouter) +3. **Full**: `alias cc='cld --audio=gtts --ai=full'` - Google TTS with all AI features (requires + OpenRouter) +4. **Premium**: `alias cc='cld --audio=elevenlabs --ai=full'` - ElevenLabs with AI (requires both + API keys) +5. **Silent**: `alias cc='cld --silent'` - No audio, visual only +6. **Skip**: Continue without creating a wrapper alias + +**Implementation:** + +- If the user wants a preset, ask which one they prefer +- Optionally offer to customize with language flag (e.g., `--language=id`) +- Add the chosen alias to their shell config file +- Remind them to run `source ~/.zshrc` (or appropriate config file) or restart their terminal +- Explain that they can still use `cld` with different flags when needed + +**Example:** + +```bash +# Enhanced preset with Indonesian language +alias cc='cld --audio=gtts --ai=basic --language=id' +``` + +## 3. Status Line Configuration Check + +Check if statusline is configured properly in `~/.claude/settings.json`: + +```bash +# Read the settings file +cat ~/.claude/settings.json | grep -A 2 '"statusLine"' +``` + +**Expected configuration**: + +```json +"statusLine": { + "type": "command", + "command": "uv run ~/.claude/plugins/marketplaces/cc-hooks-plugin/status-lines/status_line.py" +} +``` + +**If not configured or pointing to wrong path**, offer to update it automatically or guide the user +to add/update the statusLine configuration. + +## 4. Environment Variables Check + +**IMPORTANT**: Plugin updates will delete and redownload all plugin files. Therefore, API keys and +environment variables MUST be stored outside the plugin directory (e.g., in shell config files like +`~/.zshrc` or `~/.bashrc`, or in separate files loaded by your shell). + +### Check if API Keys are Available + +First, check if API keys are available in the current environment: + +```bash +# Check for API keys in current environment (DO NOT print values) +env | grep -E "OPENROUTER_API_KEY|ELEVENLABS_API_KEY" | sed 's/=.*/=[SET]/' || echo "No API keys found" +``` + +**If API keys ARE available** (regardless of how they're loaded): + +- ✅ Confirm that API keys are set and ready to use +- Skip offering to add them (user has their own setup) +- Continue to next step + +**If API keys ARE NOT available**, check shell config files: + +```bash +# Check for API keys in shell config (DO NOT print values) +grep -h "OPENROUTER_API_KEY\|ELEVENLABS_API_KEY" ~/.zshrc ~/.bashrc ~/.bash_profile ~/.profile 2>/dev/null | sed 's/=.*/=[REDACTED]/' || echo "No API keys found in shell config" +``` + +### API Keys to Configure + +**OpenRouter** (for AI contextual messages): + +- `OPENROUTER_API_KEY`: Get from https://openrouter.ai/keys +- Required only if using `--ai=basic` or `--ai=full` +- **If provided**: Recommend starting with `cld --audio=gtts --ai=full` (or `--ai=basic`) + +**ElevenLabs** (for premium TTS): + +- `ELEVENLABS_API_KEY`: Get from https://elevenlabs.io/ +- Required only if using `--audio=elevenlabs` + +### Configuring Environment Variables + +**Only offer this if API keys are NOT available in the current environment.** + +Guide the user to add them to their shell config: + +**For zsh users** (~/.zshrc): + +```bash +# cc-hooks API Keys +export OPENROUTER_API_KEY="your-key-here" +export ELEVENLABS_API_KEY="your-key-here" +``` + +**For bash users** (~/.bashrc or ~/.bash_profile): + +```bash +# cc-hooks API Keys +export OPENROUTER_API_KEY="your-key-here" +export ELEVENLABS_API_KEY="your-key-here" +``` + +**After adding:** + +- Remind them to run `source ~/.zshrc` (or appropriate config file) or restart their terminal +- Explain that only the keys they need should be added (OpenRouter for AI, ElevenLabs for premium + TTS) +- Note that they can also load keys from separate files (e.g., `source ~/.api-keys` in their shell + config) + +**SECURITY NOTE**: Never print actual API key values in output. Always redact or mask them. + +## 5. Configuration File Setup (Recommended) + +**This step is OPTIONAL but highly recommended** - it provides a better experience for all users. + +### Why Use a Config File? + +The config file (`~/.claude/.cc-hooks/config.yaml`) lets you set default preferences without using +CLI flags: + +**Benefits for Zed/Editor users:** + +- ✅ **Editors can't pass CLI flags** → Config file enables customization +- ✅ Set audio provider, language, AI features → Works automatically in Zed + +**Benefits for Terminal users:** + +- ✅ No need to type flags every time → Just run `cld` or `claude` +- ✅ Set your preferred defaults → Consistent experience +- ✅ Can still override with CLI flags when needed + +### Check if Config Exists + +```bash +# Check if config file already exists +ls -la ~/.claude/.cc-hooks/config.yaml +``` + +**If config exists:** + +- Show the user their current settings +- Ask if they want to modify it +- Skip to next section if they're happy + +**If config doesn't exist:** + +- Offer to create one with their preferences + +### Creating Config File + +If the user wants to create a config file: + +**Option 1: Create with default example (Recommended)** + +```bash +# Create example config with all options documented +uv run ~/.claude/plugins/marketplaces/cc-hooks-plugin/utils/config_loader.py --create-example + +# Show the created file +cat ~/.claude/.cc-hooks/config.yaml +``` + +**Option 2: Interactive configuration** + +Ask the user for their preferences: + +1. **Audio provider**: prerecorded (default), gtts (free), or elevenlabs (premium) +2. **Language**: en (default), id, es, fr, etc. +3. **AI features**: disabled (default), basic, or full +4. **Silent modes**: none (default), announcements, or sound-effects + +Then create a customized config file based on their answers. + +**Example for Indonesian user with Google TTS:** + +```yaml +audio: + providers: gtts,prerecorded + language: id + cache_enabled: true + +openrouter: + enabled: false +``` + +**Example for premium setup (requires API keys):** + +```yaml +audio: + providers: elevenlabs,gtts,prerecorded + language: en + cache_enabled: true + +elevenlabs: + voice_id: 21m00Tcm4TlvDq8ikWAM + model_id: eleven_flash_v2_5 + +openrouter: + enabled: true + model: openai/gpt-4o-mini + contextual_stop: true + contextual_pretooluse: false +``` + +### Explain Priority System + +After creating the config, explain to the user: + +**Configuration Priority** (highest to lowest): + +1. **CLI flags** → `cld --language=es` (terminal usage, session override) +2. **Environment variables** → `export CC_TTS_LANGUAGE=es` (temporary override) +3. **Config file** → `~/.claude/.cc-hooks/config.yaml` (your defaults) ← **NEW!** +4. **Hardcoded defaults** → Built-in fallback values + +**This means:** + +- Config file provides your defaults for all sessions +- Terminal users can override with `cld --flag` when needed +- Zed/editor users get config defaults automatically +- Everyone benefits from "set once, forget" workflow + +### Verify Config Works + +```bash +# Test that config is loaded (check with a simple session) +cld + +# Or test config loading directly +cd ~/.claude/plugins/marketplaces/cc-hooks-plugin +uv run utils/config_loader.py +``` + +## 6. Configuration Options (CLI Flags) + +Users can configure cc-hooks using **command-line arguments** which override config file and +environment variables: + +### Audio Control + +```bash +cld --audio=gtts # Google TTS (free, internet required) +cld --audio=elevenlabs # Premium TTS (requires API key) +cld --audio=prerecorded # Built-in audio files (default) +cld --language=id # Language (id, es, en, etc.) +cld --silent # Disable all audio +cld --silent=announcements # Keep sound effects, disable TTS +cld --silent=sound-effects # Keep TTS, disable sound effects +``` + +### AI Features (requires OpenRouter API key) + +```bash +cld --ai=basic # Contextual Stop messages only +cld --ai=full # All contextual messages (Stop + PreToolUse) +``` + +### Combined Examples + +```bash +cld --audio=gtts --language=id --ai=full +cld --audio=elevenlabs --ai=basic +cld --silent=announcements +``` + +**Note**: CLI arguments override config file and environment variables for that session only. + +## 7. Test Setup + +If the user requests testing, run these verification checks: + +### Basic Audio Test + +```bash +cd ~/.claude/plugins/marketplaces/cc-hooks-plugin +uv run utils/sound_player.py --list +uv run utils/sound_player.py sound_effect_cetek.mp3 +``` + +### TTS Test + +```bash +cd ~/.claude/plugins/marketplaces/cc-hooks-plugin +uv run utils/tts_announcer.py --list +uv run utils/tts_announcer.py SessionStart +``` + +### Server Test + +Check if server can start: + +```bash +cd ~/.claude/plugins/marketplaces/cc-hooks-plugin +timeout 5 uv run server.py --port 12299 || echo "Server test completed" +``` + +## 8. Usage Examples + +Show the user how to start Claude with different configurations: + +**With config file (Recommended for most users):** + +```bash +# Just run claude directly - uses your config file settings +claude + +# Or if you set up the cld alias +cld +``` + +**With CLI flags (Power users - per-session overrides):** + +**If default alias was created (e.g., `cc`):** + +```bash +# Use your default configuration +cc + +# Override with different settings +cld --audio=gtts --language=id +cld --silent +``` + +**Using `cld` directly with various configurations:** + +```bash +# Basic usage with prerecorded audio (default) +cld + +# Google TTS in Indonesian +cld --audio=gtts --language=id + +# ElevenLabs TTS with AI features +cld --audio=elevenlabs --ai=full + +# Silent mode (no audio) +cld --silent + +# Silent announcements only (keep sound effects) +cld --silent=announcements +``` + +## 9. Troubleshooting + +Common issues and solutions: + +### Audio Not Playing + +- Check system volume +- Test with: `uv run utils/sound_player.py` +- Check if pygame is installed: `uv pip list | grep pygame` + +### Server Won't Start + +- Check if port is in use: `lsof -i :12222` +- Check logs: `tail -f ~/.claude/.cc-hooks/logs/*.log` +- Try different port: `CC_HOOKS_PORT=12223 ./claude.sh` + +### TTS Not Working + +- Check if API keys are set in shell config (redacted): + `env | grep -E "OPENROUTER_API_KEY|ELEVENLABS_API_KEY" | sed 's/=.*/=[SET]/' || echo "No API keys found"` +- Test provider directly: `uv run utils/tts_announcer.py --provider gtts SessionStart` +- Check internet connection (required for gtts and elevenlabs) +- Verify shell config was sourced: restart terminal or run `source ~/.zshrc` + +### Setup Cannot Complete or Bug Found + +If you encounter issues that prevent setup from completing, or you've found a bug: + +**Report the issue on GitHub:** https://github.com/husniadil/cc-hooks/issues/new + +**Include in your report:** + +- What step failed (e.g., "Step 2: Shell Alias Setup") +- Error message or unexpected behavior +- Your OS and shell (from `echo $SHELL`) +- Relevant logs from `~/.claude/.cc-hooks/logs/` + +## Argument Handling + +If the user provides an argument: + +- **check**: Run system requirements and configuration check only +- **apikeys**: Focus on API key setup and validation +- **test**: Run all test suites to verify installation + +If no argument provided, run the full interactive setup wizard. + +## Important Notes + +- **CRITICAL**: Never print or expose API key values in any output - always redact them +- Do NOT create or modify `.env` files in the plugin directory (they will be deleted on updates) +- API keys MUST be stored in shell config files (~/.zshrc, ~/.bashrc, etc.) +- Always confirm before writing/modifying files +- Direct the user to documentation for advanced configuration: https://github.com/husniadil/cc-hooks +- **If setup fails or you encounter a bug**: Guide the user to report the issue at + https://github.com/husniadil/cc-hooks/issues/new diff --git a/commands/update.md b/commands/update.md new file mode 100644 index 0000000..27e2fa6 --- /dev/null +++ b/commands/update.md @@ -0,0 +1,251 @@ +--- +allowed-tools: Bash +description: Check for cc-hooks updates and install if available +--- + +# cc-hooks Update Assistant + +Check for cc-hooks updates and install them if available. + +## Update Check Flow + +### 1. Detect Installation Mode + +Determine if cc-hooks is running in plugin mode or standalone mode by checking the hooks +configuration: + +```bash +# Detect installation mode +python3 -c " +import json, sys, os + +# Check 1: Plugin mode - hooks defined in plugin directory +plugin_hooks_file = os.path.expanduser('~/.claude/plugins/marketplaces/cc-hooks-plugin/hooks/hooks.json') +if os.path.isfile(plugin_hooks_file): + try: + with open(plugin_hooks_file, 'r') as f: + config = json.load(f) + # Verify it has hooks configuration + if config.get('hooks') and len(config['hooks']) > 0: + # Verify hooks.py exists + plugin_hooks_py = os.path.expanduser('~/.claude/plugins/marketplaces/cc-hooks-plugin/hooks.py') + if os.path.isfile(plugin_hooks_py): + print('plugin') + sys.exit(0) + except: + pass + +# Check 2: Standalone mode - hooks defined in settings.json +settings_file = os.path.expanduser('~/.claude/settings.json') +if os.path.isfile(settings_file): + try: + with open(settings_file, 'r') as f: + config = json.load(f) + hooks = config.get('hooks', {}) + # Check if any hook points to hooks.py + for event_hooks in hooks.values(): + if isinstance(event_hooks, list): + for matcher_group in event_hooks: + for hook in matcher_group.get('hooks', []): + command = hook.get('command', '') + if 'hooks.py' in command: + print('standalone') + sys.exit(0) + except: + pass + +print('unknown') +" +``` + +**Detection Logic**: + +1. **Check Plugin Mode First**: + - Look for `~/.claude/plugins/marketplaces/cc-hooks-plugin/hooks/hooks.json` + - Verify it contains valid `hooks` configuration + - Verify `hooks.py` exists at `~/.claude/plugins/marketplaces/cc-hooks-plugin/hooks.py` + - If all checks pass → **Plugin mode** + +2. **Check Standalone Mode**: + - Read `~/.claude/settings.json` + - Check the `hooks` field (MUST be exactly `hooks`, not `#hooks_disabled`) + - Look for any hook command containing `hooks.py` + - If found → **Standalone mode** + +3. **If neither**: + - Result: **Unknown** (cc-hooks not configured) + +**Why this order matters**: + +- In plugin mode, hooks are NOT in `~/.claude/settings.json` +- In plugin mode, hooks are in `~/.claude/plugins/marketplaces/cc-hooks-plugin/hooks/hooks.json` +- Must check plugin directory first before checking settings.json + +**Example configurations**: + +**Plugin mode**: `~/.claude/plugins/marketplaces/cc-hooks-plugin/hooks/hooks.json` + +```json +{ + "hooks": { + "SessionStart": [ + { + "hooks": [{ "type": "command", "command": "uv run ${CLAUDE_PLUGIN_ROOT}/hooks.py" }] + } + ] + } +} +``` + +**Standalone mode**: `~/.claude/settings.json` + +```json +{ + "hooks": { + "SessionStart": [ + { + "hooks": [{ "type": "command", "command": "uv run /Users/username/cc-hooks/hooks.py" }] + } + ] + } +} +``` + +### 2. Check for Updates + +Query the cc-hooks server for version status: + +```bash +# Try to get version status from the server +curl -s http://localhost:12222/version/status 2>/dev/null || \ +curl -s http://localhost:12223/version/status 2>/dev/null || \ +curl -s http://localhost:12224/version/status 2>/dev/null || \ +echo '{"error": "Server not running"}' +``` + +**Important**: Try multiple ports (12222, 12223, 12224) as the server may be running on different +ports for different instances. + +### 3. Parse Version Information + +From the API response, extract: + +- `update_available` (boolean) +- `current_version` (string) +- `latest_version` (string) +- `commits_behind` (number) + +### 4. Display Status + +**If server is not running or error:** + +``` +❌ Cannot check for updates: cc-hooks server is not running +💡 Start Claude Code with cc-hooks to check for updates +``` + +**If no update available:** + +``` +✅ cc-hooks is up to date +📌 Current version: {current_version} +``` + +**If update available:** + +``` +⚠️ Update available for cc-hooks + +Current version: {current_version} +Latest version: {latest_version} +Commits behind: {commits_behind} + +Would you like to update now? +``` + +### 5. Offer to Update + +If update is available, ask the user if they would like to proceed with the update now. + +- If the user confirms → Proceed with update +- If the user declines → Skip update and show them how to update manually later + +### 6. Execute Update + +**For Plugin Mode:** + +```bash +claude plugin marketplace update cc-hooks-plugin +``` + +**For Standalone Mode:** + +```bash +cd {repo_root} && npm run update +``` + +**After update:** + +``` +✅ cc-hooks has been updated to {latest_version} +⚠️ Please restart your Claude Code session for changes to take effect +``` + +## Error Handling + +**If update command fails:** + +``` +❌ Update failed. Please try manually: + +Plugin mode: + claude plugin marketplace update cc-hooks-plugin + +Standalone mode: + cd {repo_root} + npm run update +``` + +**If the update continues to fail or you encounter a bug:** + +Direct the user to report the issue on GitHub: https://github.com/husniadil/cc-hooks/issues/new + +**Include in the report:** + +- Current version (from error message or `/version/status` endpoint) +- Installation mode (plugin or standalone) +- Full error message +- OS and shell information +- Steps attempted before failure + +## Example Session + +``` +$ /cc-hooks-plugin:update + +Checking for cc-hooks updates... + +⚠️ Update available for cc-hooks + +Current version: v1.0.0 +Latest version: v1.0.1 +Commits behind: 3 + +Would you like to update now? [Yes/No] +> Yes + +Updating cc-hooks... +✅ cc-hooks has been updated to v1.0.1 +⚠️ Please restart your Claude Code session for changes to take effect +``` + +## Implementation Notes + +- Always check server availability first +- Try multiple ports (race condition during server startup) +- Detect installation mode from current working directory +- Use appropriate update command based on mode +- Always remind user to restart Claude Code after update +- Handle connection errors gracefully +- **If update fails or bugs are found**: Direct users to + https://github.com/husniadil/cc-hooks/issues/new diff --git a/hooks/hooks.json b/hooks/hooks.json new file mode 100644 index 0000000..fb2c25f --- /dev/null +++ b/hooks/hooks.json @@ -0,0 +1,103 @@ +{ + "hooks": { + "SessionStart": [ + { + "matcher": "", + "hooks": [ + { + "type": "command", + "command": "uv run ${CLAUDE_PLUGIN_ROOT}/hooks.py" + } + ] + } + ], + "SessionEnd": [ + { + "matcher": "", + "hooks": [ + { + "type": "command", + "command": "uv run ${CLAUDE_PLUGIN_ROOT}/hooks.py" + } + ] + } + ], + "PreToolUse": [ + { + "matcher": "", + "hooks": [ + { + "type": "command", + "command": "uv run ${CLAUDE_PLUGIN_ROOT}/hooks.py" + } + ] + } + ], + "PostToolUse": [ + { + "matcher": "", + "hooks": [ + { + "type": "command", + "command": "uv run ${CLAUDE_PLUGIN_ROOT}/hooks.py" + } + ] + } + ], + "Notification": [ + { + "matcher": "", + "hooks": [ + { + "type": "command", + "command": "uv run ${CLAUDE_PLUGIN_ROOT}/hooks.py" + } + ] + } + ], + "UserPromptSubmit": [ + { + "matcher": "", + "hooks": [ + { + "type": "command", + "command": "uv run ${CLAUDE_PLUGIN_ROOT}/hooks.py" + } + ] + } + ], + "Stop": [ + { + "matcher": "", + "hooks": [ + { + "type": "command", + "command": "uv run ${CLAUDE_PLUGIN_ROOT}/hooks.py" + } + ] + } + ], + "SubagentStop": [ + { + "matcher": "", + "hooks": [ + { + "type": "command", + "command": "uv run ${CLAUDE_PLUGIN_ROOT}/hooks.py" + } + ] + } + ], + "PreCompact": [ + { + "matcher": "", + "hooks": [ + { + "type": "command", + "command": "uv run ${CLAUDE_PLUGIN_ROOT}/hooks.py" + } + ] + } + ] + } +} diff --git a/plugin.lock.json b/plugin.lock.json new file mode 100644 index 0000000..9410c72 --- /dev/null +++ b/plugin.lock.json @@ -0,0 +1,53 @@ +{ + "$schema": "internal://schemas/plugin.lock.v1.json", + "pluginId": "gh:husniadil/cc-hooks:", + "normalized": { + "repo": null, + "ref": "refs/tags/v20251128.0", + "commit": "2940902b30adf3549f039336e1463935c2eebb36", + "treeHash": "e6c454bd96c657ece5dd0ac8e8a3cdd235ac66164aba2854e78c07b436ad4504", + "generatedAt": "2025-11-28T10:17:37.488436Z", + "toolVersion": "publish_plugins.py@0.2.0" + }, + "origin": { + "remote": "git@github.com:zhongweili/42plugin-data.git", + "branch": "master", + "commit": "aa1497ed0949fd50e99e70d6324a29c5b34f9390", + "repoRoot": "/Users/zhongweili/projects/openmind/42plugin-data" + }, + "manifest": { + "name": "cc-hooks", + "description": "Audio feedback system with multilingual TTS announcements, AI-powered contextual messages, and sound effects for Claude Code. Transform your coding experience with intelligent voice feedback that keeps you informed without breaking your flow.", + "version": "1.0.0" + }, + "content": { + "files": [ + { + "path": "README.md", + "sha256": "e2875c66526539420eaada5b96498ba793a46696fba4e97b9957a73825dc6f43" + }, + { + "path": "hooks/hooks.json", + "sha256": "3dc4a1f16e2b80f1ee8b763fa30602111e7dd321b5b768427b15ba87db6905b0" + }, + { + "path": ".claude-plugin/plugin.json", + "sha256": "8c1294441e11f9252d30c1847a9ff6cb7c5fc9311993fb48b9b4fc85d06e15db" + }, + { + "path": "commands/setup.md", + "sha256": "98858b94c60361534059c8dcd54d58f8c9fbacbc9498aa6598f0f2c98b3cfb15" + }, + { + "path": "commands/update.md", + "sha256": "43013081262da74b018f6a10058c91ac16d8d1f418f2d7c84ab921e4d950bb0f" + } + ], + "dirSha256": "e6c454bd96c657ece5dd0ac8e8a3cdd235ac66164aba2854e78c07b436ad4504" + }, + "security": { + "scannedAt": null, + "scannerVersion": null, + "flags": [] + } +} \ No newline at end of file