stravinsky 0.2.40__py3-none-any.whl → 0.3.4__py3-none-any.whl
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.
- mcp_bridge/__init__.py +1 -1
- mcp_bridge/auth/token_refresh.py +130 -0
- mcp_bridge/cli/__init__.py +6 -0
- mcp_bridge/cli/install_hooks.py +1265 -0
- mcp_bridge/cli/session_report.py +585 -0
- mcp_bridge/hooks/HOOKS_SETTINGS.json +175 -0
- mcp_bridge/hooks/README.md +215 -0
- mcp_bridge/hooks/__init__.py +119 -43
- mcp_bridge/hooks/edit_recovery.py +42 -37
- mcp_bridge/hooks/git_noninteractive.py +89 -0
- mcp_bridge/hooks/keyword_detector.py +30 -0
- mcp_bridge/hooks/manager.py +50 -0
- mcp_bridge/hooks/notification_hook.py +103 -0
- mcp_bridge/hooks/parallel_enforcer.py +127 -0
- mcp_bridge/hooks/parallel_execution.py +111 -0
- mcp_bridge/hooks/pre_compact.py +123 -0
- mcp_bridge/hooks/preemptive_compaction.py +81 -7
- mcp_bridge/hooks/rules_injector.py +507 -0
- mcp_bridge/hooks/session_idle.py +116 -0
- mcp_bridge/hooks/session_notifier.py +125 -0
- mcp_bridge/{native_hooks → hooks}/stravinsky_mode.py +51 -16
- mcp_bridge/hooks/subagent_stop.py +98 -0
- mcp_bridge/hooks/task_validator.py +73 -0
- mcp_bridge/hooks/tmux_manager.py +141 -0
- mcp_bridge/hooks/todo_continuation.py +90 -0
- mcp_bridge/hooks/todo_delegation.py +88 -0
- mcp_bridge/hooks/tool_messaging.py +164 -0
- mcp_bridge/hooks/truncator.py +21 -17
- mcp_bridge/notifications.py +151 -0
- mcp_bridge/prompts/__init__.py +3 -1
- mcp_bridge/prompts/dewey.py +30 -20
- mcp_bridge/prompts/explore.py +46 -8
- mcp_bridge/prompts/multimodal.py +24 -3
- mcp_bridge/prompts/planner.py +222 -0
- mcp_bridge/prompts/stravinsky.py +107 -28
- mcp_bridge/server.py +170 -10
- mcp_bridge/server_tools.py +554 -32
- mcp_bridge/tools/agent_manager.py +316 -106
- mcp_bridge/tools/background_tasks.py +2 -1
- mcp_bridge/tools/code_search.py +97 -11
- mcp_bridge/tools/lsp/__init__.py +7 -0
- mcp_bridge/tools/lsp/manager.py +448 -0
- mcp_bridge/tools/lsp/tools.py +637 -150
- mcp_bridge/tools/model_invoke.py +270 -47
- mcp_bridge/tools/semantic_search.py +2492 -0
- mcp_bridge/tools/templates.py +32 -18
- stravinsky-0.3.4.dist-info/METADATA +420 -0
- stravinsky-0.3.4.dist-info/RECORD +79 -0
- stravinsky-0.3.4.dist-info/entry_points.txt +5 -0
- mcp_bridge/native_hooks/edit_recovery.py +0 -46
- mcp_bridge/native_hooks/truncator.py +0 -23
- stravinsky-0.2.40.dist-info/METADATA +0 -204
- stravinsky-0.2.40.dist-info/RECORD +0 -57
- stravinsky-0.2.40.dist-info/entry_points.txt +0 -3
- /mcp_bridge/{native_hooks → hooks}/context.py +0 -0
- {stravinsky-0.2.40.dist-info → stravinsky-0.3.4.dist-info}/WHEEL +0 -0
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
{
|
|
2
|
+
"description": "Stravinsky MCP Hooks Configuration - Copy this to .claude/settings.json",
|
|
3
|
+
"installation_note": "These hooks are bundled with the stravinsky PyPI package. Hook paths should point to the installed package location or .claude/hooks/ if copied locally.",
|
|
4
|
+
|
|
5
|
+
"hooks": {
|
|
6
|
+
"Notification": [
|
|
7
|
+
{
|
|
8
|
+
"matcher": "*",
|
|
9
|
+
"hooks": [
|
|
10
|
+
{
|
|
11
|
+
"type": "command",
|
|
12
|
+
"command": "python3 ~/.claude/hooks/notification_hook.py",
|
|
13
|
+
"description": "Agent spawn notification messages"
|
|
14
|
+
}
|
|
15
|
+
]
|
|
16
|
+
}
|
|
17
|
+
],
|
|
18
|
+
"SubagentStop": [
|
|
19
|
+
{
|
|
20
|
+
"matcher": "*",
|
|
21
|
+
"hooks": [
|
|
22
|
+
{
|
|
23
|
+
"type": "command",
|
|
24
|
+
"command": "python3 ~/.claude/hooks/subagent_stop.py",
|
|
25
|
+
"description": "Agent completion handling and validation"
|
|
26
|
+
}
|
|
27
|
+
]
|
|
28
|
+
}
|
|
29
|
+
],
|
|
30
|
+
"PreCompact": [
|
|
31
|
+
{
|
|
32
|
+
"matcher": "*",
|
|
33
|
+
"hooks": [
|
|
34
|
+
{
|
|
35
|
+
"type": "command",
|
|
36
|
+
"command": "python3 ~/.claude/hooks/pre_compact.py",
|
|
37
|
+
"description": "Context preservation before compaction"
|
|
38
|
+
}
|
|
39
|
+
]
|
|
40
|
+
}
|
|
41
|
+
],
|
|
42
|
+
"PreToolUse": [
|
|
43
|
+
{
|
|
44
|
+
"matcher": "Read,Search,Grep,Bash,Edit,MultiEdit",
|
|
45
|
+
"hooks": [
|
|
46
|
+
{
|
|
47
|
+
"type": "command",
|
|
48
|
+
"command": "python3 ~/.claude/hooks/stravinsky_mode.py",
|
|
49
|
+
"description": "Hard blocking of direct tools in stravinsky mode"
|
|
50
|
+
}
|
|
51
|
+
]
|
|
52
|
+
}
|
|
53
|
+
],
|
|
54
|
+
"UserPromptSubmit": [
|
|
55
|
+
{
|
|
56
|
+
"matcher": "*",
|
|
57
|
+
"hooks": [
|
|
58
|
+
{
|
|
59
|
+
"type": "command",
|
|
60
|
+
"command": "python3 ~/.claude/hooks/parallel_execution.py",
|
|
61
|
+
"description": "Pre-emptive parallel execution enforcement"
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
"type": "command",
|
|
65
|
+
"command": "python3 ~/.claude/hooks/context.py",
|
|
66
|
+
"description": "Auto-inject project context (CLAUDE.md, README.md)"
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
"type": "command",
|
|
70
|
+
"command": "python3 ~/.claude/hooks/todo_continuation.py",
|
|
71
|
+
"description": "Remind about incomplete todos"
|
|
72
|
+
}
|
|
73
|
+
]
|
|
74
|
+
}
|
|
75
|
+
],
|
|
76
|
+
"PostToolUse": [
|
|
77
|
+
{
|
|
78
|
+
"matcher": "*",
|
|
79
|
+
"hooks": [
|
|
80
|
+
{
|
|
81
|
+
"type": "command",
|
|
82
|
+
"command": "python3 ~/.claude/hooks/truncator.py",
|
|
83
|
+
"description": "Truncate long tool responses"
|
|
84
|
+
}
|
|
85
|
+
]
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
"matcher": "mcp__stravinsky__*,mcp__grep-app__*,Task",
|
|
89
|
+
"hooks": [
|
|
90
|
+
{
|
|
91
|
+
"type": "command",
|
|
92
|
+
"command": "python3 ~/.claude/hooks/tool_messaging.py",
|
|
93
|
+
"description": "User-friendly MCP tool messaging"
|
|
94
|
+
}
|
|
95
|
+
]
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
"matcher": "Edit,MultiEdit",
|
|
99
|
+
"hooks": [
|
|
100
|
+
{
|
|
101
|
+
"type": "command",
|
|
102
|
+
"command": "python3 ~/.claude/hooks/edit_recovery.py",
|
|
103
|
+
"description": "Recovery guidance for failed Edit operations"
|
|
104
|
+
}
|
|
105
|
+
]
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
"matcher": "TodoWrite",
|
|
109
|
+
"hooks": [
|
|
110
|
+
{
|
|
111
|
+
"type": "command",
|
|
112
|
+
"command": "python3 ~/.claude/hooks/todo_delegation.py",
|
|
113
|
+
"description": "Parallel execution enforcer after TodoWrite"
|
|
114
|
+
}
|
|
115
|
+
]
|
|
116
|
+
}
|
|
117
|
+
]
|
|
118
|
+
},
|
|
119
|
+
|
|
120
|
+
"usage_instructions": {
|
|
121
|
+
"installation": [
|
|
122
|
+
"1. Copy this file to .claude/settings.json in your project root",
|
|
123
|
+
"2. Ensure hook scripts are available at .claude/hooks/ (copy from package or use symlink)",
|
|
124
|
+
"3. Restart Claude Code or run /reload"
|
|
125
|
+
],
|
|
126
|
+
"hook_paths": {
|
|
127
|
+
"local_copy": "Copy hooks to .claude/hooks/ and use relative paths (as shown above)",
|
|
128
|
+
"package_install": "Use absolute paths to installed package: python -c 'import mcp_bridge; print(mcp_bridge.__path__[0])'/hooks/",
|
|
129
|
+
"development": "For development, symlink: ln -s /path/to/stravinsky/mcp_bridge/hooks .claude/hooks"
|
|
130
|
+
},
|
|
131
|
+
"customization": [
|
|
132
|
+
"Disable individual hooks by removing them from the hooks array",
|
|
133
|
+
"Adjust matchers to change which tools trigger hooks",
|
|
134
|
+
"Add custom hooks by creating new Python scripts"
|
|
135
|
+
]
|
|
136
|
+
},
|
|
137
|
+
|
|
138
|
+
"hook_overview": {
|
|
139
|
+
"execution_control": {
|
|
140
|
+
"parallel_execution.py": "Detects implementation tasks and injects parallel execution instructions before response generation. Activates stravinsky mode on /stravinsky invocation.",
|
|
141
|
+
"stravinsky_mode.py": "Blocks native file tools (Read, Grep, Bash, Edit) when stravinsky mode is active, forcing Task delegation.",
|
|
142
|
+
"todo_delegation.py": "Hard blocks response completion after TodoWrite if 2+ pending items exist without spawning Task agents."
|
|
143
|
+
},
|
|
144
|
+
"context_management": {
|
|
145
|
+
"context.py": "Auto-injects CLAUDE.md, README.md, or AGENTS.md content into prompts for project-specific context.",
|
|
146
|
+
"todo_continuation.py": "Reminds about incomplete in_progress or pending todos before starting new work.",
|
|
147
|
+
"pre_compact.py": "Preserves critical context patterns (ARCHITECTURE, DESIGN DECISION, etc.) before compaction."
|
|
148
|
+
},
|
|
149
|
+
"tool_enhancement": {
|
|
150
|
+
"tool_messaging.py": "Outputs user-friendly messages about which agent/tool was used (e.g., 'delphi:gpt-5.2-medium(\"Analyzing architecture\")').",
|
|
151
|
+
"edit_recovery.py": "Detects Edit tool failures and suggests recovery actions (re-read file, verify exact match).",
|
|
152
|
+
"truncator.py": "Truncates tool responses longer than 30k characters to prevent token overflow."
|
|
153
|
+
},
|
|
154
|
+
"agent_lifecycle": {
|
|
155
|
+
"notification_hook.py": "Outputs spawn messages for agent delegation (e.g., 'spawned explore:gemini-3-flash(\"Find auth code\")').",
|
|
156
|
+
"subagent_stop.py": "Handles subagent completion, validates output, and can block if critical agents fail."
|
|
157
|
+
}
|
|
158
|
+
},
|
|
159
|
+
|
|
160
|
+
"exit_code_reference": {
|
|
161
|
+
"0": "Success - Allow continuation",
|
|
162
|
+
"1": "Warning - Show message but continue",
|
|
163
|
+
"2": "Block - Hard failure (prevents tool execution in PreToolUse, or signals error in PostToolUse)"
|
|
164
|
+
},
|
|
165
|
+
|
|
166
|
+
"state_files": {
|
|
167
|
+
"~/.stravinsky_mode": "Marker file indicating stravinsky orchestrator mode is active (enables hard blocking)",
|
|
168
|
+
"~/.claude/state/compaction.jsonl": "Audit log of context compaction events with preserved items",
|
|
169
|
+
".claude/todo_state.json": "Cached todo state for continuation enforcement"
|
|
170
|
+
},
|
|
171
|
+
|
|
172
|
+
"version": "0.2.63",
|
|
173
|
+
"package": "stravinsky",
|
|
174
|
+
"documentation": "https://github.com/GratefulDave/stravinsky"
|
|
175
|
+
}
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
# Stravinsky Hooks for Claude Code
|
|
2
|
+
|
|
3
|
+
This directory contains 11 production-ready hooks that integrate with Claude Code to enforce parallel execution, stravinsky mode, and advanced workflow patterns.
|
|
4
|
+
|
|
5
|
+
## Quick Start
|
|
6
|
+
|
|
7
|
+
### Option 1: Copy to Local Project
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
# In your Claude Code project root
|
|
11
|
+
mkdir -p .claude/hooks
|
|
12
|
+
cp -r $(python -c "import mcp_bridge; print(mcp_bridge.__path__[0])")/hooks/*.py .claude/hooks/
|
|
13
|
+
cp $(python -c "import mcp_bridge; print(mcp_bridge.__path__[0])")/hooks/HOOKS_SETTINGS.json .claude/settings.json
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
### Option 2: Symlink (Development)
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
# In your Claude Code project root
|
|
20
|
+
mkdir -p .claude
|
|
21
|
+
ln -s $(python -c "import mcp_bridge; print(mcp_bridge.__path__[0])")/hooks .claude/hooks
|
|
22
|
+
cp .claude/hooks/HOOKS_SETTINGS.json .claude/settings.json
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Hook Files (11 Total)
|
|
26
|
+
|
|
27
|
+
### Core Execution (3)
|
|
28
|
+
1. **parallel_execution.py** - UserPromptSubmit hook
|
|
29
|
+
- Detects implementation tasks and injects parallel execution instructions
|
|
30
|
+
- Activates stravinsky mode when `/stravinsky` is invoked
|
|
31
|
+
- Creates `~/.stravinsky_mode` marker file for hard blocking
|
|
32
|
+
|
|
33
|
+
2. **stravinsky_mode.py** - PreToolUse hook
|
|
34
|
+
- Blocks Read, Grep, Bash, Edit, MultiEdit when stravinsky mode is active
|
|
35
|
+
- Forces delegation via Task tool instead
|
|
36
|
+
- Exit code 2 = hard block
|
|
37
|
+
|
|
38
|
+
3. **todo_delegation.py** - PostToolUse hook (after TodoWrite)
|
|
39
|
+
- Enforces parallel Task spawning when 2+ pending todos exist
|
|
40
|
+
- Blocks continuation without Task delegation in stravinsky mode
|
|
41
|
+
- Exit code 2 = hard block if stravinsky mode active
|
|
42
|
+
|
|
43
|
+
### Context Management (3)
|
|
44
|
+
4. **context.py** - UserPromptSubmit hook
|
|
45
|
+
- Auto-injects CLAUDE.md, README.md, or AGENTS.md content
|
|
46
|
+
- Prepends project context to every prompt
|
|
47
|
+
- Reduces need for explicit context requests
|
|
48
|
+
|
|
49
|
+
5. **todo_continuation.py** - UserPromptSubmit hook
|
|
50
|
+
- Reminds about in_progress and pending todos
|
|
51
|
+
- Prevents starting new work when existing todos are incomplete
|
|
52
|
+
- Uses `.claude/todo_state.json` cache
|
|
53
|
+
|
|
54
|
+
6. **pre_compact.py** - PreCompact hook
|
|
55
|
+
- Preserves critical context before compaction (ARCHITECTURE, DESIGN DECISION, etc.)
|
|
56
|
+
- Logs compaction events to `~/.claude/state/compaction.jsonl`
|
|
57
|
+
- Maintains stravinsky mode state across compactions
|
|
58
|
+
|
|
59
|
+
### Tool Enhancement (3)
|
|
60
|
+
7. **tool_messaging.py** - PostToolUse hook
|
|
61
|
+
- User-friendly messages for MCP tools and Task delegations
|
|
62
|
+
- Format: `🎯 delphi:gpt-5.2-medium('Strategic analysis')`
|
|
63
|
+
- Works with mcp__stravinsky__* and mcp__grep-app__* tools
|
|
64
|
+
|
|
65
|
+
8. **edit_recovery.py** - PostToolUse hook (after Edit/MultiEdit)
|
|
66
|
+
- Detects Edit failures (oldString not found, multiple matches, etc.)
|
|
67
|
+
- Suggests recovery: re-read file, verify exact match
|
|
68
|
+
- Appends recovery guidance to error messages
|
|
69
|
+
|
|
70
|
+
9. **truncator.py** - PostToolUse hook (all tools)
|
|
71
|
+
- Truncates responses longer than 30k characters
|
|
72
|
+
- Prevents token overflow and context bloat
|
|
73
|
+
- Adds truncation markers for transparency
|
|
74
|
+
|
|
75
|
+
### Agent Lifecycle (2)
|
|
76
|
+
10. **notification_hook.py** - Notification hook
|
|
77
|
+
- Outputs spawn messages for agent delegations
|
|
78
|
+
- Format: `spawned explore:gemini-3-flash('Find auth code')`
|
|
79
|
+
- Maps agents to their display models
|
|
80
|
+
|
|
81
|
+
11. **subagent_stop.py** - SubagentStop hook
|
|
82
|
+
- Handles subagent completion events
|
|
83
|
+
- Validates output and detects failures
|
|
84
|
+
- Can block completion for critical agents (delphi, code-reviewer, debugger)
|
|
85
|
+
|
|
86
|
+
## Configuration
|
|
87
|
+
|
|
88
|
+
The `HOOKS_SETTINGS.json` file contains the complete hook configuration for `.claude/settings.json`. It includes:
|
|
89
|
+
|
|
90
|
+
- Hook type mappings (UserPromptSubmit, PreToolUse, PostToolUse, etc.)
|
|
91
|
+
- Tool matchers (which tools trigger which hooks)
|
|
92
|
+
- Command paths (python3 .claude/hooks/hookname.py)
|
|
93
|
+
- Descriptions for each hook
|
|
94
|
+
|
|
95
|
+
## Hook Types & Exit Codes
|
|
96
|
+
|
|
97
|
+
### Hook Types
|
|
98
|
+
- **UserPromptSubmit**: Before response generation (can modify prompt)
|
|
99
|
+
- **PreToolUse**: Before tool execution (can block with exit 2)
|
|
100
|
+
- **PostToolUse**: After tool execution (can modify response)
|
|
101
|
+
- **Notification**: On notification events
|
|
102
|
+
- **SubagentStop**: When subagent completes
|
|
103
|
+
- **PreCompact**: Before context compaction
|
|
104
|
+
|
|
105
|
+
### Exit Codes
|
|
106
|
+
- `0` - Success (allow continuation)
|
|
107
|
+
- `1` - Warning (show message but continue)
|
|
108
|
+
- `2` - Block/Error (prevents tool in PreToolUse, signals failure in PostToolUse)
|
|
109
|
+
|
|
110
|
+
## State Files
|
|
111
|
+
|
|
112
|
+
Hooks use these state files:
|
|
113
|
+
|
|
114
|
+
| File | Purpose |
|
|
115
|
+
|------|---------|
|
|
116
|
+
| `~/.stravinsky_mode` | Marker for stravinsky orchestrator mode (enables hard blocking) |
|
|
117
|
+
| `~/.claude/state/compaction.jsonl` | Audit log of context compaction events |
|
|
118
|
+
| `.claude/todo_state.json` | Cached todo state for continuation enforcement |
|
|
119
|
+
|
|
120
|
+
## Testing Hooks
|
|
121
|
+
|
|
122
|
+
Test individual hooks with JSON input:
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
# Test parallel_execution
|
|
126
|
+
echo '{"prompt": "implement feature X"}' | python3 parallel_execution.py
|
|
127
|
+
|
|
128
|
+
# Test stravinsky_mode (should block)
|
|
129
|
+
touch ~/.stravinsky_mode
|
|
130
|
+
echo '{"toolName": "Read", "params": {}}' | python3 stravinsky_mode.py
|
|
131
|
+
echo $? # Should be 2
|
|
132
|
+
|
|
133
|
+
# Test todo_delegation
|
|
134
|
+
echo '{"tool_name": "TodoWrite", "tool_input": {"todos": [{"status": "pending"}, {"status": "pending"}]}}' | python3 todo_delegation.py
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
## Customization
|
|
138
|
+
|
|
139
|
+
To disable a hook:
|
|
140
|
+
1. Open `.claude/settings.json`
|
|
141
|
+
2. Find the hook in the hooks array
|
|
142
|
+
3. Remove or comment out the hook object
|
|
143
|
+
|
|
144
|
+
To modify a hook:
|
|
145
|
+
1. Copy the hook file to your project's `.claude/hooks/`
|
|
146
|
+
2. Edit as needed
|
|
147
|
+
3. Update the command path in `.claude/settings.json`
|
|
148
|
+
|
|
149
|
+
## Environment Variables
|
|
150
|
+
|
|
151
|
+
Hooks receive these from Claude Code:
|
|
152
|
+
- `CLAUDE_CWD` - Current working directory
|
|
153
|
+
- `CLAUDE_TOOL_NAME` - Tool being invoked
|
|
154
|
+
- `CLAUDE_SESSION_ID` - Active session ID
|
|
155
|
+
|
|
156
|
+
## Workflow
|
|
157
|
+
|
|
158
|
+
### Stravinsky Mode Flow
|
|
159
|
+
1. User invokes `/stravinsky`
|
|
160
|
+
2. `parallel_execution.py` detects it and creates `~/.stravinsky_mode`
|
|
161
|
+
3. `stravinsky_mode.py` now blocks Read/Grep/Bash/Edit tools
|
|
162
|
+
4. Claude must use Task tool for delegation
|
|
163
|
+
5. `todo_delegation.py` enforces parallel Task spawning for 2+ pending todos
|
|
164
|
+
|
|
165
|
+
### Normal Flow (No Stravinsky Mode)
|
|
166
|
+
1. User submits prompt
|
|
167
|
+
2. `context.py` injects CLAUDE.md content
|
|
168
|
+
3. `todo_continuation.py` reminds about incomplete todos
|
|
169
|
+
4. `parallel_execution.py` adds parallel execution guidance if implementation task
|
|
170
|
+
5. Claude generates response
|
|
171
|
+
6. `tool_messaging.py` outputs friendly tool messages
|
|
172
|
+
7. `truncator.py` truncates long responses
|
|
173
|
+
|
|
174
|
+
## Troubleshooting
|
|
175
|
+
|
|
176
|
+
### Hooks Not Firing
|
|
177
|
+
- Check `.claude/settings.json` exists with hook configuration
|
|
178
|
+
- Verify hook scripts are executable: `chmod +x .claude/hooks/*.py`
|
|
179
|
+
- Check hook paths are correct (relative to project root)
|
|
180
|
+
- Restart Claude Code: `/reload`
|
|
181
|
+
|
|
182
|
+
### Stravinsky Mode Stuck Active
|
|
183
|
+
- Remove marker file: `rm ~/.stravinsky_mode`
|
|
184
|
+
- Check for orphaned mode files: `ls -la ~/ | grep stravinsky`
|
|
185
|
+
|
|
186
|
+
### Hooks Causing Errors
|
|
187
|
+
- Test hooks individually (see Testing section above)
|
|
188
|
+
- Check Python version: `python3 --version` (requires 3.8+)
|
|
189
|
+
- Review hook stderr output in Claude Code logs
|
|
190
|
+
- Disable problematic hooks temporarily
|
|
191
|
+
|
|
192
|
+
## Integration with Stravinsky MCP
|
|
193
|
+
|
|
194
|
+
These hooks are designed to work seamlessly with the Stravinsky MCP server:
|
|
195
|
+
|
|
196
|
+
- `tool_messaging.py` recognizes `mcp__stravinsky__*` tools
|
|
197
|
+
- `parallel_execution.py` works with `agent_spawn` MCP tool
|
|
198
|
+
- `stravinsky_mode.py` forces use of MCP Task delegation
|
|
199
|
+
- All hooks respect the parallel execution philosophy
|
|
200
|
+
|
|
201
|
+
## Version
|
|
202
|
+
|
|
203
|
+
Version: 0.2.61
|
|
204
|
+
Package: stravinsky
|
|
205
|
+
Repository: https://github.com/GratefulDave/stravinsky
|
|
206
|
+
|
|
207
|
+
## License
|
|
208
|
+
|
|
209
|
+
MIT License - See package LICENSE file
|
|
210
|
+
|
|
211
|
+
## Support
|
|
212
|
+
|
|
213
|
+
For issues or questions:
|
|
214
|
+
- GitHub Issues: https://github.com/GratefulDave/stravinsky/issues
|
|
215
|
+
- Documentation: See CLAUDE.md in package root
|
mcp_bridge/hooks/__init__.py
CHANGED
|
@@ -1,49 +1,125 @@
|
|
|
1
1
|
"""
|
|
2
|
-
Hooks
|
|
3
|
-
|
|
2
|
+
Stravinsky Hooks - Claude Code Integration
|
|
3
|
+
|
|
4
|
+
This package contains all hook files for deep integration with Claude Code.
|
|
5
|
+
Hooks are Python scripts that intercept Claude Code events to enforce
|
|
6
|
+
parallel execution, stravinsky mode, and other workflow patterns.
|
|
7
|
+
|
|
8
|
+
## Available Hooks
|
|
9
|
+
|
|
10
|
+
### Core Execution Hooks
|
|
11
|
+
- `parallel_execution.py` - UserPromptSubmit: Pre-emptive parallel execution enforcement
|
|
12
|
+
- `stravinsky_mode.py` - PreToolUse: Hard blocking of direct tools (Read, Grep, Bash)
|
|
13
|
+
- `todo_delegation.py` - PostToolUse: Parallel execution enforcer after TodoWrite
|
|
14
|
+
|
|
15
|
+
### Context & State Hooks
|
|
16
|
+
- `context.py` - UserPromptSubmit: Auto-inject project context (CLAUDE.md, README.md)
|
|
17
|
+
- `todo_continuation.py` - UserPromptSubmit: Remind about incomplete todos
|
|
18
|
+
- `pre_compact.py` - PreCompact: Context preservation before compaction
|
|
19
|
+
|
|
20
|
+
### Tool Enhancement Hooks
|
|
21
|
+
- `tool_messaging.py` - PostToolUse: User-friendly tool/agent messaging
|
|
22
|
+
- `edit_recovery.py` - PostToolUse: Recovery guidance for failed Edit operations
|
|
23
|
+
- `truncator.py` - PostToolUse: Truncate long tool responses to prevent token overflow
|
|
24
|
+
|
|
25
|
+
### Agent Lifecycle Hooks
|
|
26
|
+
- `notification_hook.py` - Notification: Agent spawn messages
|
|
27
|
+
- `subagent_stop.py` - SubagentStop: Agent completion handling
|
|
28
|
+
|
|
29
|
+
## Installation for Claude Code
|
|
30
|
+
|
|
31
|
+
Copy the HOOKS_SETTINGS.json configuration to your project's .claude/settings.json:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
# From PyPI package location
|
|
35
|
+
cp $(python -c "import mcp_bridge; print(mcp_bridge.__path__[0])")/hooks/HOOKS_SETTINGS.json .claude/settings.json
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Or manually configure in .claude/settings.json (see HOOKS_SETTINGS.json for template).
|
|
39
|
+
|
|
40
|
+
## Hook Types
|
|
41
|
+
|
|
42
|
+
Claude Code supports these hook types:
|
|
43
|
+
- **UserPromptSubmit**: Fires before response generation
|
|
44
|
+
- **PreToolUse**: Fires before tool execution (can block with exit 2)
|
|
45
|
+
- **PostToolUse**: Fires after tool execution
|
|
46
|
+
- **Notification**: Fires on notification events
|
|
47
|
+
- **SubagentStop**: Fires when subagent completes
|
|
48
|
+
- **PreCompact**: Fires before context compaction
|
|
49
|
+
|
|
50
|
+
## Exit Codes
|
|
51
|
+
|
|
52
|
+
- `0` - Success (allow continuation)
|
|
53
|
+
- `1` - Warning (show but continue)
|
|
54
|
+
- `2` - Block (hard failure in stravinsky mode)
|
|
55
|
+
|
|
56
|
+
## Environment Variables
|
|
57
|
+
|
|
58
|
+
Hooks receive these environment variables from Claude Code:
|
|
59
|
+
- `CLAUDE_CWD` - Current working directory
|
|
60
|
+
- `CLAUDE_TOOL_NAME` - Tool being invoked (PreToolUse/PostToolUse)
|
|
61
|
+
- `CLAUDE_SESSION_ID` - Active session ID
|
|
62
|
+
|
|
63
|
+
## State Management
|
|
64
|
+
|
|
65
|
+
Stravinsky mode uses a marker file for state:
|
|
66
|
+
- `~/.stravinsky_mode` - Active when file exists
|
|
67
|
+
- Created by `/stravinsky` skill invocation
|
|
68
|
+
- Enables hard blocking of direct tools
|
|
69
|
+
|
|
70
|
+
## Usage
|
|
71
|
+
|
|
72
|
+
These hooks are automatically installed with the Stravinsky MCP package.
|
|
73
|
+
To enable them in a Claude Code project:
|
|
74
|
+
|
|
75
|
+
1. Copy HOOKS_SETTINGS.json to .claude/settings.json
|
|
76
|
+
2. Adjust hook paths if needed (default assumes installed via PyPI)
|
|
77
|
+
3. Restart Claude Code or reload configuration
|
|
78
|
+
|
|
79
|
+
## Development
|
|
80
|
+
|
|
81
|
+
To test hooks locally:
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
# Test parallel_execution hook
|
|
85
|
+
echo '{"prompt": "implement feature X"}' | python parallel_execution.py
|
|
86
|
+
|
|
87
|
+
# Test stravinsky_mode hook (requires marker file)
|
|
88
|
+
touch ~/.stravinsky_mode
|
|
89
|
+
echo '{"toolName": "Read", "params": {}}' | python stravinsky_mode.py
|
|
90
|
+
echo $? # Should be 2 (blocked)
|
|
91
|
+
rm ~/.stravinsky_mode
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## Package Contents
|
|
4
95
|
"""
|
|
5
96
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
97
|
+
__all__ = [
|
|
98
|
+
# Core execution
|
|
99
|
+
"parallel_execution",
|
|
100
|
+
"stravinsky_mode",
|
|
101
|
+
"todo_delegation",
|
|
102
|
+
# Context & state
|
|
103
|
+
"context",
|
|
104
|
+
"todo_continuation",
|
|
105
|
+
"pre_compact",
|
|
106
|
+
# Tool enhancement
|
|
107
|
+
"tool_messaging",
|
|
108
|
+
"edit_recovery",
|
|
109
|
+
"truncator",
|
|
110
|
+
# Agent lifecycle
|
|
111
|
+
"notification_hook",
|
|
112
|
+
"subagent_stop",
|
|
113
|
+
]
|
|
21
114
|
|
|
22
115
|
|
|
23
116
|
def initialize_hooks():
|
|
24
|
-
"""
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
# Tier 2: Pre-model-invoke (context management)
|
|
35
|
-
manager.register_pre_model_invoke(directory_context_hook)
|
|
36
|
-
manager.register_pre_model_invoke(context_compaction_hook)
|
|
37
|
-
manager.register_pre_model_invoke(context_monitor_hook)
|
|
38
|
-
manager.register_pre_model_invoke(preemptive_compaction_hook)
|
|
39
|
-
manager.register_pre_model_invoke(empty_message_sanitizer_hook)
|
|
40
|
-
|
|
41
|
-
# Tier 3: Pre-model-invoke (performance optimization)
|
|
42
|
-
manager.register_pre_model_invoke(budget_optimizer_hook)
|
|
43
|
-
|
|
44
|
-
# Tier 4: Pre-model-invoke (behavior enforcement)
|
|
45
|
-
manager.register_pre_model_invoke(keyword_detector_hook)
|
|
46
|
-
manager.register_pre_model_invoke(todo_continuation_hook)
|
|
47
|
-
manager.register_pre_model_invoke(auto_slash_command_hook)
|
|
48
|
-
|
|
49
|
-
return manager
|
|
117
|
+
"""Initialize and register all hooks with the HookManager."""
|
|
118
|
+
# Currently hooks are primarily external scripts or lazy-loaded.
|
|
119
|
+
# This entry point allows for future internal hook registration.
|
|
120
|
+
pass
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
__version__ = "0.2.63"
|
|
124
|
+
__author__ = "David Andrews"
|
|
125
|
+
__description__ = "Claude Code hooks for Stravinsky MCP parallel execution"
|
|
@@ -1,41 +1,46 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
"""
|
|
5
|
-
|
|
1
|
+
import os
|
|
2
|
+
import sys
|
|
3
|
+
import json
|
|
6
4
|
import re
|
|
7
|
-
from typing import Any, Dict, Optional
|
|
8
5
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
6
|
+
def main():
|
|
7
|
+
# Claude Code PostToolUse inputs via Environment Variables
|
|
8
|
+
tool_name = os.environ.get("CLAUDE_TOOL_NAME")
|
|
9
|
+
|
|
10
|
+
# We only care about Edit/MultiEdit
|
|
11
|
+
if tool_name not in ["Edit", "MultiEdit"]:
|
|
12
|
+
return
|
|
16
13
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
14
|
+
# Read from stdin (Claude Code passes the tool response via stdin for some hook types,
|
|
15
|
+
# but for PostToolUse it's often better to check the environment variable if available.
|
|
16
|
+
# Actually, the summary says input is a JSON payload.
|
|
17
|
+
try:
|
|
18
|
+
data = json.load(sys.stdin)
|
|
19
|
+
tool_response = data.get("tool_response", "")
|
|
20
|
+
except Exception:
|
|
21
|
+
# Fallback to direct string if not JSON
|
|
22
|
+
return
|
|
26
23
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
24
|
+
# Error patterns
|
|
25
|
+
error_patterns = [
|
|
26
|
+
r"oldString not found",
|
|
27
|
+
r"oldString matched multiple times",
|
|
28
|
+
r"line numbers out of range"
|
|
29
|
+
]
|
|
30
|
+
|
|
31
|
+
recovery_needed = any(re.search(p, tool_response, re.IGNORECASE) for p in error_patterns)
|
|
32
|
+
|
|
33
|
+
if recovery_needed:
|
|
34
|
+
correction = (
|
|
35
|
+
"\n\n[SYSTEM RECOVERY] It appears the Edit tool failed to find the target string. "
|
|
36
|
+
"Please call 'Read' on the file again to verify the current content, "
|
|
37
|
+
"then ensure your 'oldString' is an EXACT match including all whitespace."
|
|
38
|
+
)
|
|
39
|
+
# For PostToolUse, stdout is captured and appended/replaces output
|
|
40
|
+
print(tool_response + correction)
|
|
41
|
+
else:
|
|
42
|
+
# No change
|
|
43
|
+
print(tool_response)
|
|
44
|
+
|
|
45
|
+
if __name__ == "__main__":
|
|
46
|
+
main()
|