Nightfall Hooks for Cursor
This guide walks an MDM administrator through deploying Nightfall's Cursor hooks to corporate-managed developer devices, end to end. It covers all five supported MDMs in detail. The deployment package ships as a zip (Hooks Setup/cursor/) containing this payload, the install scripts, and a README.md quick reference. This guide is the long-form companion to that README.
When to use this guide
Nightfall installs hooks on most AI coding agents automatically - when you activate an AI Agent Security policy, the Nightfall endpoint agent writes the hook configuration to ~/.claude/settings.json on each endpoint, with nothing for IT to deploy by hand. That path is documented in setup.md. This guide is the exception for Cursor, which requires a manual MDM deployment of a system-level hooks.json.
Why Cursor needs a manual path (Cursor enterprise hooks bug, Feb 2026): Hooks configured in Cursor's admin dashboard sometimes don't materialize at the endpoint path Cursor reads from. Until Cursor resolves this, deploying hooks.json directly through your MDM is the reliable way to enforce Nightfall hooks in Cursor.
Use the automatic path for Claude Code and VS Code. Use this guide to add reliable hook coverage for Cursor on managed devices.
How it works
Cursor reads its hook configuration from a single file at a fixed path and a fixed name (hooks.json). Deployment is a two-step model:
Stage the payload. Your MDM's file-distribution (or app-deployment) feature drops Nightfall's
hooks.jsonat a staging path on each device.Run the merge script. A script provided in the package splices Nightfall's entries into Cursor's
hooks.jsonat the path Cursor actually reads.
Why merge instead of overwrite
The file Cursor reads (hooks.json) is shared - another security vendor or your own org policy may already own entries in it. And because the filename and path are dictated by Cursor, you can't rename or relocate it without Cursor ceasing to read it.
So the install scripts merge: they drop any existing Nightfall-marked entries, then append the staged Nightfall entries, leaving every other vendor's entries untouched. This makes re-runs idempotent - periodic re-execution never accumulates duplicates.
Prerequisites
Before deploying the Cursor hooks payload:
The Nightfall endpoint agent is already installed and running on the managed devices. The agent owns the
nightfall-hook-relaybinary the hooks invoke.You've selected the MDM scope (device group / smart group) that will receive the deployment.
jqis present on macOS devices where ahooks.jsonmay already exist. The macOS install script refuses to run — rather than clobber another vendor's entries - if a targethooks.jsonexists andjqis not installed. (Greenfield devices with no existinghooks.jsondo not needjq.)
Package contents
The scripts are MDM-agnostic - the same install.sh works whether your MDM is Rippling, Jamf Pro, Kandji, or Workspace ONE. The per-MDM sections below show which MDM feature to wire each script into.
Hooks installed
Nightfall registers four Cursor events. The two pre-action events carry failClosed: true, which blocks the action if the hook crashes, times out, or returns invalid JSON.
Event
When it fires
failClosed
beforeSubmitPrompt
Before a prompt is submitted to the model
true
preToolUse
Before a tool executes
true
postToolUse
After a tool finishes executing
-
afterAgentResponse
After the agent returns its response
-
All four invoke the same command: nightfall-hook-relay --source cursor.
failClosed: true on the pre-action events (beforeSubmitPrompt, preToolUse) means the action is blocked if the hook can't complete cleanly. The post-action events (postToolUse, afterAgentResponse) observe content after the action has already happened, so they monitor only there is nothing left to block.
Paths reference
macOS
Windows
Staging path (MDM drops the payload here)
/opt/nightfall/hooks/cursor/hooks.json
C:\Nightfall\Hooks\cursor\hooks.json
Target path (Cursor reads from here)
/Library/Application Support/Cursor/hooks.json
C:\ProgramData\Cursor\hooks.json
The target path and filename are dictated by Cursor and must not be changed.
On macOS, a greenfield device (no existing target hooks.json) is handled by a plain cp - no jq required. If a target already exists, the script requires jq to merge and refuses to run without it. On Windows, the merge runs in PowerShell, writes the result as UTF-8 without a BOM, then locks the file down with icacls.
Per-MDM setup
Every MDM follows the same two-step wiring: distribute the payload to the staging path, then run the install script to merge it into Cursor's hooks.json. The install scripts hard-fail unless run as root (macOS) or SYSTEM / Administrator (Windows), so always run them in a System / SYSTEM context.
Rippling
macOS
Distribute the payload — Use Rippling's file/app distribution to place
payloads/hooks.jsonat/opt/nightfall/hooks/cursor/hooks.json.Run the merge — Create a Custom Script that runs
scripts/macos/install.shat System scope, triggered on enrollment and daily.
Windows
Distribute the payload to
C:\Nightfall\Hooks\cursor\hooks.json.Run the merge - Create a PowerShell Script that runs
scripts/windows/install.ps1at SYSTEM scope.
Jamf Pro
macOS
Distribute the payload to
/opt/nightfall/hooks/cursor/hooks.json(e.g. via a package or a Files and Processes distribution).Run the merge - Add
scripts/macos/install.shas a Script, then attach it to a Policy scoped to your device group with the triggers Recurring Check-in and Enrollment Complete.
Kandji
macOS - Kandji's Custom Script library item pairs an audit script with a remediation script, which matches the package's presence-check model exactly:
Distribute the payload to
/opt/nightfall/hooks/cursor/hooks.json(Custom App or file distribution).Audit - Set
scripts/macos/audit.shas the Audit Script. It exits 0 when Nightfall's command is already present and exits 1 when remediation is needed.Remediation - Set
scripts/macos/install.shas the Remediation Script. Kandji runs it only when the audit reports drift.
Microsoft Intune
Windows - Wire into a Win32 / Proactive Remediation (Detection + Remediation):
Distribute the payload to
C:\Nightfall\Hooks\cursor\hooks.json(e.g. a Win32 app).Detection - Use
scripts/windows/detect.ps1as the Detection script. It exits 0 (present) when Nightfall's command is already inhooks.jsonand exits 1 to trigger remediation. Run it in the SYSTEM context (64-bit PowerShell).Remediation - Use
scripts/windows/install.ps1as the Remediation script, also in the SYSTEM context.
Workspace ONE
Workspace ONE covers both platforms via its Scripts feature, run in the System / SYSTEM context with Periodic and Enrollment triggers.
macOS
Distribute the payload to
/opt/nightfall/hooks/cursor/hooks.json.Run the merge - Add
scripts/macos/install.shas a Script in the System context, scheduled Periodic + on Enrollment.
Windows
Distribute the payload to
C:\Nightfall\Hooks\cursor\hooks.json.Run the merge - Add
scripts/windows/install.ps1as a Script in the SYSTEM context, scheduled Periodic + on Enrollment.
Validation
Open the Devices page in the Nightfall console. Each device shows a per-client hook status indicator - a healthy status for Cursor means the deployment is working on that device. A healthy Cursor hook status on the Devices page confirms the payload was staged, the merge script ran, and Cursor is reading Nightfall's entries.
Drift & re-run behavior
The audit/detection scripts (audit.sh / detect.ps1) check for the presence of Nightfall's command in hooks.json (a grep / regex match), not byte equality. Byte equality with the staged payload isn't meaningful because hooks.json is shared with other vendors.
The install scripts are idempotent: each run drops any existing Nightfall-marked entries and re-appends the staged ones, so periodic re-execution never accumulates duplicates and never disturbs other vendors' entries.
If the staging payload hasn't been deployed yet, the audit/detection scripts report present / exit 0 rather than failing. Remediation couldn't succeed without the staged file, so this stops the MDM from looping on a state it can't fix from the device.
Rollback
To remove Nightfall's Cursor hooks, hand-edit hooks.json on the device (or push an edited copy via your MDM) and remove every entry whose command is nightfall-hook-relay --source cursor. Leave all other vendors' entries - and your own org policy's entries - untouched.
The nightfall-hook-relay binary stays installed; the Nightfall endpoint agent owns its lifecycle.
A scripted rollback may be added in a future release. For now, removal is a manual entry edit.
Troubleshooting
Symptom
Likely cause
Resolution
macOS install exits with "jq is not installed"
A hooks.json already exists and jq is missing, so the script refuses to merge
Install jq on the device and re-run the install script
Install exits with "must run as root" / "administrator privileges"
Script ran in a user context
Re-run in the System (macOS) or SYSTEM (Windows) context via your MDM
Install exits with "payload not found"
The payload wasn't staged before the script ran
Deploy hooks.json to the staging path first, then re-run
Windows hooks.json fails to parse on re-run
A UTF-8 BOM was written by an older PowerShell 5.1 run
Re-run the current install.ps1 — it strips the BOM on read and writes UTF-8 without a BOM
Cursor hook status not showing in console
Hooks not yet merged, or agent not connected
Confirm the install script ran successfully and the Nightfall agent is running on the device
Known issues / notes
Cursor enterprise hooks bug (Feb 2026): Hooks configured in Cursor's admin dashboard sometimes don't materialize at the expected endpoint path. MDM-deployed
hooks.jsonis the reliable path until Cursor resolves this.Cursor cloud agents don't yet honor team/enterprise-managed hooks — only a project-committed
.cursor/hooks.jsonruns in cloud sessions. The MDM deployment in this guide covers local Cursor sessions on managed devices.
Last updated
Was this helpful?