Where does the bug appear (feature/product)?
Cursor IDE
Describe the Bug
Summary
A workspaceOpen hook in the project .cursor/hooks.json never runs. At startup, Cursor fires workspaceOpen while it is reloading the hooks configuration, before the project hooks are registered again. The event is dispatched when no hooks are registered and is never replayed, so the pluginPaths it should return are never applied. Other project hooks in the same file (preToolUse, beforeShellExecution, afterFileEdit) run normally.
Impact
Plugins in a repo can’t be auto-loaded through workspaceOpen + pluginPaths, which is the documented way to enable workspace-scoped plugins or MCP servers automatically. The only fallback is project .cursor/mcp.json entries, which users have to toggle on by hand in every new workspace or worktree.
Likely cause
When the hooks service initializes, it triggers a config reload and dispatches workspaceOpen immediately, without waiting for the reload to finish. Waiting for the reload before dispatching, or replaying workspaceOpen once hooks are loaded, would fix it.
Scope
- This happened in 9 out of 9 workspace windows in one session, with a 20–570 ms gap between the event and the hooks finishing their reload.
- Across roughly 370 hook logs on one machine,
Hook step requested: workspaceOpenappears about 740 times (twice per window), and the hook executed zero times. - Running the hook script by hand with the documented input returns valid
{"pluginPaths":["<absolute path>"]}, so the script isn’t the problem. - User-level hooks (
~/.cursor/hooks.json) load in the same reload, after the event, so moving the hook there wouldn’t help.
Steps to Reproduce
- In any project, create
.cursor/hooks.json:{ "version": 1, "hooks": { "workspaceOpen": [{ "command": ".cursor/hooks/ws-open.sh" }] } } - Create
.cursor/hooks/ws-open.shand make it executable (chmod +x):#!/usr/bin/env bash cat >/dev/null date >> /tmp/ws-open-ran.log echo '{"pluginPaths":[]}' - Open the folder in Cursor, or run Developer: Reload Window.
- Check
/tmp/ws-open-ran.logand Output → Cursor Hooks.
Expected Behavior
The script runs once when the workspace opens, as described in the hooks docs. Any pluginPaths it returns are loaded.
Operating System
MacOS
Version Information
Cursor version: 3.21.18
OS: macOS 26 (Darwin 25.6.0)
Does this stop you from using Cursor
No - Cursor works, but with this issue