diff --git a/AGENTS.md b/AGENTS.md index da1a044..ac89fb7 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -29,6 +29,7 @@ This repository publishes the open-source server, console, integration catalog, - Write Auggie hooks only to `~/.augment/settings.json`; keep system and workspace settings read-only. Generate `.cmd` wrappers on Windows and `.sh` wrappers on Unix because Auggie dispatches supported script paths, and express hook timeouts in milliseconds. - Validate Auggie matcher syntax during installation with Node.js `new RegExp`; keep status and uninstall independent from the JavaScript validator so recovery remains available offline. - Write Cline file hooks to `$CLINE_DIR/hooks` with `~/.cline/hooks` as the default; keep Documents and workspace hook roots read-only. Use supported event filenames, preserve official hook input byte-for-byte, use `process.execPath` in Node and Go wrappers, and resolve Python runtimes from absolute shebangs. Translate guard exit code `2` into JSON stdout with `cancel: true`. Treat hook errors, timeouts, and invalid control JSON as fail-open. +- Model Cursor as one CLI-and-IDE hook contract. Preserve user, project, and enterprise sources in documented priority order; forward `tool_name`, `tool_input`, and `conversation_id`; use exit code `2` for denial; record `failClosed` as the per-script failure-mode control. - Preserve Factory Droid's scope-root `hooks.json` precedence, legacy nested hook source, and per-event `settings.json` fallback. Scope-root and legacy files store event keys at the document root; settings stores the same map under `hooks`. Edit only effective user sources; keep project and organization sources read-only. Preserve JSONC comments through syntax-tree edits, use SDK-native absolute runtime commands, commit generated runtime artifacts and hook sources as one recoverable transaction, and require `/hooks` review after external changes. - Qwen Code `0.20.0` resolves user settings through explicit `QWEN_HOME`, then user-level `.qwen/.env`, then `~/.env`, with `~/.qwen/settings.json` as the default. Keep workspace settings read-only. Preserve JSON comments, reject trailing commas and duplicate keys before writes, express timeouts in milliseconds, propagate native exit code `2` through PowerShell, and require `/hooks` review. - Commit Qwen Code runtime config, private key, audit runtime, and user settings in one rollback-capable transaction. Status requires enabled `PreToolUse` and `PostToolUse` hooks with matching managed runtime files. diff --git a/integrations/README.md b/integrations/README.md index b25d0dc..27e4e18 100644 --- a/integrations/README.md +++ b/integrations/README.md @@ -8,6 +8,8 @@ Grok Build adapters write native user hook files under `$GROK_HOME/hooks` or `~/ GitHub Copilot command `preToolUse` hooks deny on crashes and every non-zero exit. Command timeouts continue through the normal permission flow, so `timeout_failure_mode` records that explicit exception when it differs from `failure_mode`. +Cursor uses the same `preToolUse` and `postToolUse` contract across its CLI and IDE. User, project, and enterprise hook sources merge by documented priority; command exit code `2` denies an action, while per-script `failClosed` controls crash, timeout, and invalid-output behavior. + `delivery_state` is computed from the `node`, `python`, and `go` adapter flags: | State | Meaning | diff --git a/integrations/catalog.json b/integrations/catalog.json index d40aea8..c764093 100644 --- a/integrations/catalog.json +++ b/integrations/catalog.json @@ -148,20 +148,28 @@ "id": "cursor", "name": "Cursor", "vendor": "Anysphere", - "surface": "ide", + "surface": "cli_and_ide", "integration_mode": "command_hooks", "config_format": "json", "config_paths": [ - "~/.cursor/hooks.json", - ".cursor/hooks.json" + "/Library/Application Support/Cursor/hooks.json", + "/etc/cursor/hooks.json", + "C:\\ProgramData\\Cursor\\hooks.json", + ".cursor/hooks.json", + "~/.cursor/hooks.json" ], "events": { "before_tool": "preToolUse", "after_tool": "postToolUse" }, + "event_fields": { + "name": "tool_name", + "input": "tool_input", + "session": "conversation_id" + }, "blocking": { "mechanism": "exit_code_2", - "failure_mode": "fail_open" + "failure_mode": "configurable" }, "adapters": { "node": true, "python": true, "go": true }, "delivery_state": "available", diff --git a/test/integration-catalog.test.mjs b/test/integration-catalog.test.mjs index 958f977..e065a5b 100644 --- a/test/integration-catalog.test.mjs +++ b/test/integration-catalog.test.mjs @@ -296,6 +296,27 @@ test('high-drift providers retain their verified hook contracts', async () => { failure_mode: 'fail_closed', timeout_failure_mode: 'fail_open', }); + assert.equal(providers.get('cursor').surface, 'cli_and_ide'); + assert.deepEqual(providers.get('cursor').config_paths, [ + '/Library/Application Support/Cursor/hooks.json', + '/etc/cursor/hooks.json', + 'C:\\ProgramData\\Cursor\\hooks.json', + '.cursor/hooks.json', + '~/.cursor/hooks.json', + ]); + assert.deepEqual(providers.get('cursor').events, { + before_tool: 'preToolUse', + after_tool: 'postToolUse', + }); + assert.deepEqual(providers.get('cursor').event_fields, { + name: 'tool_name', + input: 'tool_input', + session: 'conversation_id', + }); + assert.deepEqual(providers.get('cursor').blocking, { + mechanism: 'exit_code_2', + failure_mode: 'configurable', + }); assert.deepEqual(providers.get('droid').config_paths, [ '~/.factory/hooks.json', '~/.factory/settings.json',