feat: add Cursor hooks support to install command#196
feat: add Cursor hooks support to install command#196imkarrer wants to merge 2 commits intotirth8205:mainfrom
Conversation
Install user-level Cursor hooks (~/.cursor/hooks.json + shell scripts) that mirror the three Claude Code hook behaviors: 1. afterFileEdit: auto-update graph via code-review-graph update --skip-flows 2. sessionStart: show graph status via code-review-graph status 3. beforeShellExecution: detect changes before git commit All hooks fail gracefully (exit 0) since they're user-level and will run for all projects. Hooks are installed when running install/init with --platform cursor or --platform all, unless --no-hooks is passed. New functions in skills.py: - generate_cursor_hooks_config(): returns hooks.json config dict - _cursor_hook_scripts(): returns 3 shell script contents - install_cursor_hooks(): writes config + scripts, merges with existing 18 new tests covering config generation, script content, installation, merge behavior, idempotency, and error handling.
Match MCP behavior: only install Cursor hooks when ~/.cursor exists, consistent with how PLATFORMS['cursor']['detect'] gates MCP config.
|
The Cursor hooks implementation looks correct. The hook scripts properly consume stdin (per Cursor's protocol), fail gracefully with The branch has merge conflicts with One minor note for after rebase: the Once rebased, this is ready to merge. |
Yes that is precisely my intent, thanks for verifying. Since #198 will also trigger merge conflicts, I will let that merge first and then I will resolve all conficts at one time. #198 is ready. |
Summary
~/.cursor/hooks.json+ shell scripts in~/.cursor/hooks/) that mirror all three Claude Code hook behaviors: auto-update graph after file edits, show graph status on session start, and detect changes before git commitsinstall/initwith--platform cursoror--platform all, unless--no-hooksis passedRelated Issues & PRs
--platformfiltering for hooks/skills; this PR respects the sametargetfiltering pattern for Cursor hooksChanges
code_review_graph/skills.pygenerate_cursor_hooks_config()— returns Cursorhooks.jsonconfig dict (version 1) with hooks forafterFileEdit,sessionStart, andbeforeShellExecution_cursor_hook_scripts()— returns 3 shell script contents (crg-update.sh,crg-session-start.sh,crg-pre-commit.sh) that consume stdin per Cursor protocol and emit JSON on stdoutinstall_cursor_hooks()— writes~/.cursor/hooks.json(merging with existing config), creates~/.cursor/hooks/with executable scriptscode_review_graph/cli.pyinstall_cursor_hooks()in_handle_init()when target isallorcursor, gated by--no-hooksloggermodule-level variable for consistent loggingtests/test_skills.pyTestCursorHooksConfig(6 tests): config structure, event types, pathsTestCursorHookScripts(7 tests): script content, shebang, exit codes, commandsTestInstallCursorHooks(5 tests): file creation, executability, merge, idempotency, error handlingHook Behaviors
afterFileEditcrg-update.shcode-review-graph update --skip-flowssessionStartcrg-session-start.shcode-review-graph statusbeforeShellExecution(matcher:^git\s+commit)crg-pre-commit.shcode-review-graph detect-changes --briefTesting
All 48 tests pass (30 existing + 18 new). Ruff and mypy clean.
Checklist (per CONTRIBUTING.md)
feature/cursor-hooksuv run pytest tests/test_skills.py(48/48)ruff checkwith rules E, F, I, N, Wmypy --ignore-missing-imports --no-strict-optional