Add config-based close hooks (bd-g4b4)

Implements on_close hooks in .beads/config.yaml for automation and
notifications. Hooks receive issue data via environment variables
(BEAD_ID, BEAD_TITLE, BEAD_TYPE, BEAD_PRIORITY, BEAD_CLOSE_REASON)
and run via sh -c.

Changes:
- internal/config: Add HookEntry type and GetCloseHooks()
- internal/hooks: Add RunConfigCloseHooks() for executing config hooks
- cmd/bd: Call RunConfigCloseHooks after successful close
- docs/CONFIG.md: Document hooks configuration with examples

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Steve Yegge
2025-12-23 13:38:09 -08:00
parent bc0973bfa2
commit c46b1a0bbb
5 changed files with 449 additions and 2 deletions

View File

@@ -104,6 +104,73 @@ external_projects:
gastown: /path/to/gastown
```
### Hooks Configuration
bd supports config-based hooks for automation and notifications. Currently, close hooks are implemented.
#### Close Hooks
Close hooks run after an issue is successfully closed via `bd close`. They execute synchronously but failures are logged as warnings and don't block the close operation.
**Configuration:**
```yaml
# .beads/config.yaml
hooks:
on_close:
- name: show-next
command: bd ready --limit 1
- name: context-check
command: echo "Issue $BEAD_ID closed. Check context if nearing limit."
- command: notify-team.sh # name is optional
```
**Environment Variables:**
Hook commands receive issue data via environment variables:
| Variable | Description |
|----------|-------------|
| `BEAD_ID` | Issue ID (e.g., `bd-abc1`) |
| `BEAD_TITLE` | Issue title |
| `BEAD_TYPE` | Issue type (`task`, `bug`, `feature`, etc.) |
| `BEAD_PRIORITY` | Priority (0-4) |
| `BEAD_CLOSE_REASON` | Close reason if provided |
**Example Use Cases:**
1. **Show next work item:**
```yaml
hooks:
on_close:
- name: next-task
command: bd ready --limit 1
```
2. **Context check reminder:**
```yaml
hooks:
on_close:
- name: context-check
command: |
echo "Issue $BEAD_ID ($BEAD_TITLE) closed."
echo "Priority was P$BEAD_PRIORITY. Reason: $BEAD_CLOSE_REASON"
```
3. **Integration with external tools:**
```yaml
hooks:
on_close:
- name: slack-notify
command: curl -X POST "$SLACK_WEBHOOK" -d "{\"text\":\"Closed: $BEAD_ID - $BEAD_TITLE\"}"
```
**Notes:**
- Hooks have a 10-second timeout
- Hook failures log warnings but don't fail the close operation
- Commands run via `sh -c`, so shell features like pipes and redirects work
- Both script-based hooks (`.beads/hooks/on_close`) and config-based hooks run
### Why Two Systems?
**Tool settings (Viper)** are user preferences: