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:

  1. Stage the payload. Your MDM's file-distribution (or app-deployment) feature drops Nightfall's hooks.json at a staging path on each device.

  2. Run the merge script. A script provided in the package splices Nightfall's entries into Cursor's hooks.json at 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:

  1. The Nightfall endpoint agent is already installed and running on the managed devices. The agent owns the nightfall-hook-relay binary the hooks invoke.

  2. You've selected the MDM scope (device group / smart group) that will receive the deployment.

  3. jq is present on macOS devices where a hooks.json may already exist. The macOS install script refuses to run — rather than clobber another vendor's entries - if a target hooks.json exists and jq is not installed. (Greenfield devices with no existing hooks.json do not need jq.)


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

  1. Distribute the payload — Use Rippling's file/app distribution to place payloads/hooks.json at /opt/nightfall/hooks/cursor/hooks.json.

  2. Run the merge — Create a Custom Script that runs scripts/macos/install.sh at System scope, triggered on enrollment and daily.

Windows

  1. Distribute the payload to C:\Nightfall\Hooks\cursor\hooks.json.

  2. Run the merge - Create a PowerShell Script that runs scripts/windows/install.ps1 at SYSTEM scope.

Jamf Pro

macOS

  1. Distribute the payload to /opt/nightfall/hooks/cursor/hooks.json (e.g. via a package or a Files and Processes distribution).

  2. Run the merge - Add scripts/macos/install.sh as 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:

  1. Distribute the payload to /opt/nightfall/hooks/cursor/hooks.json (Custom App or file distribution).

  2. Audit - Set scripts/macos/audit.sh as the Audit Script. It exits 0 when Nightfall's command is already present and exits 1 when remediation is needed.

  3. Remediation - Set scripts/macos/install.sh as the Remediation Script. Kandji runs it only when the audit reports drift.

Microsoft Intune

Windows - Wire into a Win32 / Proactive Remediation (Detection + Remediation):

  1. Distribute the payload to C:\Nightfall\Hooks\cursor\hooks.json (e.g. a Win32 app).

  2. Detection - Use scripts/windows/detect.ps1 as the Detection script. It exits 0 (present) when Nightfall's command is already in hooks.json and exits 1 to trigger remediation. Run it in the SYSTEM context (64-bit PowerShell).

  3. Remediation - Use scripts/windows/install.ps1 as 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

  1. Distribute the payload to /opt/nightfall/hooks/cursor/hooks.json.

  2. Run the merge - Add scripts/macos/install.sh as a Script in the System context, scheduled Periodic + on Enrollment.

Windows

  1. Distribute the payload to C:\Nightfall\Hooks\cursor\hooks.json.

  2. Run the merge - Add scripts/windows/install.ps1 as 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.json is the reliable path until Cursor resolves this.

  • Cursor cloud agents don't yet honor team/enterprise-managed hooks — only a project-committed .cursor/hooks.json runs in cloud sessions. The MDM deployment in this guide covers local Cursor sessions on managed devices.


Last updated

Was this helpful?