# Cursor hooks — Enterprise Skills orchestration

Optional **project-level** hooks so Cursor can:

1. **`beforeShellExecution`** — enforce skill trigger bindings at the moment of risk (`pre-shell-gate.mjs`). See below.
2. **`userPromptSubmit`** — run the input gateway before agent execution when `inputGateway` is true.
3. **`sessionStart`** — ensure an orchestration session exists when `sessionStartInit` is true.
4. **`stop`** — run `orchestrate signal-active` when `stopSignalActive` is true.
5. **`afterAgentResponse` + `stop`** — run `scan-autopilot-scope.ps1` as a runtime backstop for model-autopilot SCOPE CHECK discipline.

## Skill trigger bindings (`beforeShellExecution`)

`pre-deploy-check` can be active in the pack and still never get invoked before an
infrastructure apply — which is exactly what happened before three production
defects. A skill that depends on somebody remembering a trigger phrase at the
right moment is a suggestion, not a control.

`pre-shell-gate.mjs` fires when a command is about to run, asks
`enterprise-skills triggers check` for a verdict, and maps it to Cursor's
`permission` field:

| Binding `mode` | Cursor `permission` |
|---|---|
| `ask` (default) | `ask` |
| `block` | `deny` |
| `warn` | `allow` |

Configure bindings in **`.project-ai/SKILL_TRIGGERS.yaml`** (`enterprise-skills
triggers init` seeds it from the infrastructure actually on disk). With no
config file the hook returns immediately and costs nothing.

Two properties worth knowing:

- **The command travels in `ES_TRIGGER_COMMAND`, never in argv.** On Windows the
  CLI entry point is a `.cmd` shim, which forces `shell: true`; Node then joins
  argv into a command line, so a command containing `&` would execute its tail
  *from inside the gate meant to control it*, and any command containing a space
  would split and silently never match. Same reason `ES_AGENT_PROMPT` exists.
- **It fails open, deliberately.** A pre-execution hook that errors must not
  brick the shell. The gate that must not fail open is the merge gate — the
  Release Governor — which this file cannot affect.

The equivalent Claude Code hook (`PreToolUse`) ships at
`templates/claude-code-hooks/pre-tool-use-gate.mjs`; both are thin shims over the
same `triggers check`, so two editors cannot disagree about what is armed.

## Zero manual merge (recommended)

Templates ship **inside the npm package**. From your **application** repo root:

```bash
npm install -g enterprise-skills
enterprise-skills setup-hooks
```

Or full onboarding + hooks:

```bash
enterprise-skills onboard --with-init --install-cursor-hooks
```

The CLI **merges** entries into `.cursor/hooks.json` (dedupes by `command`) and writes a timestamped backup if the file already existed. You do not paste `hooks.snippet.json` by hand.

Configuration: **`.project-ai/orchestration-hooks.json`** (created from `orchestration-hooks.sample.json` if missing). If the file is missing, hook scripts exit immediately (no-op).

Default config:

```json
{
  "inputGateway": true,
  "subscriptionTier": "community",
  "maxPromptChars": 2000,
  "sessionStartInit": true,
  "stopSignalActive": false
}
```

The input gateway creates `.project-ai/skill-outputs/_task-contract.yaml` for each prompt it can read from hook stdin. It only blocks when the advisor returns `decision: "block"`.

## Hub maintainers

After editing files here, sync the npm bundle:

```powershell
.\scripts\sync-cursor-hooks-templates.ps1
```

## Requirements

- **`node`** on `PATH`
- **`enterprise-skills`** on `PATH`

## Commercial path

See **`packaging/ENTERPRISE_COMMERCIAL_PATH.md`**.
