Skip to content

Commit d204606

Browse files
committed
Release v0.2.0: Pure Python implementation with critical bug fixes
🐛 Critical Bug Fixes: - Fixed HTTP 403 errors by adding User-Agent headers to webhook requests - Fixed broken uninstall script to handle Python files instead of shell scripts - Fixed broken install script by removing references to non-existent shell scripts ✨ New Features: - Added /user:discord:remove command for project-level removal - Smart hook preservation during removal (preserves non-Discord hooks) - Complete install/uninstall symmetry 🏗️ Architecture Improvements: - Pure Python implementation (removed all .sh files) - Reduced dependencies (only Python 3 required) - Consistent documentation updated for Python-only approach 📁 Repository Changes: - Added: commands/discord/remove.md - Removed: All .sh files from hooks/ directory - Updated: install.sh and uninstall.sh for Python-only operation
1 parent 93b8006 commit d204606

8 files changed

Lines changed: 194 additions & 647 deletions

File tree

CHANGELOG.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,33 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [0.2.0] - 2025-07-07
9+
10+
### 🐛 Critical Bug Fixes
11+
- **Fixed HTTP 403 Forbidden errors** - Added required User-Agent headers to all Python webhook requests
12+
- **Fixed broken uninstall script** - Updated to properly handle Python files instead of shell scripts
13+
- **Fixed broken install script** - Removed references to non-existent shell scripts
14+
15+
### ✨ New Features
16+
- **Project-level removal command** - New `/user:discord:remove` slash command for clean project-specific removal
17+
- **Smart hook preservation** - Removal command preserves non-Discord hooks when cleaning up Discord integration
18+
- **Complete install/uninstall symmetry** - Uninstall script removes exactly what install script adds
19+
20+
### 🏗️ Architecture Improvements
21+
- **Pure Python implementation** - Completely removed all shell scripts (.sh files) from the codebase
22+
- **Reduced dependencies** - Removed `jq` and `curl` requirements, now only needs Python 3
23+
- **Consistent documentation** - Updated all references from shell scripts to Python scripts
24+
25+
### 🧪 Testing Improvements
26+
- **End-to-end validation** - Comprehensive testing of install → use → uninstall → reinstall cycle
27+
- **Webhook validation** - Improved Discord webhook URL testing and validation
28+
- **Error handling** - Better error messages and recovery for common issues
29+
30+
### 📁 Repository Changes
31+
- **Added**: `commands/discord/remove.md` - Project-level removal command
32+
- **Removed**: All `.sh` files from `hooks/` directory
33+
- **Updated**: `install.sh` and `uninstall.sh` for Python-only operation
34+
835
## [0.1.1] - 2025-01-07
936

1037
### Fixed

CLAUDE.md

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,17 @@ chmod +x uninstall.sh
2727
./uninstall.sh
2828
```
2929

30+
### Remove Project Integration
31+
```bash
32+
# Remove Discord integration from current project only
33+
/user:discord:remove
34+
35+
# This removes:
36+
# - .claude/discord-state.json
37+
# - Discord hooks from .claude/settings.json
38+
# - Preserves other hooks and global components
39+
```
40+
3041
### Project Setup (in any project directory)
3142
```bash
3243
# Basic setup
@@ -43,12 +54,15 @@ chmod +x uninstall.sh
4354

