Skip to content
Open
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
1 change: 1 addition & 0 deletions plugins/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ Learn more in the [official plugins documentation](https://docs.claude.com/en/do
| [frontend-design](./frontend-design/) | Create distinctive, production-grade frontend interfaces that avoid generic AI aesthetics | **Skill:** `frontend-design` - Auto-invoked for frontend work, providing guidance on bold design choices, typography, animations, and visual details |
| [hookify](./hookify/) | Easily create custom hooks to prevent unwanted behaviors by analyzing conversation patterns or explicit instructions | **Commands:** `/hookify`, `/hookify:list`, `/hookify:configure`, `/hookify:help`<br>**Agent:** `conversation-analyzer` - Analyzes conversations for problematic behaviors<br>**Skill:** `writing-rules` - Guidance on hookify rule syntax |
| [learning-output-style](./learning-output-style/) | Interactive learning mode that requests meaningful code contributions at decision points (mimics the unshipped Learning output style) | **Hook:** SessionStart - Encourages users to write meaningful code (5-10 lines) at decision points while receiving educational insights |
| [notifier](./notifier/) | Cross-platform notifications when Claude Code completes tasks, requests permissions, or waits for input (macOS, Linux, Windows Native/WSL2) | **Hooks:** UserPromptSubmit, Stop, Notification, SessionEnd - Smart notifications for long-running tasks<br>**Command:** `/notifier` - Configure language, duration threshold, and preview length |
| [plugin-dev](./plugin-dev/) | Comprehensive toolkit for developing Claude Code plugins with 7 expert skills and AI-assisted creation | **Command:** `/plugin-dev:create-plugin` - 8-phase guided workflow for building plugins<br>**Agents:** `agent-creator`, `plugin-validator`, `skill-reviewer`<br>**Skills:** Hook development, MCP integration, plugin structure, settings, commands, agents, and skill development |
| [pr-review-toolkit](./pr-review-toolkit/) | Comprehensive PR review agents specializing in comments, tests, error handling, type design, code quality, and code simplification | **Command:** `/pr-review-toolkit:review-pr` - Run with optional review aspects (comments, tests, errors, types, code, simplify, all)<br>**Agents:** `comment-analyzer`, `pr-test-analyzer`, `silent-failure-hunter`, `type-design-analyzer`, `code-reviewer`, `code-simplifier` |
| [ralph-wiggum](./ralph-wiggum/) | Interactive self-referential AI loops for iterative development. Claude works on the same task repeatedly until completion | **Commands:** `/ralph-loop`, `/cancel-ralph` - Start/stop autonomous iteration loops<br>**Hook:** Stop - Intercepts exit attempts to continue iteration |
Expand Down
11 changes: 11 additions & 0 deletions plugins/notifier/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"name": "notifier",
"description": "Get notified when Claude Code completes tasks, requests permissions, or waits for input. Supports macOS, Linux, and Windows (Native/WSL2).",
"version": "2.0.0",
"author": {
"name": "Joo-Seung Koo",
"email": "[email protected]"
},
"repository": "https://github.com/js-koo/claude-code-notifier",
"keywords": ["notifications", "productivity", "cross-platform"]
}
154 changes: 154 additions & 0 deletions plugins/notifier/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
# claude-code-notifier

Get notified when Claude Code completes your tasks (Windows/macOS/Linux)

## Features

- **Cross-platform**: Windows (Native/WSL2), macOS, and Linux support
- **Smart notifications**: Only notifies for tasks taking 20+ seconds
- **Prompt preview**: Shows the first few characters of your prompt
- **Session-aware**: Multiple Claude Code sessions work independently
- **Zero config**: Works out of the box with sensible defaults
- **Slash command**: Easy configuration with `/notifier` command

## Tested Environments

| Platform | Status |
|----------|--------|
| macOS | ✅ Tested |
| Linux | ✅ Tested (Docker) |
| Windows (Native) | ✅ Tested |
| Windows (WSL2) | ✅ Tested |

