claude-code-achievements 1.0.0
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.
- package/.claude-plugin/plugin.json +7 -0
- package/README.md +201 -0
- package/bin/config.js +285 -0
- package/bin/install.js +221 -0
- package/commands/achievements-settings.md +63 -0
- package/commands/achievements.md +93 -0
- package/data/achievements.json +168 -0
- package/data/i18n/en.json +94 -0
- package/data/i18n/ko.json +94 -0
- package/hooks/hooks.json +28 -0
- package/hooks/track-achievement.sh +178 -0
- package/hooks/track-stop.sh +44 -0
- package/package.json +38 -0
- package/scripts/init-state.sh +44 -0
- package/scripts/show-achievements.sh +152 -0
- package/scripts/show-notification.sh +145 -0
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# show-notification.sh - Display achievement unlock notification
|
|
3
|
+
# Usage: show-notification.sh <achievement_id>
|
|
4
|
+
|
|
5
|
+
set -e
|
|
6
|
+
|
|
7
|
+
PLUGIN_ROOT="${CLAUDE_PLUGIN_ROOT:-$(dirname "$(dirname "$0")")}"
|
|
8
|
+
STATE_FILE="${HOME}/.claude/achievements/state.json"
|
|
9
|
+
ACHIEVEMENTS_FILE="${PLUGIN_ROOT}/data/achievements.json"
|
|
10
|
+
|
|
11
|
+
ACHIEVEMENT_ID="$1"
|
|
12
|
+
|
|
13
|
+
if [[ -z "${ACHIEVEMENT_ID}" ]]; then
|
|
14
|
+
exit 1
|
|
15
|
+
fi
|
|
16
|
+
|
|
17
|
+
# Get user's language preference
|
|
18
|
+
LANG=$(jq -r '.settings.language // "en"' "${STATE_FILE}" 2>/dev/null || echo "en")
|
|
19
|
+
NOTIFICATIONS_ENABLED=$(jq -r '.settings.notifications // true' "${STATE_FILE}" 2>/dev/null || echo "true")
|
|
20
|
+
NOTIFICATION_STYLE=$(jq -r '.settings.notification_style // "system"' "${STATE_FILE}" 2>/dev/null || echo "system")
|
|
21
|
+
|
|
22
|
+
# Skip if notifications are disabled
|
|
23
|
+
if [[ "${NOTIFICATIONS_ENABLED}" == "false" ]]; then
|
|
24
|
+
exit 0
|
|
25
|
+
fi
|
|
26
|
+
|
|
27
|
+
# Get achievement data
|
|
28
|
+
ICON=$(jq -r ".achievements[\"${ACHIEVEMENT_ID}\"].icon // \"🏆\"" "${ACHIEVEMENTS_FILE}")
|
|
29
|
+
RARITY=$(jq -r ".achievements[\"${ACHIEVEMENT_ID}\"].rarity // \"common\"" "${ACHIEVEMENTS_FILE}")
|
|
30
|
+
|
|
31
|
+
# Get unlock stats
|
|
32
|
+
TOTAL=$(jq '.achievements | length' "${ACHIEVEMENTS_FILE}")
|
|
33
|
+
UNLOCKED=$(jq '.achievements | to_entries | map(select(.value.unlocked == true)) | length' "${STATE_FILE}")
|
|
34
|
+
|
|
35
|
+
# Get localized name
|
|
36
|
+
I18N_FILE="${PLUGIN_ROOT}/data/i18n/${LANG}.json"
|
|
37
|
+
if [[ -f "${I18N_FILE}" ]]; then
|
|
38
|
+
NAME=$(jq -r ".achievements[\"${ACHIEVEMENT_ID}\"].name // empty" "${I18N_FILE}")
|
|
39
|
+
fi
|
|
40
|
+
|
|
41
|
+
# Fall back to default if no translation
|
|
42
|
+
if [[ -z "${NAME}" ]]; then
|
|
43
|
+
NAME=$(jq -r ".achievements[\"${ACHIEVEMENT_ID}\"].name // \"Unknown\"" "${ACHIEVEMENTS_FILE}")
|
|
44
|
+
fi
|
|
45
|
+
|
|
46
|
+
# Rarity display
|
|
47
|
+
get_rarity_label() {
|
|
48
|
+
case "$1" in
|
|
49
|
+
common) echo "Common" ;;
|
|
50
|
+
uncommon) echo "Uncommon" ;;
|
|
51
|
+
rare) echo "Rare" ;;
|
|
52
|
+
epic) echo "Epic" ;;
|
|
53
|
+
legendary) echo "Legendary" ;;
|
|
54
|
+
*) echo "Common" ;;
|
|
55
|
+
esac
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
RARITY_LABEL=$(get_rarity_label "${RARITY}")
|
|
59
|
+
|
|
60
|
+
# Show system notification (cross-platform)
|
|
61
|
+
# Check if system notifications are available
|
|
62
|
+
check_system_notification_available() {
|
|
63
|
+
local OS="$(uname -s)"
|
|
64
|
+
case "${OS}" in
|
|
65
|
+
Darwin)
|
|
66
|
+
# macOS - osascript is always available
|
|
67
|
+
return 0
|
|
68
|
+
;;
|
|
69
|
+
Linux)
|
|
70
|
+
# Linux - check for notify-send
|
|
71
|
+
command -v notify-send &> /dev/null && return 0
|
|
72
|
+
return 1
|
|
73
|
+
;;
|
|
74
|
+
MINGW*|MSYS*|CYGWIN*)
|
|
75
|
+
# Windows - check for powershell
|
|
76
|
+
command -v powershell.exe &> /dev/null && return 0
|
|
77
|
+
return 1
|
|
78
|
+
;;
|
|
79
|
+
*)
|
|
80
|
+
return 1
|
|
81
|
+
;;
|
|
82
|
+
esac
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
show_system_notification() {
|
|
86
|
+
local OS="$(uname -s)"
|
|
87
|
+
local TITLE="Achievement Unlocked!"
|
|
88
|
+
local BODY="${ICON} ${NAME}"
|
|
89
|
+
local SUBTITLE="${UNLOCKED}/${TOTAL} unlocked • ${RARITY_LABEL}"
|
|
90
|
+
|
|
91
|
+
case "${OS}" in
|
|
92
|
+
Darwin)
|
|
93
|
+
# macOS - use osascript
|
|
94
|
+
osascript -e "display notification \"${BODY}\" with title \"${TITLE}\" subtitle \"${SUBTITLE}\"" 2>/dev/null || show_terminal_notification
|
|
95
|
+
;;
|
|
96
|
+
Linux)
|
|
97
|
+
# Linux - use notify-send if available
|
|
98
|
+
if command -v notify-send &> /dev/null; then
|
|
99
|
+
notify-send "${TITLE}" "${BODY} - ${SUBTITLE}" -i dialog-information 2>/dev/null || show_terminal_notification
|
|
100
|
+
else
|
|
101
|
+
show_terminal_notification
|
|
102
|
+
fi
|
|
103
|
+
;;
|
|
104
|
+
MINGW*|MSYS*|CYGWIN*)
|
|
105
|
+
# Windows (Git Bash, MSYS, Cygwin) - use PowerShell toast
|
|
106
|
+
if command -v powershell.exe &> /dev/null; then
|
|
107
|
+
powershell.exe -Command "Add-Type -AssemblyName System.Windows.Forms; [System.Windows.Forms.MessageBox]::Show('${BODY}', '${TITLE}', 'OK', 'Information')" 2>/dev/null || show_terminal_notification
|
|
108
|
+
else
|
|
109
|
+
show_terminal_notification
|
|
110
|
+
fi
|
|
111
|
+
;;
|
|
112
|
+
*)
|
|
113
|
+
show_terminal_notification
|
|
114
|
+
;;
|
|
115
|
+
esac
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
# Show terminal notification
|
|
119
|
+
show_terminal_notification() {
|
|
120
|
+
{
|
|
121
|
+
echo ""
|
|
122
|
+
echo "🎮 Achievement Unlocked!"
|
|
123
|
+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
124
|
+
echo " ${ICON} ${NAME}"
|
|
125
|
+
echo " ${RARITY_LABEL} • ${UNLOCKED}/${TOTAL} unlocked"
|
|
126
|
+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
127
|
+
echo ""
|
|
128
|
+
} >&2
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
# Display notification based on style
|
|
132
|
+
case "${NOTIFICATION_STYLE}" in
|
|
133
|
+
system)
|
|
134
|
+
show_system_notification
|
|
135
|
+
;;
|
|
136
|
+
both)
|
|
137
|
+
show_system_notification
|
|
138
|
+
show_terminal_notification
|
|
139
|
+
;;
|
|
140
|
+
*)
|
|
141
|
+
show_terminal_notification
|
|
142
|
+
;;
|
|
143
|
+
esac
|
|
144
|
+
|
|
145
|
+
exit 0
|