Project workspaceOpen hook never runs: the event fires during a hooks-config reload, before project hooks are registered

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: workspaceOpen appears 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

  1. In any project, create .cursor/hooks.json:
    {
      "version": 1,
      "hooks": {
        "workspaceOpen": [{ "command": ".cursor/hooks/ws-open.sh" }]
      }
    }
    
  2. Create .cursor/hooks/ws-open.sh and make it executable (chmod +x):
    #!/usr/bin/env bash
    cat >/dev/null
    date >> /tmp/ws-open-ran.log
    echo '{"pluginPaths":[]}'
    
  3. Open the folder in Cursor, or run Developer: Reload Window.
  4. Check /tmp/ws-open-ran.log and 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

The script never runs. The hooks log shows the same sequence in every window:

[T+0.000s] Reloading hooks configuration...
[T+0.082s] Loaded 9 project hook(s) for steps: beforeReadFile, afterFileEdit, afterTabFileEdit, beforeShellExecution, preToolUse, postToolUse, workspaceOpen
[T+1.842s] Reloading hooks configuration...
[T+1.842s] Cursor Hooks Service initialized successfully
[T+1.842s] Hook step requested: workspaceOpen
[T+1.842s] Hook step requested: workspaceOpen
[T+1.904s] No Claude user settings found
[T+1.904s] No enterprise hooks configuration found
[T+1.948s] No user hooks configuration found
[T+1.961s] Loaded 9 project hook(s) for steps: ..., workspaceOpen

For other hook types the log shows “Found N hook(s) to execute for step: …” and then the execution block. For workspaceOpen, neither ever appears. The Cursor Plugins log loads only marketplace plugins, and the plugin directory returned via pluginPaths is never mentioned.

Hey @raz-drift, thanks for the report and the log.

We reproduced this on our side with your exact hooks.json and script. On startup, workspaceOpen is dispatched while the hooks configuration is reloading, so it finds no project hooks and your script never runs.

Unfortunately there isn’t a reliable workaround for per-repo loading until a fix ships. If you need the plugin loaded automatically in the meantime, installing it through your team marketplace (or Customize) loads it without the hook, although it won’t be scoped to this repo.