> Found an issue? Please [open an issue](https://github.com/js-koo/claude-code-notifier/issues)!

## Requirements

- [Claude Code CLI](https://claude.ai/code)
- `jq` (JSON processor)
- **Linux only**: `libnotify-bin` (for `notify-send`)

## Installation

This plugin is included in the official Claude Code plugins directory.

For standalone installation, see [claude-code-notifier](https://github.com/js-koo/claude-code-notifier).

## Configuration

### Using Slash Command (Recommended)

Use the `/notifier` command in Claude Code:

| Command | Description |
|---------|-------------|
| `/notifier help` | Show available commands |
| `/notifier status` | Show current configuration |
| `/notifier lang <en\|ko>` | Set language (en: English, ko: 한국어) |
| `/notifier duration <seconds>` | Set minimum task duration (default: 20) |
| `/notifier preview <length>` | Set prompt preview length (default: 45) |
| `/notifier test` | Send a test notification |
| `/notifier uninstall` | Uninstall claude-code-notifier |

### Manual Configuration

Edit `config.sh` in the plugin's `hooks-handlers/` directory:

```bash
# Language setting: "en" (English) or "ko" (한국어)
NOTIFIER_LANG="en"

# Minimum task duration (seconds) to trigger notification
MIN_DURATION_SECONDS=20

# Number of characters to preview from the prompt
PROMPT_PREVIEW_LENGTH=45
```

### Configuration Options Explained

| Option | Default | Description |
|--------|---------|-------------|
| `NOTIFIER_LANG` | `en` | UI language. `en` for English, `ko` for Korean. Affects notification messages and slash command responses. |
| `MIN_DURATION_SECONDS` | `20` | Minimum task duration to trigger notification. Tasks completing faster than this won't show notifications. Set to `0` to notify on every task. |
| `PROMPT_PREVIEW_LENGTH` | `45` | Number of characters to show from your original prompt in the notification. |

### Notification Messages

Messages are automatically set based on `NOTIFIER_LANG`:

| Event | English | 한국어 |
|-------|---------|--------|
| Task completed | Task completed! | 작업 완료! |
| Permission required | Permission required! | 권한 필요! |
| Waiting for input | Waiting for input... | 입력 대기 중... |

### Examples

**Quick tasks without notifications:**
```bash
# Only notify for tasks taking 60+ seconds
/notifier duration 60
```

**Always notify:**
```bash
# Notify on every task completion
/notifier duration 0
```

**Longer prompt preview:**
```bash
# Show more of the original prompt
/notifier preview 100
```

**Switch to Korean:**
```bash
/notifier lang ko
```

## How It Works

This tool uses Claude Code's [hooks system](https://docs.anthropic.com/en/docs/claude-code/hooks) to:

1. **UserPromptSubmit**: Save the prompt and start time when you submit a task
2. **Stop**: Show a notification when Claude Code finishes (if duration > threshold)
3. **Notification**: Alert when permission is required or Claude is waiting for input
4. **SessionEnd**: Clean up temporary files when the session ends

Session data is stored in `~/.claude-code-notifier/data/`.

## Troubleshooting

### Notifications not appearing

**Windows (WSL)**:
- Ensure Windows notifications are enabled in Settings > System > Notifications
- Check that Focus Assist is not blocking notifications

**macOS**:
- Allow notifications from "Script Editor" in System Preferences > Notifications

**Linux**:
- Install `libnotify-bin`: `sudo apt install libnotify-bin`
- Check if `notify-send` works: `notify-send "Test" "Hello"`

### jq not found

Install jq using your package manager (see Installation section).

### WSL path issues

If you're using a non-default WSL distribution, the path conversion should still work automatically. If issues persist, check that `wslpath` is available.

## License

MIT License - see the [original repository](https://github.com/js-koo/claude-code-notifier) for details.

## Contributing

Contributions are welcome!

- **Bug reports / Feature requests**: [Open an Issue](https://github.com/js-koo/claude-code-notifier/issues)
- **Code contributions**: Submit a Pull Request
120 changes: 120 additions & 0 deletions plugins/notifier/commands/notifier.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
---
allowed-tools: Bash(sed:*), Bash(cat:*), Bash(grep:*), Bash(mkdir:*), Bash(echo:*), Bash(~/.claude-code-notifier/uninstall.sh)
argument-hint: <command> [value]
description: Configure claude-code-notifier settings
---

# Claude Code Notifier Configuration

## Available Commands

| Command | Description |
|---------|-------------|
| `help` | Show this help message |
| `status` | Show current configuration |
| `lang <en\|ko>` | Set language (en: English, ko: 한국어) |
| `duration <seconds>` | Set minimum task duration (default: 20) |
| `preview <length>` | Set prompt preview length (default: 45) |
| `test` | Send a test notification |
| `uninstall` | Uninstall claude-code-notifier |

## Language Detection

First, read NOTIFIER_LANG from ~/.claude-code-notifier/hooks-handlers/config.sh to determine response language.

## Task

User command: `$ARGUMENTS`

Perform the appropriate action based on the detected language:

### 1. `status`
Display current settings:

**English (en):**
```
📊 Current Configuration
━━━━━━━━━━━━━━━━━━━━━━━━
🌐 Language: {en|ko}
⏱️ Min Duration: {value} seconds
📝 Preview Length: {value} characters
━━━━━━━━━━━━━━━━━━━━━━━━
```

**Korean (ko):**
```
📊 현재 설정
━━━━━━━━━━━━━━━━━━━━━━━━
🌐 언어: {en|ko}
⏱️ 최소 시간: {value}초
📝 미리보기 길이: {value}자
━━━━━━━━━━━━━━━━━━━━━━━━
```

### 2. `lang <en|ko>`
- Validate that the value is "en" or "ko"
- Update NOTIFIER_LANG in config.sh using sed
- **en:** "✅ Language updated to {value}"
- **ko:** "✅ 언어가 {value}(으)로 변경되었습니다"

### 3. `duration <number>`
- Validate that the value is a positive number
- Update MIN_DURATION_SECONDS in config.sh using sed
- **en:** "✅ Duration updated to {value} seconds"
- **ko:** "✅ 최소 시간이 {value}초로 변경되었습니다"

### 4. `preview <number>`
- Validate that the value is a positive number
- Update PROMPT_PREVIEW_LENGTH in config.sh using sed
- **en:** "✅ Preview length updated to {value} characters"
- **ko:** "✅ 미리보기 길이가 {value}자로 변경되었습니다"

### 5. `test`
Run these commands:
```bash
mkdir -p ~/.claude-code-notifier/data
echo "Test notification from /notifier" > ~/.claude-code-notifier/data/prompt-test.txt
echo $(date +%s) > ~/.claude-code-notifier/data/timestamp-test.txt
echo '{"session_id": "test"}' | ~/.claude-code-notifier/hooks-handlers/notify.sh
```
- **en:** "✅ Test notification sent!"
- **ko:** "✅ 테스트 알림을 전송했습니다!"

### 6. `uninstall`
Run the uninstall script:
```bash
~/.claude-code-notifier/uninstall.sh
```

**English (en):**
```
✅ claude-code-notifier has been uninstalled.

⚠️ Please restart Claude Code to complete the uninstallation.
(Type /exit or press Ctrl+C)
```

**Korean (ko):**
```
✅ claude-code-notifier가 삭제되었습니다.

⚠️ 삭제를 완료하려면 Claude Code를 재시작하세요.
(/exit 입력 또는 Ctrl+C)
```

### 7. `help` or empty/invalid command
Show the available commands table above.

### Error Handling

**English (en):**
- If config.sh not found: "❌ claude-code-notifier is not installed. Run install.sh first."
- If invalid number provided: "❌ Please provide a valid positive number."
- If invalid language provided: "❌ Please provide a valid language (en or ko)."
- If unknown command: "❌ Unknown command. Use `/notifier help` to see available commands."

**Korean (ko):**
- If config.sh not found: "❌ claude-code-notifier가 설치되지 않았습니다. install.sh를 먼저 실행하세요."
- If invalid number provided: "❌ 유효한 양수를 입력하세요."
- If invalid language provided: "❌ 유효한 언어를 입력하세요 (en 또는 ko)."
- If unknown command: "❌ 알 수 없는 명령어입니다. `/notifier help`로 사용 가능한 명령어를 확인하세요."
19 changes: 19 additions & 0 deletions plugins/notifier/hooks-handlers/cleanup-session.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#!/bin/bash
# cleanup-session.sh - Cleans up session files when Claude Code session ends
# Hook: SessionEnd

set -e

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/common.sh"

# Read stdin (JSON from Claude Code)
INPUT=$(cat)

SESSION_ID=$(get_session_id "$INPUT")

# Clean up session files
rm -f "$DATA_DIR/prompt-${SESSION_ID}.txt"
rm -f "$DATA_DIR/timestamp-${SESSION_ID}.txt"

exit 0
64 changes: 64 additions & 0 deletions plugins/notifier/hooks-handlers/common.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#!/bin/bash
# common.sh - Shared utilities for claude-code-notifier
# Sourced by notifier scripts

DATA_DIR="$HOME/.claude-code-notifier/data"

# Extract value from JSON using jq or fallback to grep/sed
# Usage: json_get "$JSON_STRING" "field_name"
json_get() {
local json="$1"
local field="$2"

if command -v jq &> /dev/null; then
echo "$json" | jq -r ".$field // empty" 2>/dev/null
else
echo "$json" | grep -oE "\"$field\":[[:space:]]*\"[^\"]*\"" | sed "s/\"$field\":[[:space:]]*\"\(.*\)\"/\1/" | head -1
fi
}

# Get session ID from JSON, defaulting to "default"
# Usage: get_session_id "$JSON_STRING"
get_session_id() {
local json="$1"
local session_id

session_id=$(json_get "$json" "session_id")
echo "${session_id:-default}"
}

# Check if notification should be shown based on duration
# Returns 0 if should notify, 1 if should skip
# Usage: should_notify "$SESSION_ID" "$MIN_DURATION"
should_notify() {
local session_id="$1"
local min_duration="$2"
local timestamp_file="$DATA_DIR/timestamp-${session_id}.txt"

if [ ! -f "$timestamp_file" ]; then
return 1
fi

local start_time
start_time=$(cat "$timestamp_file" 2>/dev/null)
local current_time
current_time=$(date +%s)
local elapsed=$((current_time - start_time))

if [ "$elapsed" -lt "$min_duration" ]; then
return 1
fi

return 0
}

# Get saved prompt text for session
# Usage: get_prompt_text "$SESSION_ID"
get_prompt_text() {
local session_id="$1"
local prompt_file="$DATA_DIR/prompt-${session_id}.txt"

if [ -f "$prompt_file" ]; then
cat "$prompt_file" 2>/dev/null
fi
}
Loading