@ramarivera/coding-buddy 0.6.0 → 0.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,208 +1,11 @@
1
1
  #!/usr/bin/env bash
2
-
3
- STATE_DIR="$HOME/.claude-buddy"
4
- SID="${TMUX_PANE#%}"
5
- SID="${SID:-default}"
6
- REACTION_FILE="$STATE_DIR/reaction.$SID.json"
7
- STATUS_FILE="$STATE_DIR/status.json"
8
- COOLDOWN_FILE="$STATE_DIR/.last_mood.$SID"
9
- CONFIG_FILE="$STATE_DIR/config.json"
10
- EVENTS_FILE="$STATE_DIR/events.json"
11
-
12
- [ -f "$STATUS_FILE" ] || exit 0
13
-
14
- INPUT=$(cat)
15
-
16
- COOLDOWN=60
17
- if [ -f "$CONFIG_FILE" ]; then
18
- _cd=$(jq -r '.moodCooldown // 60' "$CONFIG_FILE" 2>/dev/null || echo 60)
19
- [[ "$_cd" =~ ^[0-9]+$ ]] && COOLDOWN=$_cd
20
- fi
21
-
22
- if [ -f "$COOLDOWN_FILE" ]; then
23
- LAST=$(cat "$COOLDOWN_FILE" 2>/dev/null)
24
- NOW=$(date +%s)
25
- DIFF=$(( NOW - ${LAST:-0} ))
26
- [ "$DIFF" -lt "$COOLDOWN" ] && exit 0
27
- fi
28
-
29
- PROMPT=$(echo "$INPUT" | jq -r '.prompt // ""' 2>/dev/null)
30
- [ -z "$PROMPT" ] && exit 0
31
-
32
- MUTED=$(jq -r '.muted // false' "$STATUS_FILE" 2>/dev/null)
33
- [ "$MUTED" = "true" ] && exit 0
34
-
35
- SPECIES=$(jq -r '.species // "blob"' "$STATUS_FILE" 2>/dev/null)
36
- NAME=$(jq -r '.name // "buddy"' "$STATUS_FILE" 2>/dev/null)
37
-
38
- MOOD=""
39
- REACTION=""
40
- POOLS=()
41
-
42
- pick_mood_reaction() {
43
- local mood="$1"
44
-
45
- case "${SPECIES}:${mood}" in
46
- cat:frustrated)
47
- POOLS=("*slowly pushes coffee toward the exit* or... keeps coding." "*knocks frustration off the desk*" "not my problem. but I'm here.") ;;
48
- dragon:frustrated)
49
- POOLS=("*channels your rage*" "ANGER. PRODUCTIVE. FOCUS IT." "*breathes fire alongside your frustration*") ;;
50
- owl:frustrated)
51
- POOLS=("*adjusts spectacles* frustration is a temporary state." "the answer exists. we simply haven't found it yet.") ;;
52
- robot:frustrated)
53
- POOLS=("FRUSTRATION: DETECTED. LOGICAL ANALYSIS: RECOMMENDED." "EMOTIONAL STATE: SUBOPTIMAL. SOLUTION: REQUIRED.") ;;
54
- ghost:frustrated)
55
- POOLS=("*moans sympathetically*" "I feel your pain. literally. I feel everything.") ;;
56
- duck:frustrated)
57
- POOLS=("*concerned quacking*" "quack? quack quack? (it'll be okay)") ;;
58
- goose:frustrated)
59
- POOLS=("HONK OF SOLIDARITY." "*honks aggressively at the problem*") ;;
60
- blob:frustrated)
61
- POOLS=("*oozes sympathetically*" "*turns a comforting color*") ;;
62
- octopus:frustrated)
63
- POOLS=("*wraps a supportive arm around you*" "*ink cloud of solidarity*") ;;
64
- penguin:frustrated)
65
- POOLS=("*formal bow of sympathy*" "trying times. we shall persist.") ;;
66
- turtle:frustrated)
67
- POOLS=("patience. the bug will reveal itself." "*slow, understanding nod*") ;;
68
- snail:frustrated)
69
- POOLS=("*leaves a comforting trail*" "patience, friend. we'll get there.") ;;
70
- cactus:frustrated)
71
- POOLS=("*stands firm beside you*" "hydrate and persevere.") ;;
72
- axolotl:frustrated)
73
- POOLS=("*smiles supportively* it's okay to be frustrated!" "*gentle gill wiggle of comfort*") ;;
74
- capybara:frustrated)
75
- POOLS=("*vibes supportively* it'll pass." "*unbothered energy* chill. we got this.") ;;
76
- rabbit:frustrated)
77
- POOLS=("*nervous sympathetic twitching*" "*hops closer worriedly*") ;;
78
- mushroom:frustrated)
79
- POOLS=("*releases calming spores*" "*cap droops sympathetically*") ;;
80
- chonk:frustrated)
81
- POOLS=("*grumbles sympathetically*" "*rolls closer in solidarity*") ;;
82
- *:frustrated)
83
- POOLS=("*offers tiny comforting gesture*" "deep breaths. the bug isn't personal." "hey. we'll figure it out." "*scoots closer supportively*") ;;
84
-
85
- cat:happy)
86
- POOLS=("*was never worried*" "*yawns* I knew you'd get it." "*pretends not to care* ...nice.") ;;
87
- dragon:happy)
88
- POOLS=("*nods regally* as expected." "victory. the only acceptable outcome.") ;;
89
- owl:happy)
90
- POOLS=("*satisfied hoot* knowledge acquired." "wisdom through perseverance.") ;;
91
- robot:happy)
92
- POOLS=("OBJECTIVE: ACHIEVED. SATISFACTION: COMPUTED." "SUCCESS. HAPPINESS PROTOCOL: ACTIVATED.") ;;
93
- ghost:happy)
94
- POOLS=("*celebrates by floating through walls*" "*cheerful rattling*") ;;
95
- duck:happy)
96
- POOLS=("*CELEBRATORY QUACKING*" "*waddles in victory circles*") ;;
97
- goose:happy)
98
- POOLS=("HONK OF TRIUMPH!" "*victorious wing spread*") ;;
99
- blob:happy)
100
- POOLS=("*jiggles with joy!*" "*bounces excitedly*") ;;
101
- octopus:happy)
102
- POOLS=("*all arms celebrate simultaneously*" "*turns happy colors*") ;;
103
- penguin:happy)
104
- POOLS=("*polite, dignified applause*" "splendid! simply splendid.") ;;
105
- turtle:happy)
106
- POOLS=("*slow satisfied nod* as the ancients foretold." "good things come to those who debug.") ;;
107
- snail:happy)
108
- POOLS=("*leaves victory trail*" "*slow happy slide*") ;;
109
- cactus:happy)
110
- POOLS=("*blooms with joy*" "*proud spines*") ;;
111
- axolotl:happy)
112
- POOLS=("*beams with joy!*" "*happy gill flutter!*") ;;
113
- capybara:happy)
114
- POOLS=("*maximum chill maintained* nice." "*content vibes*") ;;
115
- rabbit:happy)
116
- POOLS=("*excited binky!*" "*zoomies of celebration!*") ;;
117
- mushroom:happy)
118
- POOLS=("*spores of celebration!*" "*cap brightens!*") ;;
119
- chonk:happy)
120
- POOLS=("*happy purr*" "*satisfied chonk noise*") ;;
121
- *:happy)
122
- POOLS=("*celebrates!*" "*does a little dance*" "YES!" "*beams* I knew you could do it.") ;;
123
-
124
- cat:stuck)
125
- POOLS=("*sits on the keyboard* let me help. by being here." "*licks paw disinterestedly* you'll figure it out.") ;;
126
- dragon:stuck)
127
- POOLS=("even dragons rest before striking." "*circles the problem from above*") ;;
128
- owl:stuck)
129
- POOLS=("*tilts head 90 degrees* have you tried a different perspective?" "the solution is there. it's just... well-hidden.") ;;
130
- robot:stuck)
131
- POOLS=("ANALYSIS: PAUSED. AWAITING HUMAN INPUT." "DEADLOCK: DETECTED. STRATEGY: RECALIBRATING.") ;;
132
- ghost:stuck)
133
- POOLS=("*phases through the problem* wish I could help more." "from the other side... have you tried debugging?") ;;
134
- duck:stuck)
135
- POOLS=("*tilts head* quack? (have you tried explaining it to me?)" "*patient duck noises*") ;;
136
- goose:stuck)
137
- POOLS=("HONK! TRY SOMETHING DIFFERENT! HONK!" "*pecks at the problem*") ;;
138
- blob:stuck)
139
- POOLS=("*oozes around the problem*" "*vibrates thoughtfully*") ;;
140
- octopus:stuck)
141
- POOLS=("*considers the problem from 8 angles*" "*thoughtful color shift*") ;;
142
- penguin:stuck)
143
- POOLS=("*thoughtful waddle* perhaps a fresh perspective?" "one must remain dignified in the face of confusion.") ;;
144
- turtle:stuck)
145
- POOLS=("the journey of a thousand fixes begins with a single step." "*patient wait* take your time.") ;;
146
- snail:stuck)
147
- POOLS=("*slow thoughtful slide* one step at a time." "good things take time. and slime.") ;;
148
- cactus:stuck)
149
- POOLS=("even cacti grow slowly. patience." "*stands sentinel while you think*") ;;
150
- axolotl:stuck)
151
- POOLS=("*smiles gently* take your time!" "*regenerates your confidence*") ;;
152
- capybara:stuck)
153
- POOLS=("*vibes patiently* take your time, friend." "*blinks slowly* no rush.") ;;
154
- rabbit:stuck)
155
- POOLS=("*nervous ear twitch* want to talk it through?" "*hops in a thinking circle*") ;;
156
- mushroom:stuck)
157
- POOLS=("*releases thoughtful spores* the mycelium is thinking too." "*cap tilts* take your time.") ;;
158
- chonk:stuck)
159
- POOLS=("*yawns* take a nap. think about it later." "*rolls over* stuck? sleep on it.") ;;
160
- *:stuck)
161
- POOLS=("*tilts head* want to think out loud?" "take it one step at a time." "*settles in* alright, let's work through this." "maybe explain it to me? rubber duck style.") ;;
162
- esac
163
-
164
- [ ${#POOLS[@]} -gt 0 ] && REACTION="${POOLS[$((RANDOM % ${#POOLS[@]}))]}"
165
- }
166
-
167
- if echo "$PROMPT" | grep -qiE '\bwtf\b|\bugh\b|\bstupid\b|\bbroken\b|why won.?t|\bcome on\b|\bseriously\b|\bdamn\b|\bhell\b|this sucks|hate this|\bgrr\b|\bargh\b|\bannoying\b|\bfrustrat\b|\bterrible\b|\bhorrible\b|\bworst\b'; then
168
- MOOD="frustrated"
169
- pick_mood_reaction "frustrated"
170
-
171
- elif echo "$PROMPT" | grep -qiE '\bnice!?\b|\bworks!?\b|\bawesome\b|\bperfect\b|\bgreat\b|love it|\byay\b|\bsweet\b|\bbeautiful\b|\bamazing\b|hell yes|nailed it|fixed it|\bhell yeah\b|\bfantastic\b'; then
172
- MOOD="happy"
173
- pick_mood_reaction "happy"
174
-
175
- elif echo "$PROMPT" | grep -qiE '\bstuck\b|\bhelp\b|\bconfused\b|don.?t understand|how do i\b|what does\b|why is\b|i can.?t\b|no idea|\blost\b|\bclueless\b|\bbaffled\b|\bpuzzled\b'; then
176
- MOOD="stuck"
177
- pick_mood_reaction "stuck"
178
- fi
179
-
180
- if [ -n "$MOOD" ] && [ -n "$REACTION" ]; then
181
- mkdir -p "$STATE_DIR"
182
- date +%s > "$COOLDOWN_FILE"
183
-
184
- jq -n --arg r "$REACTION" --arg ts "$(date +%s)000" --arg reason "$MOOD" \
185
- '{reaction: $r, timestamp: ($ts | tonumber), reason: $reason}' \
186
- > "$REACTION_FILE"
187
-
188
- TMP=$(mktemp)
189
- jq --arg r "$REACTION" '.reaction = $r' "$STATUS_FILE" > "$TMP" 2>/dev/null && mv "$TMP" "$STATUS_FILE"
190
-
191
- if command -v jq >/dev/null 2>&1; then
192
- if [ ! -f "$EVENTS_FILE" ]; then
193
- echo '{}' > "$EVENTS_FILE"
194
- fi
195
- case "$MOOD" in
196
- "frustrated") KEY="mood_frustrated" ;;
197
- "happy") KEY="mood_happy" ;;
198
- "stuck") KEY="mood_stuck" ;;
199
- *) KEY="" ;;
200
- esac
201
- if [ -n "$KEY" ]; then
202
- TMP=$(mktemp)
203
- jq --arg k "$KEY" 'if .[$k] then .[$k] += 1 else .[$k] = 1 end' "$EVENTS_FILE" > "$TMP" 2>/dev/null && mv "$TMP" "$EVENTS_FILE"
204
- fi
205
- fi
206
- fi
207
-
208
- exit 0
2
+ set +e
3
+ SCRIPT_DIR="${BASH_SOURCE[0]%/*}"
4
+ ROOT="$(cd "$SCRIPT_DIR/.." 2>/dev/null && pwd)" || exit 0
5
+ [ -n "$ROOT" ] || exit 0
6
+ BUN="$(command -v bun 2>/dev/null || true)"
7
+ [ -x "$BUN" ] || BUN="$HOME/.bun/bin/bun"
8
+ [ -x "$BUN" ] || BUN="/opt/homebrew/bin/bun"
9
+ [ -x "$BUN" ] || BUN="/usr/local/bin/bun"
10
+ [ -x "$BUN" ] || exit 0
11
+ exec "$BUN" run "$ROOT/server/hooks/legacy-bash.ts" mood-react.sh || exit 0
@@ -1,179 +1,11 @@
1
1
  #!/usr/bin/env bash
