> ## Documentation Index
> Fetch the complete documentation index at: https://docs.runlayer.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Endpoint modes

> Choose Monitor, Protect, or Enforce behavior for real-time AI client tool calls

AI Watch client hooks support three endpoint modes: Monitor, Protect, and Enforce. Unlike Detect (which discovers configurations), Protect applies scanner decisions to supported endpoint tool activity and blocks configured MCP sources that match its fail-open denylist. Enforce applies scanner and local policy decisions to non-MCP tools, uses fail-closed allowlists for configured MCP sources, and relies on the Runlayer gateway to scan managed MCP calls.

| Mode        | Endpoint scanner coverage                                            | Local file/shell policy | Configured MCP source governance                  |
| ----------- | -------------------------------------------------------------------- | ----------------------- | ------------------------------------------------- |
| **Monitor** | Report only                                                          | Off                     | Off                                               |
| **Protect** | Supported local and direct MCP tool hooks                            | Off                     | Allow unless denied (Protect denylist; fail open) |
| **Enforce** | Supported local non-MCP tool hooks; managed MCPs scan at the gateway | On                      | Deny by default (Enforce allowlists; fail closed) |

The scanner action named **Alert** is unchanged; it remains a scanner-level action that records a finding without blocking. **Monitor** is the endpoint mode name.

<Note>
  Exact Block and Mask behavior depends on what each client's hooks can do. The safe rule: when a client cannot replace sensitive content, a Mask verdict becomes a Block, so nothing sensitive slips through.

  | Client                          | Mask behavior                                                                                      |
  | ------------------------------- | -------------------------------------------------------------------------------------------------- |
  | Gemini CLI                      | Masks tool input; a Mask verdict on tool output becomes a Block                                    |
  | Devin CLI                       | Masks tool input; tool output can be neither masked nor blocked — post-tool events are report-only |
  | Grok CLI                        | Blocks before the tool runs; input masks become a pre-tool Block; post-tool events are report-only |
  | Claude Code, GitHub Copilot CLI | Failed-tool output is report-only (the raw error cannot be replaced)                               |

  The Protect and Enforce scanner path also requires **Full session scanning APIs** and the target **Hook client** under **Settings** → **Agent session monitoring**. MCP source governance in both modes stays active without full session telemetry.
</Note>

<Note>
  Grok Bot is separate from Grok CLI. Its desktop and iOS apps control agents
  running on cloud computers, so endpoint-installed AI Watch hooks do not reach
  those runs. Use the [Grok Bot team hook collector](/shadow-ai/grok-bot) for
  monitor-only session visibility; it does not participate in Protect or Enforce.
</Note>

## Endpoint mode decision flow

Detect remains active in every mode. Sessions independently controls session and event telemetry, while the selected endpoint mode determines which real-time decisions run on the device.

