For the complete documentation index, see llms.txt. This page is also available as Markdown.

Nightfall Hooks for Claude Code

Step-by-step instructions for deploying Nightfall's Claude Code hooks to corporate-managed employee devices via your MDM.


1. What gets deployed

Nightfall ships a managed-settings drop-in (payloads/nightfall-hooks.json) that registers the nightfall-hook-relay binary against four Claude Code events:

Event

When it fires

Purpose

PreToolUse

Before Claude Code runs a tool (file write, bash, etc.)

Inspect/intercept the action before it happens

PostToolUse

After a tool runs

Capture the result

UserPromptSubmit

When the developer submits a prompt

Inspect prompt content

Stop

When the agent finishes responding

Capture the completed turn

Every event runs the same command — nightfall-hook-relay --source claude_code - with a 15-second timeout. The payload also sets "allowManagedHooksOnly": true, which prevents users from registering their own hooks alongside the managed ones.

{
  "hooks": {
    "PreToolUse":       [ { "hooks": [ { "type": "command", "command": "nightfall-hook-relay --source claude_code", "timeout": 15 } ] } ],
    "PostToolUse":      [ { "hooks": [ { "type": "command", "command": "nightfall-hook-relay --source claude_code", "timeout": 15 } ] } ],
    "UserPromptSubmit": [ { "hooks": [ { "type": "command", "command": "nightfall-hook-relay --source claude_code", "timeout": 15 } ] } ],
    "Stop":             [ { "hooks": [ { "type": "command", "command": "nightfall-hook-relay --source claude_code", "timeout": 15 } ] } ]
  },
  "allowManagedHooksOnly": true
}

2. How the deployment works

Each device needs two things to happen, in order:

  1. Payload staged - the JSON file lands at a fixed staging path, delivered by your MDM's file-distribution / app-deployment feature.

  2. Install script runs - copies the staged payload into Claude Code's managed-settings.d/ drop-in directory and locks the file permissions.

  3. Developer relaunches Claude Code - Managed settings are read at startup. Any Claude Code session already running when the file lands will not pick up the hooks until it is fully quit and reopened. Hooks take effect on the next launch — there is no live reload.

The install scripts are idempotent: re-running just re-copies the file, so it's safe to wire them to a recurring trigger.

Staging and target paths

Platform

Staging path (step 1)

Target path (step 2)

macOS

/opt/nightfall/hooks/claude-code/nightfall-hooks.json

/Library/Application Support/ClaudeCode/managed-settings.d/nightfall-hooks.json

Windows

C:\Nightfall\Hooks\claude-code\nightfall-hooks.json

C:\Program Files\ClaudeCode\managed-settings.d\nightfall-hooks.json

The drop-in directory managed-settings.d/ accepts multiple vendor files, so Nightfall's nightfall-hooks.json coexists with anything else already there. The install just adds one file.


3. macOS setup

Step 1 - Stage the payload

Deliver payloads/nightfall-hooks.json to /opt/nightfall/hooks/claude-code/nightfall-hooks.json using your MDM's file-distribution or app-deployment feature (e.g. wrap the JSON in a .pkg, or use Workspace ONE's Files feature).

Step 2 - Run the install script

Wire scripts/macos/install.sh into your MDM as a System-context script. It:

  1. Verifies it's running as root (exits early if not — deploy at System scope).

  2. Confirms the staged payload exists.

  3. Creates …/ClaudeCode/managed-settings.d/ if needed.

  4. Copies the payload in, then sets chmod 644 and chown root:wheel.

scripts/macos/audit.sh compares the deployed file against the staged payload byte-for-byte (cmp -s):

  • Exit 0 > in sync, no action.

  • Exit 1 > drift detected, run install.sh to remediate.

