Skip to content

Commit d852fb6

Browse files
authored
Merge pull request #6 from thomasKn/feat/pause-toggle
Add pause/mute toggle via CLI subcommands and slash command
2 parents 5f68808 + 9474f12 commit d852fb6

5 files changed

Lines changed: 162 additions & 2 deletions

File tree

README.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,25 @@ One command. Takes 10 seconds. macOS only. Re-run to update (sounds and config p
2929

3030
Plus Terminal tab titles (`● project: done`) and macOS notifications when Terminal isn't focused.
3131

32+
## Quick controls
33+
34+
Need to mute sounds and notifications during a meeting or pairing session? Two options:
35+
36+
| Method | Command | When |
37+
|---|---|---|
38+
| **Slash command** | `/peon-ping-toggle` | While working in Claude Code |
39+
| **CLI** | `peon --toggle` | From any terminal tab |
40+
41+
Other CLI commands:
42+
43+
```bash
44+
peon --pause # Mute sounds
45+
peon --resume # Unmute sounds
46+
peon --status # Check if paused or active
47+
```
48+
49+
Pausing mutes sounds and desktop notifications instantly. Persists across sessions until you resume. Tab titles remain active when paused.
50+
3251
## Configuration
3352

3453
Edit `~/.claude/hooks/peon-ping/config.json`:

install.sh

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,28 @@ fi
103103

104104
chmod +x "$INSTALL_DIR/peon.sh"
105105

106+
# --- Install skill (slash command) ---
107+
SKILL_DIR="$HOME/.claude/skills/peon-ping-toggle"
108+
mkdir -p "$SKILL_DIR"
109+
if [ -n "$SCRIPT_DIR" ] && [ -d "$SCRIPT_DIR/skills/peon-ping-toggle" ]; then
110+
cp "$SCRIPT_DIR/skills/peon-ping-toggle/SKILL.md" "$SKILL_DIR/"
111+
elif [ -z "$SCRIPT_DIR" ]; then
112+
curl -fsSL "$REPO_BASE/skills/peon-ping-toggle/SKILL.md" -o "$SKILL_DIR/SKILL.md"
113+
else
114+
echo "Warning: skills/peon-ping-toggle not found in local clone, skipping skill install"
115+
fi
116+
117+
# --- Add shell alias ---
118+
ALIAS_LINE='alias peon="bash ~/.claude/hooks/peon-ping/peon.sh"'
119+
for rcfile in "$HOME/.zshrc" "$HOME/.bashrc"; do
120+
if [ -f "$rcfile" ] && ! grep -qF 'alias peon=' "$rcfile"; then
121+
echo "" >> "$rcfile"
122+
echo "# peon-ping quick controls" >> "$rcfile"
123+
echo "$ALIAS_LINE" >> "$rcfile"
124+
echo "Added peon alias to $(basename "$rcfile")"
125+
fi
126+
done
127+
106128
# --- Verify sounds are installed ---
107129
echo ""
108130
for pack in $PACKS; do
@@ -220,4 +242,9 @@ else
220242
echo "Uninstall: bash $INSTALL_DIR/uninstall.sh"
221243
fi
222244
echo ""
245+
echo "Quick controls:"
246+
echo " /peon-ping-toggle — toggle sounds in Claude Code"
247+
echo " peon --toggle — toggle sounds from any terminal"
248+
echo " peon --status — check if sounds are paused"
249+
echo ""
223250
echo "Ready to work!"

peon.sh

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,25 @@ PEON_DIR="${CLAUDE_PEON_DIR:-$HOME/.claude/hooks/peon-ping}"
77
CONFIG="$PEON_DIR/config.json"
88
STATE="$PEON_DIR/.state.json"
99

10+
# --- CLI subcommands (must come before INPUT=$(cat) which blocks on stdin) ---
11+
PAUSED_FILE="$PEON_DIR/.paused"
12+
case "${1:-}" in
13+
--pause) touch "$PAUSED_FILE"; echo "peon-ping: sounds paused"; exit 0 ;;
14+
--resume) rm -f "$PAUSED_FILE"; echo "peon-ping: sounds resumed"; exit 0 ;;
15+
--toggle)
16+
if [ -f "$PAUSED_FILE" ]; then rm -f "$PAUSED_FILE"; echo "peon-ping: sounds resumed"
17+
else touch "$PAUSED_FILE"; echo "peon-ping: sounds paused"; fi
18+
exit 0 ;;
19+
--status)
20+
[ -f "$PAUSED_FILE" ] && echo "peon-ping: paused" || echo "peon-ping: active"
21+
exit 0 ;;
22+
--help|-h)
23+
echo "Usage: peon --pause | --resume | --toggle | --status"; exit 0 ;;
24+
--*)
25+
echo "Unknown option: $1" >&2
26+
echo "Usage: peon --pause | --resume | --toggle | --status" >&2; exit 1 ;;
27+
esac
28+
1029
INPUT=$(cat)
1130