```mermaid theme={null}
flowchart TB
    A["AI Watch installed"]

    A --> D["Detect — always enabled<br/>Discovers and risk-classifies artifacts<br/>Never blocks"]

    A --> S{"Sessions toggle<br/>Independent of mode"}
    S -->|On| S1["Collect session and event telemetry<br/>Monitor hooks remain installed"]
    S -->|Off| S2["Session-only hooks disabled<br/>Protect/Enforce decision hooks still run<br/>Monitor becomes Detect-only"]

    A --> T["Tool call"]
    T --> R{"Runlayer-managed MCP?"}

    R -->|Yes| G["Runlayer Gateway<br/>Access policies + content scanners"]
    G --> GSCAN["Gateway scanner decision"]

    R -->|No| M{"Endpoint mode"}

    M -->|Monitor| MON["MONITOR<br/>Report activity and allow<br/><br/>Scanner actions: report-only<br/>File/shell policy: OFF<br/>MCP source governance: OFF"]

    M -->|Protect| P["PROTECT<br/>Scan supported endpoint lifecycle"]
    P --> PT{"Tool kind"}
    PT -->|Local tool| ESCAN["Endpoint scanner decision"]
    PT -->|Configured MCP source| PG{"Protect denylist"}
    PG -->|Match| PB["Block source before call"]
    PG -->|Unmatched| ESCAN
    PG -->|Lookup or evaluation error| ESCAN
    P --> POFF["File/shell policy: OFF<br/>MCP source policy: allow unless denied (fail open)"]

    M -->|Enforce| E{"ENFORCE<br/>Tool kind"}
    E -->|Local non-MCP tool| EP["Endpoint scanner<br/>+ applicable file/shell/built-in policy"]
    EP --> ESCAN

    E -->|Configured MCP source| EG["MCP source governance"]
    EG -->|Unapproved| EB["Block source before call"]
    EG -->|Allowlisted| EA["Allow source<br/>No Protect-style endpoint content scan"]

    GSCAN --> SD["Apply scanner action"]
    ESCAN --> SD
    ESCAN -.->|Requires| PRE["Full session scanning APIs<br/>+ target Hook client enabled"]

    SD --> ALERT["Alert<br/>Record and allow"]
    SD --> MASK["Mask<br/>Rewrite supported input/output"]
    SD --> BLOCK["Block<br/>Stop call or suppress output"]

    MASK -.->|Client limitation| C["Unsupported rewrite fails closed to Block<br/>Gemini CLI output masking falls back to Block<br/>Claude Code and Copilot CLI failed-tool errors remain observational<br/>Devin CLI tool output is observational: no Mask or Block"]

    S -.->|Does not change| M
```

## How It Works

When endpoint hooks are installed, they capture supported client events before tool input is executed and before tool output is returned to the assistant:

1. **User invokes a tool** — The AI assistant requests an MCP or local tool call
2. **Intercept** — A supported pre-tool or post-tool hook captures the input or output
3. **Evaluation** — Protect evaluates its fail-open denylist for configured MCP sources, then scanner settings for supported endpoint tools that remain allowed. Enforce evaluates scanners and local policy for non-MCP tools plus fail-closed configured-MCP-source policy; managed MCP content is scanned at the gateway
4. **Decision** — The hook result is:
   * **Reported** — Monitor records the event without changing tool behavior
   * **Allowed** — Proceeds normally
   * **Masked** — Matching input or output is redacted before continuing on hook surfaces that support replacement
   * **Blocked** — Prevented and logged for security review
5. **Audit logging** — Scanner and MCP-source decisions plus enabled hook events are logged for visibility

Hook and Sessions events are attributed through the same device identity model as Detect. See [User and Identity Mapping](/shadow-ai/identity-mapping) for how AI Watch maps OS usernames to Runlayer users.

### Enforcement Paths

Enforce has two real-time paths:

