Initial commit
This commit is contained in:
35
hooks/hooks.json
Normal file
35
hooks/hooks.json
Normal file
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"hooks": {
|
||||
"SessionStart": [
|
||||
{
|
||||
"matcher": "startup|resume",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "${CLAUDE_PLUGIN_ROOT}/hooks/session-start.sh"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"matcher": "clear|compact",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "${CLAUDE_PLUGIN_ROOT}/hooks/session-start.sh"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"Stop": [
|
||||
{
|
||||
"matcher": "",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "${CLAUDE_PLUGIN_ROOT}/hooks/stop-hook.sh"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
120
hooks/session-start.sh
Executable file
120
hooks/session-start.sh
Executable file
@@ -0,0 +1,120 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
# Session start hook for beads plugin
|
||||
# Checks bd installation, repo initialization, and injects workflow context
|
||||
|
||||
# Check if bd is installed
|
||||
if ! command -v bd &>/dev/null; then
|
||||
cat <<'EOF'
|
||||
{
|
||||
"hookSpecificOutput": {
|
||||
"hookEventName": "SessionStart",
|
||||
"additionalContext": "<beads-system>\n**Beads (bd) Not Installed**\n\nInstall beads for dependency-aware issue tracking:\nhttps://github.com/steveyegge/beads\n\nFor skill details: Skill tool with \"beads:using-beads\"\n</beads-system>"
|
||||
}
|
||||
}
|
||||
EOF
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Check if beads is initialized in current repo
|
||||
beads_initialized="false"
|
||||
beads_db_path=""
|
||||
info_json=""
|
||||
|
||||
if info_json=$(bd info --json 2>/dev/null); then
|
||||
if echo "$info_json" | grep -q '"database_path"'; then
|
||||
beads_initialized="true"
|
||||
if command -v jq &>/dev/null; then
|
||||
beads_db_path=$(echo "$info_json" | jq -r '.database_path // ""')
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# Build context based on initialization status
|
||||
if [ "$beads_initialized" = "true" ]; then
|
||||
# Get counts using jq if available
|
||||
ready_count="0"
|
||||
in_progress_count="0"
|
||||
|
||||
if command -v jq &>/dev/null; then
|
||||
ready_count=$(bd ready --json 2>/dev/null | jq 'length' || echo "0")
|
||||
in_progress_count=$(bd list --status in_progress --json 2>/dev/null | jq 'length' || echo "0")
|
||||
fi
|
||||
|
||||
# Shorten path for display
|
||||
display_path="$beads_db_path"
|
||||
if [ -n "$beads_db_path" ]; then
|
||||
display_path=$(echo "$beads_db_path" | sed "s|$HOME|~|")
|
||||
fi
|
||||
|
||||
context="<beads-system>
|
||||
**Beads (bd) - Issue Tracking ACTIVE**
|
||||
|
||||
Database: ${display_path}
|
||||
Ready: ${ready_count} | In Progress: ${in_progress_count}
|
||||
|
||||
**START OF SESSION CHECKLIST:**
|
||||
1. Run \`bd ready\` to see what's actionable
|
||||
2. Run \`bd list --status in_progress\` to see claimed work
|
||||
3. Claim work with \`bd update ID --status in_progress\`
|
||||
|
||||
**Quick Commands:**
|
||||
| Action | Command |
|
||||
|--------|---------|
|
||||
| What's ready? | \`bd ready\` |
|
||||
| Start work | \`bd update ID --status in_progress\` |
|
||||
| Create issue | \`bd create \"title\"\` |
|
||||
| Add blocker | \`bd dep add BLOCKED BLOCKER\` |
|
||||
| Finish work | \`bd close ID --reason \"...\"\` |
|
||||
|
||||
**IMPORTANT:** Before ending session, leftover work (TODOs, FIXMEs, review issues) will be captured as beads issues.
|
||||
|
||||
For full workflow: Skill tool with \"beads:using-beads\"
|
||||
</beads-system>"
|
||||
else
|
||||
context="<beads-system>
|
||||
**Beads (bd) - NOT INITIALIZED IN THIS REPO**
|
||||
|
||||
Beads is installed but this repository has no .beads/ directory.
|
||||
|
||||
**ACTION REQUIRED:** Initialize beads for this project:
|
||||
\`\`\`bash
|
||||
bd init # Use directory name as prefix
|
||||
bd init --prefix myapp # Or specify custom prefix
|
||||
\`\`\`
|
||||
|
||||
After initialization:
|
||||
1. \`bd create \"First issue\"\` - Create your first issue
|
||||
2. \`bd ready\` - See what's ready to work on
|
||||
|
||||
**Why initialize?**
|
||||
- Track discovered work as you code
|
||||
- Manage dependencies between tasks
|
||||
- Never lose TODOs, FIXMEs, or review items
|
||||
- AI-friendly workflow with \`bd ready\`
|
||||
|
||||
For full workflow: Skill tool with \"beads:using-beads\"
|
||||
</beads-system>"
|
||||
fi
|
||||
|
||||
# Escape for JSON using jq
|
||||
if command -v jq &>/dev/null; then
|
||||
context_escaped=$(echo "$context" | jq -Rs . | sed 's/^"//;s/"$//')
|
||||
else
|
||||
context_escaped=$(printf '%s' "$context" | \
|
||||
sed 's/\\/\\\\/g' | \
|
||||
sed 's/"/\\"/g' | \
|
||||
sed 's/ /\\t/g' | \
|
||||
sed $'s/\r/\\\\r/g' | \
|
||||
sed 's/\f/\\f/g' | \
|
||||
awk '{printf "%s\\n", $0}')
|
||||
fi
|
||||
|
||||
cat <<EOF
|
||||
{
|
||||
"hookSpecificOutput": {
|
||||
"hookEventName": "SessionStart",
|
||||
"additionalContext": "${context_escaped}"
|
||||
}
|
||||
}
|
||||
EOF
|
||||
104
hooks/stop-hook.sh
Executable file
104
hooks/stop-hook.sh
Executable file
@@ -0,0 +1,104 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
# Stop hook for beads plugin
|
||||
# Prompts Claude to capture leftover work as beads issues before ending session
|
||||
|
||||
# Check if bd is installed
|
||||
if ! command -v bd &>/dev/null; then
|
||||
# bd not installed - no action needed
|
||||
cat <<'EOF'
|
||||
{
|
||||
"decision": "approve",
|
||||
"reason": "beads not installed"
|
||||
}
|
||||
EOF
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Check if beads is initialized
|
||||
if ! bd info --json 2>/dev/null | grep -q '"database_path"'; then
|
||||
# Not initialized - no action needed
|
||||
cat <<'EOF'
|
||||
{
|
||||
"decision": "approve",
|
||||
"reason": "beads not initialized in this repo"
|
||||
}
|
||||
EOF
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Check if checkpoint has been completed
|
||||
# Strategy: If there are open issues OR no uncommitted changes with markers, approve exit
|
||||
OPEN_ISSUES=$(bd status 2>/dev/null | grep -E "Total Issues:|Open:" | head -2 | tail -1 | awk '{print $2}' || echo "0")
|
||||
RECENT_MARKERS=$(git diff --name-only HEAD~5 2>/dev/null | head -20 | xargs grep -c -E "(TODO|FIXME|HACK|XXX):" 2>/dev/null | awk '{sum+=$1} END {print sum}' || echo "0")
|
||||
|
||||
# If we have open issues capturing work, or no markers found, allow exit
|
||||
if [[ "$OPEN_ISSUES" -gt 0 ]] || [[ "$RECENT_MARKERS" -eq 0 ]]; then
|
||||
cat <<'EOF'
|
||||
{
|
||||
"decision": "approve",
|
||||
"reason": "beads checkpoint complete - work captured in issues or no markers found"
|
||||
}
|
||||
EOF
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Beads is active - inject prompt to capture leftover work
|
||||
prompt='**BEADS END-OF-SESSION CHECKPOINT**
|
||||
|
||||
Before ending this session, capture any leftover work as beads issues:
|
||||
|
||||
1. **Search for code markers** in files modified this session:
|
||||
```bash
|
||||
# Find TODOs, FIXMEs, HACKs, XXX in recent files
|
||||
git diff --name-only HEAD~5 2>/dev/null | head -20 | xargs grep -n -E "(TODO|FIXME|HACK|XXX):" 2>/dev/null | head -30
|
||||
```
|
||||
|
||||
2. **Check your TodoWrite list** - any incomplete items should become beads issues
|
||||
|
||||
3. **Review any code review findings** that were flagged but not yet addressed
|
||||
|
||||
4. **Create beads issues** for each piece of leftover work:
|
||||
```bash
|
||||
bd create "TODO: [description from code]" -t task -p 2
|
||||
bd create "FIXME: [description from code]" -t bug -p 1
|
||||
bd create "Code review: [finding]" -t task -p 2
|
||||
```
|
||||
|
||||
5. **Update in-progress issues** - if leaving work incomplete:
|
||||
```bash
|
||||
bd update ISSUE-ID --status open # Release claim if blocked
|
||||
bd comment ISSUE-ID "Session ended - progress: [summary]"
|
||||
```
|
||||
|
||||
6. **Run final status**:
|
||||
```bash
|
||||
bd status
|
||||
```
|
||||
|
||||
If there is NO leftover work (all tasks completed, no TODOs found), you may proceed to end the session.
|
||||
|
||||
**DO NOT** end the session without:
|
||||
- Checking for leftover work markers
|
||||
- Creating issues for any discovered work
|
||||
- Updating any in-progress issues with status'
|
||||
|
||||
# Escape for JSON using jq
|
||||
if command -v jq &>/dev/null; then
|
||||
prompt_escaped=$(echo "$prompt" | jq -Rs . | sed 's/^"//;s/"$//')
|
||||
else
|
||||
prompt_escaped=$(printf '%s' "$prompt" | \
|
||||
sed 's/\\/\\\\/g' | \
|
||||
sed 's/"/\\"/g' | \
|
||||
sed 's/ /\\t/g' | \
|
||||
sed $'s/\r/\\\\r/g' | \
|
||||
sed 's/\f/\\f/g' | \
|
||||
awk '{printf "%s\\n", $0}')
|
||||
fi
|
||||
|
||||
cat <<EOF
|
||||
{
|
||||
"decision": "approve",
|
||||
"reason": "${prompt_escaped}"
|
||||
}
|
||||
EOF
|
||||
Reference in New Issue
Block a user