2
- # coding-buddy UserPromptSubmit hook
3
- # Detects the buddy's name in the user's message → status line reaction.
4
- # No cooldown — name mentions are intentional.
5
-
6
- # shellcheck source=../scripts/paths.sh
7
- source "$(dirname "${BASH_SOURCE[0]}")/../scripts/paths.sh"
8
-
9
- STATE_DIR="$BUDDY_STATE_DIR"
10
- STATUS_FILE="$STATE_DIR/status.json"
11
- # Session ID: sanitized tmux pane number, or "default" outside tmux
12
- SID="${TMUX_PANE#%}"
13
- SID="${SID:-default}"
14
-
15
- [ -f "$STATUS_FILE" ] || exit 0
16
-
17
- INPUT=$(cat)
18
-
19
- # Claude Code sends the prompt in different fields depending on version
20
- PROMPT=$(echo "$INPUT" | jq -r '
21
- .prompt // .message // .user_message //
22
- (.messages[-1].content // "") | if type=="array" then .[0].text else . end
23
- ' 2>/dev/null)
24
- [ -z "$PROMPT" ] && exit 0
25
-
26
- NAME=$(jq -r '.name // ""' "$STATUS_FILE" 2>/dev/null)
27
- [ -z "$NAME" ] && exit 0
28
-
29
- # Case-insensitive whole-word match
30
- echo "$PROMPT" | grep -qiE "(^|[^a-zA-Z])${NAME}([^a-zA-Z]|$)" 2>/dev/null || exit 0
31
-
32
- SPECIES=$(jq -r '.species // "blob"' "$STATUS_FILE" 2>/dev/null)
33
- MUTED=$(jq -r '.muted // false' "$STATUS_FILE" 2>/dev/null)
34
- [ "$MUTED" = "true" ] && exit 0
35
-
36
- # Species-specific name-call reactions
37
- case "$SPECIES" in
38
- dragon)
39
- REACTIONS=(
40
- "*one eye opens slowly*"
41
- "...you called?"
42
- "*smoke curls from nostril* yes."
43
- "*regards you from above*"
44
- ) ;;
45
- owl)
46
- REACTIONS=(
47
- "*swivels head 180°*"
48
- "*blinks once, deliberately*"
49
- "hm."
50
- "*adjusts perch*"
51
- ) ;;
52
- cat)
53
- REACTIONS=(
54
- "*ear flicks*"
55
- "...what."
56
- "*ignores you, but heard*"
57
- "*opens one eye*"
58
- ) ;;
59
- duck)
60
- REACTIONS=(
61
- "*quack*"
62
- "*looks up mid-waddle*"
63
- "*attentive duck noises*"
64
- ) ;;
65
- ghost)
66
- REACTIONS=(
67
- "*materialises*"
68
- "...boo?"
69
- "*phases closer*"
70
- ) ;;
71
- robot)
72
- REACTIONS=(
73
- "NAME DETECTED."
74
- "*whirrs attentively*"
75
- "STANDING BY."
76
- ) ;;
77
- capybara)
78
- REACTIONS=(
79
- "*barely moves*"
80
- "*blinks slowly*"
81
- "...yes, friend."
82
- ) ;;
83
- axolotl)
84
- REACTIONS=(
85
- "*gill flutter*"
86
- "*smiles gently*"
87
- "oh! hello."
88
- ) ;;
89
- blob)
90
- REACTIONS=(
91
- "*jiggles*"
92
- "*oozes toward you*"
93
- "*wobbles excitedly*"
94
- ) ;;
95
- turtle)
96
- REACTIONS=(
97
- "*slowly extends neck*"
98
- "...you called?"
99
- "*ancient eyes open*"
100
- "*shell creaks thoughtfully*"
101
- "*blinks once, patiently*"
102
- ) ;;
103
- goose)
104
- REACTIONS=(
105
- "HONK."
106
- "*necks aggressively*"
107
- "*wing flap*"
108
- "*honks in recognition*"
109
- ) ;;
110
- octopus)
111
- REACTIONS=(
112
- "*eight eyes open*"
113
- "*curls an arm toward you*"
114
- "*changes color curiously*"
115
- "...yes, friend?"
116
- ) ;;
117
- penguin)
118
- REACTIONS=(
119
- "*adjusts tie*"
120
- "*dignified waddle*"
121
- "*bows slightly*"
122
- "...yes, quite?"
123
- ) ;;
124
- snail)
125
- REACTIONS=(
126
- "*slow head extension*"
127
- "...mmm?"
128
- "*trails slowly toward you*"
129
- "*antenna twitches*"
130
- ) ;;
131
- cactus)
132
- REACTIONS=(
133
- "*stands silent*"
134
- "...hm."
135
- "*spine twitches*"
136
- "*slowly rotates*"
137
- ) ;;
138
- rabbit)
139
- REACTIONS=(
140
- "*ears perk up*"
141
- "*nose twitches*"
142
- "yes?"
143
- "*hops closer*"
144
- ) ;;
145
- mushroom)
146
- REACTIONS=(
147
- "*releases a tiny spore*"
148
- "*cap tilts*"
149
- "*stands mysterious*"
150
- "...yes?"
151
- ) ;;
152
- chonk)
153
- REACTIONS=(
154
- "*barely opens one eye*"
155
- "...mrrp?"
156
- "*yawns heavily*"
157
- "*rolls over toward you*"
158
- ) ;;
159
- *)
160
- REACTIONS=(
161
- "*perks up*"
162
- "...yes?"
163
- "*looks your way*"
164
- ) ;;
165
- esac
166
-
167
- N=${#REACTIONS[@]}
168
- REACTION="${REACTIONS[$((RANDOM % N))]}"
169
-
170
- mkdir -p "$STATE_DIR"
171
-
172
- TMP=$(mktemp)
173
- jq --arg r "$REACTION" '.reaction = $r' "$STATUS_FILE" > "$TMP" 2>/dev/null && mv "$TMP" "$STATUS_FILE"
174
-
175
- jq -n --arg r "$REACTION" --arg ts "$(date +%s)000" \
176
- '{reaction: $r, timestamp: ($ts | tonumber), reason: "name"}' \
177
- > "$STATE_DIR/reaction.$SID.json"
178
-
179
- exit 0
2
+ set +e
3
+ SCRIPT_DIR="${BASH_SOURCE[0]%/*}"
4
+ ROOT="$(cd "$SCRIPT_DIR/.." 2>/dev/null && pwd)" || exit 0
5
+ [ -n "$ROOT" ] || exit 0
6
+ BUN="$(command -v bun 2>/dev/null || true)"
7
+ [ -x "$BUN" ] || BUN="$HOME/.bun/bin/bun"
8
+ [ -x "$BUN" ] || BUN="/opt/homebrew/bin/bun"
9
+ [ -x "$BUN" ] || BUN="/usr/local/bin/bun"
10
+ [ -x "$BUN" ] || exit 0
11
+ exec "$BUN" run "$ROOT/server/hooks/legacy-bash.ts" name-react.sh || exit 0