* **Shadow MCP source enforcement** — blocks MCP servers configured outside Runlayer unless the source is allowed. A source is allowed when it is a Runlayer-managed proxy URL, a Runlayer-managed stdio command, a remote URL on your [remote-URL allowlist](/shadow-ai/enforce/policy#allowed-remote-mcp-urls), a local package on your [stdio package allowlist](/shadow-ai/enforce/policy#allowed-local-stdio-packages), or a [built-in MCP server](/shadow-ai/enforce/policy#built-in-mcp-servers) permitted for that client. This path stays active once enforcement hooks are installed, even if full session scanning is disabled.
* **Local tool lifecycle enforcement** — checks non-MCP tool calls, such as shell commands and file reads, with your scanners before and after they run, and denies any [built-in client tool](/shadow-ai/enforce/policy#blocked-built-in-tools) whose behavior type (shell/terminal, file read, file write) is on your block list. The block list is a per-category switch, not a per-path or per-command rule engine; content decisions on allowed calls come from your scanners. This path requires **Full session scanning APIs** and the target **Hook client** to be enabled under **Settings** → **Agent session monitoring**.

<Note>
  **Sessions telemetry and endpoint mode are independent.** Monitor reports activity without blocking. Protect applies scanner decisions and blocks MCP sources on the [Protect denylist](/shadow-ai/protect/policy). Enforce applies its deny-by-default source policy and local tool controls. Sessions can remain enabled in every mode.
</Note>

### What Gets Intercepted

Enforce intercepts tool calls from shadow MCP servers — those configured directly in the client rather than through Runlayer. This includes MCP servers embedded in **native client plugins** (e.g. Claude Code marketplace plugins). The hook resolves MCP endpoints from installed plugin manifests and enforces the same source rules.

Tool calls to Runlayer-managed MCPs (server, plugin, and skill proxy URLs) are recognized as managed and allowed through. All other remote MCP URLs are blocked unless they appear on the [allowlist](/shadow-ai/enforce/policy#allowed-remote-mcp-urls). Connectors attached to a user's Claude account on claude.ai are also allowed through — they have no URL or command on the device, so govern them through your Claude.ai workspace controls (see [Enforce policy](/shadow-ai/enforce/policy#built-in-mcp-servers)).

For supported hook clients, Enforce also intercepts local non-MCP tools. These calls are evaluated by your scanner settings: organizations with no blocking scanner configuration allow by default; organizations with blocking scanner actions can block before execution or block untrusted output after execution.

### Can users bypass approved plugins and skills?

Not at the MCP layer, once Enforce hooks are installed. How each artifact type is governed:

* **Approved (Runlayer-managed) plugins and skills** — [Plugins](/platform-plugins) bundle connectors behind a single Runlayer proxy URL, so every tool call still goes through your organization's [policies](/platform-policies) and access controls; a user cannot repoint a managed plugin at a different endpoint. Managed [skills](/platform-skills) are security-scanned on publish, with a configurable risk policy that blocks high-risk skills by default.
* **Unapproved local plugins** — MCP servers embedded in locally installed plugins are subject to the same shadow MCP source enforcement described above: blocked unless they resolve to a Runlayer-managed URL or an allowlisted remote URL.
* **Unapproved local skills** — Skills are instruction files, not tool endpoints, so there is no skill-specific blocking path; [Detect](/shadow-ai/detect#shadow-skills-discovery) discovers and risk-classifies shadow skills but never blocks them. The actions a shadow skill drives still run through tool calls, which are covered by shadow MCP source enforcement and — where enabled — local tool lifecycle scanning.

Monitor never blocks on the device. Protect can apply scanner Block and Mask actions and block explicitly denied MCP sources; Enforce adds deny-by-default MCP source governance and local tool controls. [Detect](/shadow-ai/detect) continues to provide discovery and risk classification of shadow MCPs, skills, and plugins in every mode.

## Protect policy

Protect source governance is **allow unless denied**. Admins can deny specific remote URLs, local npm/PyPI package identities, and client built-in MCP servers while leaving every unmatched source allowed. Source-check failures fail open and continue through Protect's content-scanner path.

<Card title="Protect policy configuration" icon="shield" href="/shadow-ai/protect/policy">
  Configure Protect-only MCP source denylists and understand fail-open behavior.
</Card>

## Enforce policy

Once Enforce hooks are installed, the **Enforce policy** governs which unmanaged tool sources are allowed and which built-in client tools are blocked. Admins with the **Manage org settings** capability edit it under **Settings** → **Tool governance** → **Enforce**. It has four independent, **fail-closed** dimensions — an allowlist of remote MCP URLs, an allowlist of local (STDIO) packages, blocked built-in tool types, and a built-in MCP server allowlist. Anything Enforce cannot positively match to a Runlayer-managed source, an allowlist entry, or a permitted built-in is blocked.

<Card title="Enforce policy configuration" icon="sliders" href="/shadow-ai/enforce/policy">
  Configure the allowlists and built-in tool blocks: remote MCP URLs, local (STDIO) packages, built-in MCP servers, built-in tool types, and one-click promotion from Detect sightings.
</Card>

## Supported Clients

| Client                 | macOS | Windows |
| ---------------------- | :---: | :-----: |
| **Cursor**             |   ✓   |    ✓    |
| **VS Code**            |   ✓   |    ✓    |
| **Claude Code**        |   ✓   |    ✓    |
| **GitHub Copilot CLI** |   ✓   |    ✓    |
| **Gemini CLI**         |   ✓   |    ✓    |
| **Grok CLI**           |   ✓   |    ✓    |
| **Codex**              |   ✓   |    ✓    |
| **Qwen Code**          |   ✓   |    ✓    |
| **Cline CLI**          |   ✓   |    ✓    |
| **Devin CLI**          |   ✓   |    ✓    |
| **Hermes**             |   ✓   |    ✓    |
| **Goose**              |   ✓   |    ✓    |
| **Windsurf**           |   ✓   |    ✓    |

<Note>
  Endpoint modes use client hooks, so this matrix is intentionally smaller than Detect's scan matrix. Gemini CLI hooks require Gemini CLI v0.26.0 or newer. Earlier versions ignore the hooks settings block entirely. Check **Settings** → **Agent session monitoring** → **Hook clients** for the latest tenant-enabled client list.

  Grok CLI enforces on `PreToolUse` only and fails open if a hook times out, crashes, or returns malformed output. Its post-tool hooks provide session telemetry but cannot block or rewrite output.

  Devin CLI enforces on `PreToolUse` only and fails open if a hook times out or crashes. Its post-tool hooks provide session telemetry but cannot block or rewrite output; input masking is supported. Devin imports hook and MCP configuration from other tools (Claude Code, Cursor, Windsurf, OpenCode, Zed); Runlayer accounts for this, so a Devin tool call is neither double-enforced nor attributed to another client, and Enforce recognizes MCP servers Devin reaches through its enabled imports — a server reachable only through a disabled import counts as unregistered.

  Windsurf enforces on pre-tool events only. Cascade denies a tool call when the hook exits with code 2. It ignores post-tool hook exit codes and does not parse hook output, so Windsurf cannot block or rewrite tool output.
</Note>

***

## Deployment

<Note>
  **All three modes ship in the same AI Watch `.pkg` / `.msi`** that supports Detect and Sessions. A single signed `aiwatch` binary handles scanning, hook decisions, and session events, all authenticated by one **organization API key**. The profile or MSI provides bootstrap credentials only; macOS and Windows packages receive Mode and Sessions from the linked deployment in Runlayer. Before that sync succeeds, they remain Monitor + Sessions off with no hooks.
</Note>

<Note>
  **TLS trust:** The MDM-deployed `aiwatch` binary (scan + `aiwatch hook`) verifies HTTPS through the OS trust store — macOS Keychain (login + System), Windows certificate stores (Current User + Local Machine). Corporate root CAs pushed via MDM, GPO, or Intune are honored automatically with no extra config. If your corporate root is not installed system-wide and hooks fail with `CERTIFICATE_VERIFY_FAILED`, see [Troubleshooting](/shadow-ai/troubleshooting) for `--ca-bundle`, `RUNLAYER_CA_BUNDLE`, `SSL_CERT_FILE`, and `REQUESTS_CA_BUNDLE` overrides.
</Note>

### How the bootstrap flow works

When Mode is Protect/Enforce or Sessions is enabled, the `.pkg` / `.msi` runs an idempotent hook bootstrap: it writes Runlayer hook entries into the Cursor, VS Code, Claude Code, GitHub Copilot CLI, Gemini CLI, Grok CLI, Cline CLI, Devin CLI, Codex, Qwen Code, Hermes, Windsurf, and Goose configuration files as the command string `aiwatch hook --client <name>`. Existing third-party hooks are preserved. Monitor also installs hooks when Sessions is enabled. The hooks authenticate with the organization API key carried in tenant config.

On macOS, a package-installed root bootstrap daemon installs and re-asserts the hook configs at load and hourly. On Windows, the MSI-registered `AIWatchHooks` scheduled task does the same as SYSTEM at boot and hourly — no Intune Remediations required. See [Troubleshooting](#troubleshooting) below for how to verify either one on a device.

#### Verify hook setup

Use the built-in compliance check in [Troubleshooting](#troubleshooting) instead
of inspecting each client's configuration files. It checks every supported
client and reports any drift; the recurring bootstrap repairs drift
automatically.

<Note>
  * **Grok CLI custom home**: root/SYSTEM jobs cannot read a user's shell-defined `GROK_HOME`. If Grok CLI uses a custom directory, set the Runlayer managed string `GrokHome` to a path inside the console user's home (for example `.grok-custom`).
  * **Claude Code backups**: before changing an existing Claude Code settings file, AI Watch saves a copy beside it as `settings.backup_<timestamp>.json`. Invalid or symlinked settings are left untouched and reported as an error rather than replaced.
  * **Qwen Code**: a top-level `"disableAllHooks": true` disables Qwen hooks entirely; hook install reports it as a misconfiguration rather than claiming hooks are active.
  * **Devin CLI**: Devin's standalone `hooks.v1.json` is project-scoped only, so Runlayer merges hook entries into the `hooks` key of the user config; Devin has no machine-wide settings file, so MDM scope writes the console user's copy. Uninstall removes only Runlayer entries and never deletes `config.json`, which holds the rest of the user's Devin configuration.
  * **Cline enforcement is best-effort**: Cline can only block a tool call before it runs, and it fails open — a hook that times out or errors lets the call proceed. This covers the Cline CLI/SDK only, not the Cline VS Code extension. Uninstall and drift checks touch only Runlayer-owned files.
</Note>

The hook bootstrap is idempotent — repeat ticks refresh the deployment's Runlayer settings, re-write the same `command` strings, and preserve third-party entries. Switch Mode to Monitor to stop applying decisions; if Sessions stays enabled, hooks remain installed for telemetry. Use Monitor with Sessions disabled for Detect-only deployment with no hooks — unless **Track MCP tool usage without content** is enabled, which keeps one metadata-only MCP pre-call hook per supported client. Existing hooks read mode changes on their next fire after refresh; moving into or out of Detect-only reconciles hook entries on that bootstrap tick. Neither path requires reinstalling the package.

### MDM Deployment

Use [Deploy AI Watch](/shadow-ai/deploy) for managed rollout. Select **Monitor**, **Protect**, or **Enforce** in the MDM configuration wizard. Installer artifacts carry only bootstrap credentials; the selected Mode arrives through the Runlayer settings sync. Until that sync succeeds, the endpoint remains Monitor + Sessions off with no hooks. After deployment, use **Settings** → **AI Watch** → **Manage settings** to change Mode without re-pushing MDM policy.

<Card title="Deploy AI Watch" icon="download" href="/shadow-ai/deploy">
  Install the package once, then configure endpoint Mode and Sessions.
</Card>

For non-Intune Windows MDMs, call `aiwatch.exe setup hooks check/install --mdm` from a SYSTEM-context recurring task.

### Monitor rollout (no blocking)

For an observe-without-blocking baseline, set Mode to Monitor. Hooks still register and forward events when Sessions is enabled, but endpoint scanner and governance decisions are not applied.

| Platform | Legacy native fallback                                         | Monitor value              | Default          |
| -------- | -------------------------------------------------------------- | -------------------------- | ---------------- |
| macOS    | Optional `Mode` in `com.runlayer.aiwatch` policy               | `<string>monitor</string>` | absent ⇒ Monitor |
| Windows  | Optional `Mode` REG\_SZ under `HKLM\Software\Runlayer\AIWatch` | `monitor`                  | absent ⇒ Monitor |

For manual installs, use `--mode monitor`; add `--event-hooks` to mirror a managed deployment with Sessions enabled. For managed deployments, change Mode to Protect or Enforce from the deployment card. Existing hooks read the change on their next fire after the next settings refresh; a Detect-only device installs the required hooks during that reconcile.

<Note>
  **Older package versions:** a valid Mode always overrides the legacy `Enforcement` boolean, and an older client that does not understand Protect falls back to Enforce rather than silently monitoring. Upgrade older packages before relying on Protect behavior across the fleet.
</Note>

For Detect-only deployment with no hooks, select Monitor and disable Sessions in the Runlayer deployment configuration, and leave **Track MCP tool usage without content** off. With Monitor and Sessions off, enabling that setting installs a single metadata-only MCP pre-call hook per supported client: it reports which MCP tools are used (client, tool name, server name, device/user identity) but never request arguments, responses, or session content.

### Manual installation (single-device)

To test the packaged deployment on one macOS or Windows device without MDM, use the [Test Device guide](/shadow-ai/deploy/test-device). The same guide covers Linux's Detect-only package flow.

For a per-user macOS/Linux setup, install the `runlayer` CLI and run the operator-facing hook installer below. The full CLI hook installer does not support Windows; use the packaged [Intune deployment](/shadow-ai/deploy/intune) or another SYSTEM-context packaged deployment there.

**Step 1 — Install the Runlayer CLI:**

```bash macOS/Linux theme={null}
curl -LsSf https://astral.sh/uv/install.sh | sh
uv tool install runlayer
```

Restart your terminal after installing so `~/.local/bin` is on PATH.

**Step 2 — Log in to your Runlayer instance:**

```bash theme={null}
runlayer login --host https://your-runlayer-instance.com
```

Credentials are stored in your OS keychain when available, with a fallback to `~/.runlayer/config.yaml`.

**Step 3 — Choose and install the endpoint mode:**

```bash theme={null}
runlayer setup hooks --install --yes --host https://your-runlayer-instance.com --mode protect
```

Replace `protect` with `monitor` for report-only hooks or `enforce` for local scanner/policy decisions plus fail-closed, deny-by-default MCP-source governance. Protect itself includes fail-open, allow-unless-denied source governance.

| Flag                             | Description                                                                                                                                                                                                       |
| -------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--install`                      | Perform the installation                                                                                                                                                                                          |
| `--uninstall`                    | Remove hooks                                                                                                                                                                                                      |
| `--yes`                          | Skip confirmation prompts                                                                                                                                                                                         |
| `--host`                         | Validate this host exists in config before install                                                                                                                                                                |
| `--client`                       | Install for a specific client (`cursor`, `vscode`, `claude_code`, `github-copilot-cli`, `gemini-cli`, `grok-cli`, `cline-cli`, `devin-cli`, `codex`, `qwen-code`, `hermes`, `windsurf`, or `goose`; default: all) |
| `--event-hooks` / `--all-events` | Register all hook events including pipeline (default: enforcement only)                                                                                                                                           |
| `--mode`                         | Endpoint mode: `monitor`, `protect`, or `enforce`                                                                                                                                                                 |
| `--no-enforcement`               | Legacy Monitor setup that also registers the full event hook set; cannot be combined with `--mode`                                                                                                                |

<Note>
  The MDM-deployed `.pkg` / `.msi` runs `aiwatch setup hooks install --mdm` automatically on its hourly schedule (the macOS bootstrap LaunchDaemon / the Windows `AIWatchHooks` task); run `aiwatch config sync` to trigger it immediately. The `runlayer setup hooks --install` command above is the operator-facing path for non-MDM use — it uses the same hook endpoints and client hook shapes, but writes through the full CLI's per-user installer.
</Note>

Use `--mode monitor` when you want visibility without blocking requests. Hooks still forward events where the corresponding event endpoints are enabled, but no scanner or governance decision is applied. `--no-enforcement` remains available for compatibility.

**Uninstall:**

```bash theme={null}
runlayer setup hooks --uninstall --yes
```

### Sessions and endpoint modes

To collect detailed [Sessions](/platform-sessions) timelines, hooks must register the full event/session set, not just decision hooks. Managed deployments control this with the synced `Sessions` setting in [Deploy AI Watch](/shadow-ai/deploy). Manual installs can add `--event-hooks` (or the `--all-events` alias) to the `runlayer setup hooks --install` invocation.

Local tool lifecycle scanning uses endpoint decision hooks, but its scanner path is also gated by **Full session scanning APIs** and the target **Hook clients** under **Settings** → **Agent session monitoring**. Enforce's shadow MCP source blocking remains active without full session telemetry.

***

## Troubleshooting

<AccordionGroup>
  <Accordion title="Hooks not intercepting calls">
    1. **Restart the AI client** after installation — Cursor, VS Code, Claude Code, Codex, Gemini CLI, Grok CLI, Qwen Code, Cline CLI, Devin CLI, Hermes, Windsurf, and Goose only read hook configs at process start.
    2. Confirm the hook configs are installed:
       ```bash theme={null}
       /usr/local/bin/aiwatch setup hooks check --mdm   # macOS
       & "C:\Program Files\Runlayer\AIWatch\aiwatch.exe" setup hooks check --mdm   # Windows
       ```
       Exit 0 = compliant. Exit 1 = hook configs drifted (the next bootstrap tick will rewrite them).
    3. Confirm the deployment's effective `Mode`. The synced settings snapshot overrides the initial MDM value on macOS and Windows:
       ```bash theme={null}
       sudo cat /var/db/com.runlayer.aiwatch/backend-config.json                # macOS
       (Get-ItemProperty "HKLM:\Software\Runlayer\AIWatch").BackendConfig        # Windows
       ```
       If no valid snapshot exists, AI Watch falls back to any explicit native `Mode` / legacy `Enforcement` policy. If neither exists, it remains Monitor. Change the active setting from **Settings** → **AI Watch** → **Manage settings**, or re-push native policy only when intentionally maintaining a legacy fallback.
    4. Check that the client is supported (see table above).
  </Accordion>

  <Accordion title="`setup hooks check` exits 1 (hook configs drifted)">
    The bootstrap hasn't (re-)written the hook configs yet. Causes:

    * **Bootstrap daemon not loaded (macOS)** — Check:
      ```bash theme={null}
      sudo launchctl print system/com.runlayer.aiwatch.bootstrap
      ```
      If it returns `Could not find service`, the `.pkg` postinstall didn't bootstrap it. Re-deploy the `.pkg`, or kick it: `sudo launchctl kickstart -k system/com.runlayer.aiwatch.bootstrap`.
    * **No hook-installing capability enabled** — the bootstrap installs hooks only when Mode is Protect/Enforce, Sessions is enabled, or **Track MCP tool usage without content** is enabled in Monitor mode. Before config sync, the fail-closed default is no hooks. Verify the effective settings snapshot with the command above.
    * **`AIWatchHooks` task not running (Windows)** — the MSI-registered `AIWatchHooks` task runs `aiwatch setup hooks install --mdm` as **SYSTEM** (it writes SYSTEM-scoped paths under `Program Files` / `ProgramData`). Check it exists and its last result: `Get-ScheduledTaskInfo -TaskPath "\Runlayer\" -TaskName "AIWatchHooks" | Select-Object LastRunTime, LastTaskResult`. Force a run with `Start-ScheduledTask -TaskPath "\Runlayer\" -TaskName "AIWatchHooks"`, or repair/reinstall the app if the task is missing.
  </Accordion>

  <Accordion title="Performance issues">
    1. Check your Runlayer instance connectivity.
    2. Review the number of policies being evaluated.
    3. Contact Runlayer support if issues persist.
  </Accordion>
</AccordionGroup>

***

## Related Resources

<CardGroup cols={2}>
  <Card title="Enforce policy configuration" icon="sliders" href="/shadow-ai/enforce/policy">
    Allowlists and built-in tool blocks, field by field
  </Card>

  <Card title="Shadow MCP Overview" icon="eye" href="/shadow-ai">
    Understanding the shadow MCP problem
  </Card>

  <Card title="Detect" icon="search" href="/shadow-ai/detect">
    Discover shadow servers via scheduled scans
  </Card>

  <Card title="Policies" icon="shield" href="/platform-policies">
    Configure access control policies
  </Card>

  <Card title="Audit Logs" icon="list" href="/platform-audit-logs">
    View intercepted tool calls
  </Card>
</CardGroup>