4455
# Disable notifications
4556
/user:discord:stop
57+
58+
# Remove project integration
59+
/user:discord:remove
4660
```
4761

4862
## Architecture
4963

5064
### Global Components (`~/.claude/`)
51-
- **Hook Scripts**: `hooks/discord-notify.sh`, `hooks/posttooluse-discord.sh`, `hooks/notification-discord.sh`
65+
- **Hook Scripts**: `hooks/stop-discord.py`, `hooks/posttooluse-discord.py`, `hooks/notification-discord.py`
5266
- **Slash Commands**: `commands/discord/` (setup.md, start.md, stop.md, status.md)
5367
- **No Global Settings**: Global settings.json has no hooks configured
5468

@@ -70,7 +84,7 @@ Projects without `.claude/discord-state.json` receive **no notifications** - thi
7084

7185
## Hook Script Logic
7286

73-
Each hook script (`hooks/discord-notify.sh`, etc.) follows this pattern:
87+
Each Python hook script follows this pattern:
7488
1. Check if `.claude/discord-state.json` exists (exit silently if not)
7589
2. Parse Discord configuration from the state file
7690
3. Verify `"active": true` (exit if false)
@@ -81,9 +95,9 @@ Each hook script (`hooks/discord-notify.sh`, etc.) follows this pattern:
8195
## File Structure Analysis
8296

8397
### Core Hook Scripts
84-
- `hooks/discord-notify.sh`: Main notification handler for Stop/Notification/PostToolUse events
85-
- `hooks/posttooluse-discord.sh`: Specific handler for tool completion events
86-
- `hooks/notification-discord.sh`: Specific handler for input-needed events
98+
- `hooks/stop-discord.py`: Handler for Stop events (session completion)
99+
- `hooks/posttooluse-discord.py`: Handler for tool completion events
100+
- `hooks/notification-discord.py`: Handler for input-needed events
87101

88102
### Slash Commands (Custom Claude Code Commands)
89103
- `commands/discord/setup.md`: Creates project config and hooks
@@ -119,9 +133,9 @@ Required tools:
119133
```json
120134
{
121135
"hooks": {
122-
"Stop": [{"matcher": "", "hooks": [{"type": "command", "command": "$HOME/.claude/hooks/discord-notify.sh"}]}],
123-
"Notification": [{"matcher": "", "hooks": [{"type": "command", "command": "$HOME/.claude/hooks/notification-discord.sh"}]}],
124-
"PostToolUse": [{"matcher": "", "hooks": [{"type": "command", "command": "$HOME/.claude/hooks/posttooluse-discord.sh"}]}]
136+
"Stop": [{"matcher": "", "hooks": [{"type": "command", "command": "$HOME/.claude/hooks/stop-discord.py"}]}],
137+
"Notification": [{"matcher": "", "hooks": [{"type": "command", "command": "$HOME/.claude/hooks/notification-discord.py"}]}],
138+
"PostToolUse": [{"matcher": "", "hooks": [{"type": "command", "command": "$HOME/.claude/hooks/posttooluse-discord.py"}]}]
125139
}
126140
}
127141
```
@@ -131,13 +145,13 @@ Required tools:
131145
### Testing Hook Scripts
132146
```bash
133147
# Test hook manually
134-
echo '{"session_id": "test", "hook_type": "Stop"}' | ~/.claude/hooks/discord-notify.sh
148+
echo '{"session_id": "test", "hook_type": "Stop"}' | python3 ~/.claude/hooks/stop-discord.py
135149

136150
# Check logs
137151
tail -f ~/.claude/discord-notifications.log
138152

