[FEATURE] Plugin Lifecycle Hooks: Install and Uninstall
[FEATURE] Plugin Lifecycle Hooks: Install and Uninstall
Summary
Request support for plugin lifecycle hooks to enable automatic setup during installation and cleanup during uninstallation. Currently, Claude Code only supports SessionStart hooks, requiring manual multi-step processes for plugin installation and uninstallation.
Current Limitation
What exists today:
SessionStarthook - Runs at the start of each session- Manual plugin installation with
/install-plugin - Manual plugin uninstallation with
/plugin uninstall
The problem:
- No automatic setup during installation - Plugins cannot initialize configuration, validate dependencies, or perform first-time setup automatically
- No automatic cleanup during uninstallation - Plugins leave behind configuration files, preference keys, and other artifacts that must be manually cleaned up
- Poor user experience - Users must remember to run cleanup commands before uninstalling, and may not know what needs to be cleaned up
Proposed Solution
Add lifecycle hooks for plugin installation and uninstallation:
Installation Hooks
PreInstall- Runs before plugin files are installed- Use case: Validate dependencies, check system requirements, confirm prerequisites
PostInstall- Runs after plugin files are installed- Use case: Initialize configuration, create default settings, display setup instructions
Install- Generic installation hook (if only one is needed)
Uninstallation Hooks
PreUninstall- Runs before plugin files are removed- Use case: Clean up configuration files, remove preference keys, revert system changes
PostUninstall- Runs after plugin files are removed- Use case: Final cleanup, display uninstallation confirmation, remove orphaned files
Uninstall- Generic uninstallation hook (if only one is needed)
Use Cases
Real-World Example: plan-annotations Marketplace
I maintain a Claude Code marketplace with three plugins that enhance plan mode functionality:
plan-annotate-skills- Annotates plans with skillsplan-annotate-agents- Annotates plans with agentsplan-annotate-mcp- Annotates plans with MCP servers
Current Process (Manual):
Installation:
- User runs
/plugin marketplace add WAdamBrooksFS/plan-annotations - Plugins install
- On first session,
SessionStarthook auto-initializes.claude/preferences.jsonwith defaults - This works, but initialization happens on first session, not during installation
Uninstallation:
- User must manually run
/planning-skills-annotations-cleanup - User must manually run
/planning-agents-annotations-cleanup - User must manually run
/planning-mcp-annotations-cleanup - Each cleanup command removes preference keys from
.claude/preferences.json - Finally, user runs
/plugin uninstall plan-annotate-skills@plan-annotations - Repeat for all three plugins
Problems:
- Users must remember cleanup commands exist
- Users must run three separate cleanup commands
- If users forget, orphaned config remains in
.claude/preferences.json - Poor uninstallation experience
With Lifecycle Hooks:
Installation with PostInstall:
- User runs
/plugin marketplace add WAdamBrooksFS/plan-annotations - Plugins install
PostInstallhook runs automatically- Hook initializes
.claude/preferences.jsonimmediately - Hook displays "Setup complete!" message
- User can start using plugins right away
Uninstallation with PreUninstall:
- User runs
/plugin uninstall plan-annotate-skills@plan-annotations PreUninstallhook runs automatically- Hook removes
SKILLS_PLAN_ANNOTATIONSkey from.claude/preferences.json - Hook cleans up plugin-specific configuration
- Plugin files are removed
- Environment is completely clean
Additional Use Cases
PreInstall - Dependency Validation:
# Check if jq is installed (required for bash hooks)
if ! command -v jq &> /dev/null; then
echo "Error: This plugin requires 'jq' for JSON parsing"
echo "Install with: brew install jq (macOS) or apt-get install jq (Linux)"
exit 1
fi
PostInstall - Interactive Setup:
# Prompt user for initial configuration
echo "Would you like to enable skill annotations by default? (y/n)"
# Create initial preferences based on user input
PreUninstall - Safe Cleanup:
# Remove only this plugin's keys from shared config file
# Preserve other plugins' settings
# Delete entire file only if no other plugins exist
PostUninstall - Confirmation:
echo "Plugin successfully uninstalled and all configuration removed"
echo "Your environment is clean"
Proposed Implementation
Hook Registration in hooks.json
{
"hooks": {
"PreInstall": [{
"matcher": "*",
"hooks": [{
"type": "command",
"command": "sh ${CLAUDE_PLUGIN_ROOT}/hooks/pre-install.sh"
}]
}],
"PostInstall": [{
"matcher": "*",
"hooks": [{
"type": "command",
"command": "sh ${CLAUDE_PLUGIN_ROOT}/hooks/post-install.sh"
}]
}],
"PreUninstall": [{
"matcher": "*",
"hooks": [{
"type": "command",
"command": "sh ${CLAUDE_PLUGIN_ROOT}/hooks/pre-uninstall.sh"
}]
}],
"PostUninstall": [{
"matcher": "*",
"hooks": [{
"type": "command",
"command": "sh ${CLAUDE_PLUGIN_ROOT}/hooks/post-uninstall.sh"
}]
}],
"SessionStart": [{
"matcher": "*",
"hooks": [{
"type": "command",
"command": "sh ${CLAUDE_PLUGIN_ROOT}/hooks/session-start.sh"
}]
}]
}
}
Example PreUninstall Hook (Bash)
#!/bin/bash
# hooks/pre-uninstall.sh
PREFS_FILE=".claude/preferences.json"
PLUGIN_KEY="SKILLS_PLAN_ANNOTATIONS"
# Check if preferences file exists
if [ ! -f "$PREFS_FILE" ]; then
exit 0
fi
# Remove this plugin's key
jq "del(.$PLUGIN_KEY)" "$PREFS_FILE" > "$PREFS_FILE.tmp"
mv "$PREFS_FILE.tmp" "$PREFS_FILE"
# If preferences file is now empty, remove it
if [ "$(jq 'length' "$PREFS_FILE")" -eq 0 ]; then
rm "$PREFS_FILE"
fi
echo "✓ Plugin configuration cleaned up"
Example PreUninstall Hook (PowerShell)
# hooks/pre-uninstall.ps1
$PREFS_FILE = ".claude/preferences.json"
$PLUGIN_KEY = "SKILLS_PLAN_ANNOTATIONS"
# Check if preferences file exists
if (Test-Path $PREFS_FILE) {
$prefs = Get-Content $PREFS_FILE -Raw | ConvertFrom-Json
# Remove this plugin's key
$prefs.PSObject.Properties.Remove($PLUGIN_KEY)
# If empty, delete file; otherwise save
if ($prefs.PSObject.Properties.Count -eq 0) {
Remove-Item $PREFS_FILE
} else {
$prefs | ConvertTo-Json | Set-Content $PREFS_FILE
}
Write-Output "✓ Plugin configuration cleaned up"
}
Benefits
For Plugin Authors
- Complete lifecycle control - Handle setup and cleanup automatically
- Better user experience - No manual multi-step processes
- Cleaner environments - Automatic cleanup prevents orphaned config
- Professional polish - Plugins feel more integrated and complete
- Reduced support burden - Users don't need to remember cleanup commands
For Users
- Simple installation - Just install and go
- Simple uninstallation - Just uninstall, cleanup is automatic
- Clean environments - No leftover configuration to track down
- Better trust - Confidence that uninstalling removes everything
For the Ecosystem
- Standardization - Common pattern for plugin lifecycle management
- Quality bar - Encourages plugins to handle cleanup properly
- Best practices - Clear patterns for plugin authors to follow
- Reduced fragmentation - Consistent behavior across all plugins
Technical Considerations
Execution Order
PreInstall→ Install files →PostInstall→SessionStart(first session)PreUninstall→ Remove files →PostUninstall
Error Handling
- If
PreInstallfails (non-zero exit code), abort installation - If
PostInstallfails, warn user but complete installation - If
PreUninstallfails, warn user but proceed with uninstallation - If
PostUninstallfails, log warning (files already removed)
Environment Variables
- Continue using
${CLAUDE_PLUGIN_ROOT}for plugin-relative paths - Provide additional context like
${CLAUDE_PLUGIN_NAME},${CLAUDE_VERSION}
Cross-Platform Support
- Hooks should support same patterns as
SessionStart: - Shell scripts for Linux/macOS/WSL
- PowerShell scripts for Windows
- Platform detection wrappers
Backward Compatibility
- Existing plugins continue working without these hooks
- New hooks are optional
- No breaking changes to existing hook system
Related Issues
- Issue #11226 discusses hook security concerns, showing active interest in hook functionality
- Various feature requests mention plugin extensibility
Alternatives Considered
1. Manual Cleanup Commands (Current Approach)
Pros: Works with current system
Cons: Poor UX, easy to forget, leaves orphaned config
2. SessionStart Detection of Orphaned Config
Pros: Can detect and offer to clean up old config
Cons: Doesn't help during actual uninstallation, creates confusing warnings
3. Bundled Cleanup Scripts
Pros: Users can run standalone cleanup script
Cons: Still manual, users must find and run script
4. Documentation Only
Pros: No code changes needed
Cons: Doesn't solve the problem, users still forget
Conclusion
Plugin lifecycle hooks would significantly improve the Claude Code plugin ecosystem by enabling automatic setup and cleanup. This feature would benefit plugin authors, users, and the overall quality of the plugin marketplace.
The implementation builds on the existing SessionStart hook pattern, making it a natural extension of the current system. The use cases are real (demonstrated by my plan-annotations marketplace), and the benefits are clear.
I hope the Claude Code team will consider adding these lifecycle hooks to provide a more complete and professional plugin experience.
About This Request
Author: Adam Brooks (william.brooks@familysearch.org)
Repository: https://github.com/WAdamBrooksFS/plan-annotations
Real-world usage: Three production plugins currently requiring manual cleanup
Happy to provide more details, examples, or help with implementation if this feature is considered!
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