1231
# Debug log (comment out for quiet operation)
@@ -31,6 +50,9 @@ for cat in ['greeting','acknowledge','complete','error','permission','resource_l
3150

3251
[ "$ENABLED" = "false" ] && exit 0
3352

53+
PAUSED=false
54+
[ -f "$PEON_DIR/.paused" ] && PAUSED=true
55+
3456
# --- Parse event fields (shlex.quote prevents shell injection) ---
3557
eval "$(/usr/bin/python3 -c "
3658
import sys, json, shlex
@@ -111,6 +133,11 @@ if [ "$EVENT" = "SessionStart" ] && [ -f "$PEON_DIR/.update_available" ]; then
111133
fi
112134
fi
113135

136+
# --- Show pause status on SessionStart ---
137+
if [ "$EVENT" = "SessionStart" ] && [ "$PAUSED" = "true" ]; then
138+
echo "peon-ping: sounds paused — run 'peon --resume' or '/peon-ping-toggle' to unpause" >&2
139+
fi
140+
114141
# --- Check annoyed state (rapid prompts) ---
115142
check_annoyed() {
116143
/usr/bin/python3 -c "
@@ -243,15 +270,15 @@ if [ -n "$TITLE" ]; then
243270
fi
244271

245272
# --- Play sound ---
246-
if [ -n "$CATEGORY" ]; then
273+
if [ -n "$CATEGORY" ] && [ "$PAUSED" != "true" ]; then
247274
SOUND_FILE=$(pick_sound "$CATEGORY")
248275
if [ -n "$SOUND_FILE" ] && [ -f "$SOUND_FILE" ]; then
249276
nohup afplay -v "$VOLUME" "$SOUND_FILE" >/dev/null 2>&1 &
250277
fi
251278
fi
252279

253280
# --- Smart notification: only when terminal is NOT frontmost ---
254-
if [ -n "$NOTIFY" ]; then
281+
if [ -n "$NOTIFY" ] && [ "$PAUSED" != "true" ]; then
255282
FRONTMOST=$(osascript -e 'tell application "System Events" to get name of first process whose frontmost is true' 2>/dev/null)
256283
case "$FRONTMOST" in
257284
Terminal|iTerm2|Warp|Alacritty|kitty|WezTerm|Ghostty) ;; # terminal is focused, skip notification

skills/peon-ping-toggle/SKILL.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
---
2+
name: peon-ping-toggle
3+
description: Toggle peon-ping sound notifications on/off. Use when user wants to mute, unmute, pause, or resume peon sounds during a Claude Code session.
4+
user_invocable: true
5+
---
6+
7+
# peon-ping-toggle
8+
9+
Toggle peon-ping sounds on or off.
10+
11+
Run the following command using the Bash tool:
12+
13+
```bash
14+
bash ~/.claude/hooks/peon-ping/peon.sh --toggle
15+
```
16+
17+
Report the output to the user. The command will print either:
18+
- `peon-ping: sounds paused` — sounds are now muted
19+
- `peon-ping: sounds resumed` — sounds are now active

tests/peon.bats

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,3 +256,71 @@ JSON
256256
log_line=$(tail -1 "$TEST_DIR/afplay.log")
257257
[[ "$log_line" == *"-v 0.3"* ]]
258258
}
259+
260+
# ============================================================
261+
# Pause / mute feature
262+
# ============================================================
263+
264+
@test "--toggle creates .paused file and prints paused message" {
265+
run bash "$PEON_SH" --toggle
266+
[ "$status" -eq 0 ]
267+
[[ "$output" == *"sounds paused"* ]]
268+
[ -f "$TEST_DIR/.paused" ]
269+
}
270+
271+
@test "--toggle removes .paused file when already paused" {
272+
touch "$TEST_DIR/.paused"
273+
run bash "$PEON_SH" --toggle
274+
[ "$status" -eq 0 ]
275+
[[ "$output" == *"sounds resumed"* ]]
276+
[ ! -f "$TEST_DIR/.paused" ]
277+
}
278+
279+
@test "--pause creates .paused file" {
280+
run bash "$PEON_SH" --pause
281+
[ "$status" -eq 0 ]
282+
[[ "$output" == *"sounds paused"* ]]
283+
[ -f "$TEST_DIR/.paused" ]
284+
}
285+
286+
@test "--resume removes .paused file" {
287+
touch "$TEST_DIR/.paused"
288+
run bash "$PEON_SH" --resume
289+
[ "$status" -eq 0 ]
290+
[[ "$output" == *"sounds resumed"* ]]
291+
[ ! -f "$TEST_DIR/.paused" ]
292+
}
293+
294+
@test "--status reports paused when .paused exists" {
295+
touch "$TEST_DIR/.paused"
296+
run bash "$PEON_SH" --status
297+
[ "$status" -eq 0 ]
298+
[[ "$output" == *"paused"* ]]
299+
}
300+
301+
@test "--status reports active when not paused" {
302+
rm -f "$TEST_DIR/.paused"
303+
run bash "$PEON_SH" --status
304+
[ "$status" -eq 0 ]
305+
[[ "$output" == *"active"* ]]
306+
}
307+
308+
@test "paused file suppresses sound on SessionStart" {
309+
touch "$TEST_DIR/.paused"
310+
run_peon '{"hook_event_name":"SessionStart","cwd":"/tmp/myproject","session_id":"s1","permission_mode":"default"}'
311+
[ "$PEON_EXIT" -eq 0 ]
312+
! afplay_was_called
313+
}
314+
315+
@test "paused SessionStart shows stderr status line" {
316+
touch "$TEST_DIR/.paused"
317+
run_peon '{"hook_event_name":"SessionStart","cwd":"/tmp/myproject","session_id":"s1","permission_mode":"default"}'
318+
[[ "$PEON_STDERR" == *"sounds paused"* ]]
319+
}
320+
321+
@test "paused file suppresses notification on permission_prompt" {
322+
touch "$TEST_DIR/.paused"
323+
run_peon '{"hook_event_name":"Notification","notification_type":"permission_prompt","cwd":"/tmp/myproject","session_id":"s1","permission_mode":"default"}'
324+
[ "$PEON_EXIT" -eq 0 ]
325+
! afplay_was_called
326+
}

0 commit comments

Comments
 (0)