139153
# Verify script permissions
140-
ls -la ~/.claude/hooks/discord*.sh
154+
ls -la ~/.claude/hooks/*discord*.py
141155
```
142156

143157
### Testing Slash Commands

commands/discord/remove.md

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
---
2+
description: Remove Discord integration from this project
3+
allowed-tools: Bash(rm:*), Bash(python3:*), Bash(cat:*), Bash(echo:*)
4+
---
5+
6+
! if [ ! -f ".claude/discord-state.json" ]; then
7+
echo "ℹ️ No Discord integration found in this project"
8+
echo ""
9+
echo "Current project: $(basename $(pwd))"
10+
echo "Status: Not configured"
11+
echo ""
12+
echo "To set up Discord integration:"
13+
echo "• /user:discord:setup WEBHOOK_URL - Configure Discord integration"
14+
exit 0
15+
fi
16+
17+
! # Show current configuration
18+
! echo "🗑️ Discord Integration Removal for $(basename $(pwd))"
19+
! echo "=================================================="
20+
! echo ""
21+
22+
! # Get current state
23+
! ACTIVE=$(python3 "$HOME/.claude/commands/discord/read-state.py" .claude/discord-state.json active false)
24+
! PROJECT_NAME=$(python3 "$HOME/.claude/commands/discord/read-state.py" .claude/discord-state.json project_name unknown)
25+
! WEBHOOK_URL=$(python3 "$HOME/.claude/commands/discord/read-state.py" .claude/discord-state.json webhook_url)
26+
27+
! echo "📊 Current Configuration:"
28+
! echo " Project: $PROJECT_NAME"
29+
! echo " Status: $([ "$ACTIVE" = "true" ] && echo "🟢 Active" || echo "🔴 Disabled")"
30+
! echo " Webhook: $(echo "$WEBHOOK_URL" | sed 's/\(.*webhooks\/[0-9]*\).*/\1.../' 2>/dev/null || echo 'Not configured')"
31+
! echo " Hooks: $([ -f ".claude/settings.json" ] && echo "✅ Configured" || echo "❌ Not configured")"
32+
! echo ""
33+
34+
! # Warning and confirmation
35+
! echo "⚠️ WARNING: This will remove Discord integration from this project:"
36+
! echo " • Delete .claude/discord-state.json"
37+
! echo " • Remove Discord hooks from .claude/settings.json"
38+
! echo " • Preserve other hooks and settings"
39+
! echo ""
40+
! echo "Global Discord components (in ~/.claude/) will NOT be affected."
41+
! echo ""
42+
43+
! # Simple confirmation (no interactive read in Claude Code)
44+
! echo "🔄 Proceeding with removal..."
45+
! echo ""
46+
47+
! # Create backup of settings.json
48+
! if [ -f ".claude/settings.json" ]; then
49+
echo "📁 Creating backup of settings.json..."
50+
cp .claude/settings.json .claude/settings.json.backup-$(date +%Y%m%d-%H%M%S)
51+
echo "✅ Backup created"
52+
fi
53+
54+
! # Remove discord-state.json
55+
! if [ -f ".claude/discord-state.json" ]; then
56+
rm -f .claude/discord-state.json
57+
echo "✅ Removed discord-state.json"
58+
fi
59+
60+
! # Remove Discord hooks from settings.json while preserving other hooks
61+
! if [ -f ".claude/settings.json" ]; then
62+
echo "🔧 Removing Discord hooks from settings.json..."
63+
64+
# Use Python to remove only Discord hooks
65+
python3 -c "
66+
import json
67+
import sys
68+
69+
try:
70+
with open('.claude/settings.json', 'r') as f:
71+
settings = json.load(f)
72+
73+
if 'hooks' in settings:
74+
# Remove Discord hooks while preserving others
75+
hooks = settings['hooks']
76+
77+
# Remove Stop hooks that point to Discord
78+
if 'Stop' in hooks:
79+
hooks['Stop'] = [h for h in hooks['Stop'] if not any('discord' in hook.get('command', '') for hook in h.get('hooks', []))]
80+
if not hooks['Stop']:
81+
del hooks['Stop']
82+
83+
# Remove Notification hooks that point to Discord
84+
if 'Notification' in hooks:
85+
hooks['Notification'] = [h for h in hooks['Notification'] if not any('discord' in hook.get('command', '') for hook in h.get('hooks', []))]
86+
if not hooks['Notification']:
87+
del hooks['Notification']
88+
89+
# Remove PostToolUse hooks that point to Discord
90+
if 'PostToolUse' in hooks:
91+
hooks['PostToolUse'] = [h for h in hooks['PostToolUse'] if not any('discord' in hook.get('command', '') for hook in h.get('hooks', []))]
92+
if not hooks['PostToolUse']:
93+
del hooks['PostToolUse']
94+
95+
# Write back the cleaned settings
96+
with open('.claude/settings.json', 'w') as f:
97+
json.dump(settings, f, indent=2)
98+
99+
print('✅ Discord hooks removed from settings.json')
100+
101+
except Exception as e:
102+
print(f'❌ Error updating settings.json: {e}')
103+
sys.exit(1)
104+
"
105+
106+
else
107+
echo "ℹ️ No settings.json file found"
108+
fi
109+
110+
! echo ""
111+
! echo "=================================================="
112+
! echo "✅ Discord integration removal completed!"
113+
! echo "=================================================="
114+
! echo ""
115+
! echo "📊 What was removed:"
116+
! echo " • .claude/discord-state.json (Discord configuration)"
117+
! echo " • Discord hooks from .claude/settings.json"
118+
! echo ""
119+
! echo "📁 What was preserved:"
120+
! echo " • Other hooks in .claude/settings.json"
121+
! echo " • Global Discord components in ~/.claude/"
122+
! echo " • Backup of settings.json created"
123+
! echo ""
124+
! echo "🔄 To re-enable Discord integration:"
125+
! echo " • /user:discord:setup WEBHOOK_URL - Reconfigure"
126+
! echo ""
127+
! echo "🗑️ To completely remove global Discord components:"
128+
! echo " • Run ./uninstall.sh from the claude-discord-integration directory"

0 commit comments

Comments
 (0)