(If the staging file is missing, audit exits 0 to avoid a remediation loop it can't fix.)


4. Windows setup

Step 1 - Stage the payload

Deliver payloads/nightfall-hooks.json to C:\Nightfall\Hooks\claude-code\nightfall-hooks.json using your MDM's file-distribution feature (e.g. an .msi or .intunewin).

Step 2 - Run the install script

Wire scripts/windows/install.ps1 into your MDM as a SYSTEM-context script. It:

  1. Verifies it's running as administrator (exits early if not).

  2. Confirms the staged payload exists.

  3. Creates C:\Program Files\ClaudeCode\managed-settings.d if needed.

  4. Copies the payload in, then locks the ACL with icacls — full control for

Administrators and SYSTEM, read-only for Users.

Drift checking (Intune Win32 Remediation pattern)

scripts/windows/detect.ps1 compares the deployed file against the staged payload by SHA256:

  • Prints present, exit 0 → in sync.

  • Prints staging-missing, exit 0 → staging not deployed yet (no remediation loop).

  • Exit 1 → drift, run install.ps1 as the remediation.


5. Wiring into your MDM

The scripts are MDM-agnostic - the same install script works regardless of vendor. Wire each into the matching MDM feature:

MDM

Platform

Wire into

Script

Rippling

macOS

Custom Script (on enrollment + daily)

scripts/macos/install.sh

Rippling

Windows

PowerShell Script

scripts/windows/install.ps1

Jamf Pro

macOS

Script + Policy (Recurring Check-in + Enrollment)

scripts/macos/install.sh

Kandji

macOS

Custom Script — Audit

scripts/macos/audit.sh

Kandji

macOS

Custom Script — Remediation

scripts/macos/install.sh

Microsoft Intune

Windows

Win32 Remediation - Detection

scripts/windows/detect.ps1

Microsoft Intune

Windows

Win32 Remediation - Remediation

scripts/windows/install.ps1

Workspace ONE

macOS

Script (System context, Periodic + Enrollment)

scripts/macos/install.sh

Workspace ONE

Windows

Script (SYSTEM context, Periodic + Enrollment)

scripts/windows/install.ps1

Two drift strategies:

  • Re-run on a schedule (Rippling / Jamf / Workspace ONE) - the install script is idempotent, so a periodic trigger simply re-copies and re-locks. Simplest.

  • Audit/detect → remediate (Kandji / Intune) - pair the audit/detect script with the install script so a re-install only fires when drift is detected.


6. Validation

After deployment, open the Devices page in the Nightfall console. Each device shows a per-client hook status indicator. A healthy status for Claude Code means the hooks are registered and the relay is responding - the deployment is working.

On a single device you can also confirm the file landed at the target path and that nightfall-hook-relay resolves on PATH (the endpoint agent provides it).

  • Admin-side (on the device):

  • Developer-side (in a fresh Claude Code session) — this is the missing one:

    Run /hooks. You should see four hooks (PreToolUse, PostToolUse, UserPromptSubmit, Stop), each running nightfall-hook-relay --source claude_code. If the list is empty, Claude Code has not loaded the managed file — confirm you relaunched after deployment and that your Claude Code version is current (Section X).


7. Rollback

Delete the deployed file; the relay binary stays installed (the Nightfall agent owns its lifecycle):

  • macOS: /Library/Application Support/ClaudeCode/managed-settings.d/nightfall-hooks.json

  • Windows: C:\Program Files\ClaudeCode\managed-settings.d\nightfall-hooks.json

If you wired the install to a recurring trigger, remove that MDM assignment first - otherwise the next check-in will re-deploy the file.


8. Troubleshooting

Hooks for Claude Code are not firing? Work through the checks below in order. Each step narrows down where the chain is broken: MDM deployment → file on disk → Claude Code loads it → relay runs → event reaches Nightfall. Most "deployed but not working" cases are resolved at Step 1.

The logic is the same on macOS and Windows; where a command or path differs, both variants are shown.

Step 1 — Did the developer relaunch Claude Code?

Managed settings are read only at startup. A Claude Code session that was already open when the MDM pushed the file keeps running without the hooks — there is no live reload.

Fix: Fully quit and reopen Claude Code, then re-test.

  • macOS: Quit with Cmd+Q (don't just close the window); confirm no claude process remains, then relaunch.

  • Windows: Close all Claude Code windows and confirm no claude process remains in Task Manager, then relaunch.

This is the most common cause. If hooks were deployed while Claude Code was open, this step alone usually fixes it.

Step 2 — Does Claude Code show the hooks as registered?

In a fresh Claude Code session, run:

You should see four hooks — PreToolUse, PostToolUse, UserPromptSubmit, Stop — each running nightfall-hook-relay --source claude_code.

  • Hooks listed → Claude Code loaded the managed file. Skip to Step 5.

  • List empty / hooks missing → Claude Code did not load the file. Continue to Step 3.

You can also run /doctor for a built-in settings/installation diagnostic.


Step 3 — Is the managed-settings file on disk and locked down?

Confirm the file exists at the target path with the correct ownership/permissions.

  • macOS:

    Expect: file exists, owner root, group wheel, mode 644 (-rw-r--r--).

  • Windows (PowerShell):

    Expect: file exists, ACLs locked to SYSTEM/Administrators (as set by install.ps1).

If the file is missing: the MDM install step did not complete on this device. Confirm the payload was staged, then re-run the install script at System scope (see the macOS/Windows setup sections). If the file exists but content looks wrong, validate it parses as JSON and matches the deployed payload.

Step 4 — Is Claude Code a supported version?

Managed-settings drop-in directories (managed-settings.d/) and allowManagedHooksOnly require a recent Claude Code build. Pin managed devices to a current release; builds that predate this support will not register managed hooks even when the file is present and correct.

CLI vs. VS Code extension: the Claude Code VS Code extension bundles its own CLI binary, which can be a different version than the standalone claude CLI. Verify hooks (Step 2) in whichever surface the developer actually uses, and update the CLI and the extension independently.

After updating, fully relaunch Claude Code (Step 1) and re-check /hooks.

Step 5 — Does the relay run and respond?

Confirm the relay binary is on PATH and returns a valid response.

  • macOS:

  • Windows (PowerShell):

Expect output {"continue":true} and a success exit code. If the relay is missing or errors, re-check the deployment; the relay must be installed and on PATH for the hook command to succeed.

Step 6 — Hooks fire, but nothing appears in the Nightfall console?

If /hooks shows the hooks and the relay responds, but the Devices page shows no hook activity, the events are being captured locally but not reaching Nightfall. Check the device's network egress to endpoint.nightfall.ai — TLS, DNS, proxy, or connectivity failures will drop event uploads even though hooks are working correctly. This is a network/connectivity issue, not a hooks issue.

Still stuck?

Collect and send to Nightfall support:

  • /hooks output (screenshot or text)

  • claude --version, and whether the developer uses the CLI or the VS Code extension

  • The Step 3 file listing

  • The Step 5 relay output and exit code

This set pinpoints exactly which link in the chain is broken.


8. Notes & Known Issues

  • Hooks not active after deployment? The file is loaded only at app launch. A Claude Code instance open since before the MDM push keeps running without the hooks. Fully quit (Cmd+Q / confirm the process is gone) and relaunch.

  • User-consent dialog. Any managed Claude Code setting that contains hooks triggers a one-time security dialog the user must accept. Plan internal comms before rollout so employees aren't surprised.

  • Anthropic Windows path migration (March 2026). Claude Code on Windows moved managed-settings to C:\Program Files\ClaudeCode. The shipped scripts target this new path — pin managed devices to a recent Claude Code version so the path matches.

  • Multi-vendor coexistence. The managed-settings.d/ drop-in directory accepts multiple vendor files. Nightfall's nightfall-hooks.json coexists with anything else there - the install adds a single file and never overwrites others.

  • allowManagedHooksOnly: true. This locks out user-defined hooks. If a team has a legitimate need for their own Claude Code hooks, that's a policy decision to revisit before rollout.

  • Minimum / recommended version. Managed-settings drop-in directories (managed-settings.d/) and allowManagedHooksOnly require recent changes to Claude Code. Check with claude --version; pin managed devices to a recent release.

  • CLI vs. VS Code extension. The Claude Code VS Code extension bundles its own CLI binary, which may be a different version than the standalone claude CLI. Both should read system managed-settings, but verify hooks in whichever you actually use — running /hooks in that surface. Update the extension and the CLI independently.

Last updated

Was this helpful?