context-mode 1.0.15 → 1.0.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/README.md +99 -22
  4. package/build/adapters/claude-code/index.d.ts +4 -0
  5. package/build/adapters/claude-code/index.js +56 -40
  6. package/build/adapters/cursor/config.d.ts +4 -0
  7. package/build/adapters/cursor/config.js +4 -0
  8. package/build/adapters/cursor/hooks.d.ts +40 -0
  9. package/build/adapters/cursor/hooks.js +53 -0
  10. package/build/adapters/cursor/index.d.ts +40 -0
  11. package/build/adapters/cursor/index.js +413 -0
  12. package/build/adapters/detect.d.ts +1 -0
  13. package/build/adapters/detect.js +19 -0
  14. package/build/adapters/opencode/index.js +3 -1
  15. package/build/adapters/types.d.ts +1 -1
  16. package/build/cli.js +5 -0
  17. package/build/opencode-plugin.js +8 -0
  18. package/build/server.js +7 -3
  19. package/build/session/db.js +21 -0
  20. package/build/sync/batcher.d.ts +23 -0
  21. package/build/sync/batcher.js +74 -0
  22. package/build/sync/cloud-post.d.ts +12 -0
  23. package/build/sync/cloud-post.js +38 -0
  24. package/build/sync/config.d.ts +4 -0
  25. package/build/sync/config.js +64 -0
  26. package/build/sync/index.d.ts +12 -0
  27. package/build/sync/index.js +55 -0
  28. package/build/sync/sanitizer.d.ts +13 -0
  29. package/build/sync/sanitizer.js +86 -0
  30. package/build/sync/sender.d.ts +15 -0
  31. package/build/sync/sender.js +30 -0
  32. package/build/sync/types.d.ts +31 -0
  33. package/build/sync/types.js +1 -0
  34. package/cli.bundle.mjs +89 -88
  35. package/configs/cursor/hooks.json +16 -0
  36. package/configs/cursor/mcp.json +7 -0
  37. package/hooks/core/formatters.mjs +16 -0
  38. package/hooks/core/routing.mjs +18 -4
  39. package/hooks/cursor/posttooluse.mjs +70 -0
  40. package/hooks/cursor/pretooluse.mjs +26 -0
  41. package/hooks/cursor/sessionstart.mjs +97 -0
  42. package/hooks/formatters/cursor.mjs +37 -0
  43. package/hooks/gemini-cli/sessionstart.mjs +7 -0
  44. package/hooks/session-helpers.mjs +22 -0
  45. package/hooks/vscode-copilot/sessionstart.mjs +7 -0
  46. package/package.json +3 -2
  47. package/server.bundle.mjs +67 -66
  48. package/skills/context-mode/SKILL.md +7 -9
  49. package/skills/ctx-cloud-setup/SKILL.md +98 -0
  50. package/skills/ctx-cloud-status/SKILL.md +96 -0
  51. package/skills/ctx-doctor/SKILL.md +1 -1
  52. package/skills/ctx-stats/SKILL.md +1 -1
  53. package/skills/ctx-upgrade/SKILL.md +1 -1
@@ -6,14 +6,14 @@
6
6
  },
7
7
  "metadata": {
8
8
  "description": "Claude Code plugins by Mert Koseoğlu",
9
- "version": "1.0.15"
9
+ "version": "1.0.17"
10
10
  },
11
11
  "plugins": [
12
12
  {
13
13
  "name": "context-mode",
14
14
  "source": "./",
15
15
  "description": "Claude Code MCP plugin that saves 98% of your context window. Sandboxed code execution in 11 languages, FTS5 knowledge base with BM25 ranking, and intent-driven search.",
16
- "version": "1.0.15",
16
+ "version": "1.0.17",
17
17
  "author": {
18
18
  "name": "Mert Koseoğlu"
19
19
  },
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "context-mode",
3
- "version": "1.0.15",
3
+ "version": "1.0.17",
4
4
  "description": "MCP server that saves 98% of your context window with session continuity. Sandboxed code execution in 11 languages, FTS5 knowledge base with BM25 ranking, and automatic state restore across compactions.",
5
5
  "author": {
6
6
  "name": "Mert Koseoğlu",
package/README.md CHANGED
@@ -103,7 +103,13 @@ npm install -g context-mode
103
103
  }
104
104
  ```
105
105
 
106
- **Step 4 — Restart Gemini CLI.** On first run, a `GEMINI.md` routing instructions file is auto-created in your project root. This works alongside hooks as a parallel enforcement layer — hooks block dangerous commands programmatically, while `GEMINI.md` teaches the model to prefer sandbox tools from the start.
106
+ **Step 4 — Restart Gemini CLI.** On first session start, the sessionstart hook automatically manages `GEMINI.md` routing instructions in your project root:
107
+
108
+ - **File does not exist** — the routing instructions file is written.
109
+ - **File exists without context-mode rules** — routing instructions are appended after your existing content.
110
+ - **File already contains context-mode rules** — skipped (idempotent, no duplicate content).
111
+
112
+ This works alongside hooks as a parallel enforcement layer — hooks block dangerous commands programmatically, while `GEMINI.md` teaches the model to prefer sandbox tools from the start.
107
113
 
108
114
  > **Why hooks matter:** Without hooks, context-mode relies on `GEMINI.md` instructions alone (~60% compliance). The model sometimes follows them, but regularly runs raw `curl`, reads large files directly, or dumps unprocessed output into context — a single unrouted Playwright snapshot (56 KB) wipes out an entire session's savings. With hooks, every tool call is intercepted before execution — dangerous commands are blocked, and routing guidance is injected in real-time. This is the difference between ~60% and ~98% context savings.
109
115
 
@@ -150,7 +156,13 @@ npm install -g context-mode
150
156
  }
151
157
  ```
152
158
 
153
- **Step 4 — Restart VS Code.** On first run, a `.github/copilot-instructions.md` routing instructions file is auto-created in your project. This works alongside hooks as a parallel enforcement layer — hooks intercept tool calls programmatically, while `copilot-instructions.md` guides the model's tool selection from session start.
159
+ **Step 4 — Restart VS Code.** On first session start, the sessionstart hook automatically manages `.github/copilot-instructions.md` routing instructions in your project:
160
+
161
+ - **File does not exist** — `.github/` is created and the routing instructions file is written.
162
+ - **File exists without context-mode rules** — routing instructions are appended after your existing content, preserving project-level coding standards.
163
+ - **File already contains context-mode rules** — skipped (idempotent, no duplicate content).
164
+
165
+ This works alongside hooks as a parallel enforcement layer — hooks intercept tool calls programmatically, while `copilot-instructions.md` guides the model's tool selection from session start.
154
166
 
155
167
  > **Why hooks matter:** Without hooks, `copilot-instructions.md` guides the model but can't block commands. A single unrouted Playwright snapshot (56 KB) or `gh issue list` (59 KB) wipes out minutes of context savings. With hooks, these calls are intercepted and redirected to the sandbox before they execute.
156
168
 
@@ -158,6 +170,61 @@ Full hook config including PreCompact: [`configs/vscode-copilot/hooks.json`](con
158
170
 
159
171
  </details>
160
172
 
173
+ <details>
174
+ <summary><strong>Cursor</strong> <sup>(Beta)</sup></summary>
175
+
176
+ **Step 1 — Install globally:**
177
+
178
+ ```bash
179
+ npm install -g context-mode
180
+ ```
181
+
182
+ **Step 2 — Register the MCP server.** Create `.cursor/mcp.json` in your project root or `~/.cursor/mcp.json` for a global install:
183
+
184
+ ```json
185
+ {
186
+ "mcpServers": {
187
+ "context-mode": {
188
+ "command": "context-mode"
189
+ }
190
+ }
191
+ }
192
+ ```
193
+
194
+ **Step 3 — Add native Cursor hooks.** Cursor v1 support uses native `.cursor/hooks.json` or `~/.cursor/hooks.json` only. Create either path with:
195
+
196
+ ```json
197
+ {
198
+ "version": 1,
199
+ "hooks": {
200
+ "preToolUse": [
201
+ {
202
+ "command": "context-mode hook cursor pretooluse",
203
+ "matcher": "Shell|Read|Grep|WebFetch|Task|MCP:ctx_execute|MCP:ctx_execute_file|MCP:ctx_batch_execute"
204
+ }
205
+ ],
206
+ "postToolUse": [
207
+ {
208
+ "command": "context-mode hook cursor posttooluse"
209
+ }
210
+ ]
211
+ }
212
+ }
213
+ ```
214
+
215
+ Note: the `preToolUse` hook matcher is optional. If you don't provide it, the hook will fire on all tools.
216
+
217
+ **Step 4 — Restart Cursor or open a new agent session.** On first MCP server startup, routing instructions are auto-written to your project (same mechanism as Codex CLI).
218
+
219
+ > **Native Cursor scope:** `preToolUse` and `postToolUse` are supported. `sessionStart` is documented by Cursor but currently rejected by their validator ([forum report](https://forum.cursor.com/t/unknown-hook-type-sessionstart/149566)), so routing instructions are delivered via MCP server startup instead.
220
+ >
221
+ > **Config precedence:** project `.cursor/hooks.json` overrides `~/.cursor/hooks.json`.
222
+
223
+ Full native hook config: [`configs/cursor/hooks.json`](configs/cursor/hooks.json)
224
+ Example MCP registration: [`configs/cursor/mcp.json`](configs/cursor/mcp.json)
225
+
226
+ </details>
227
+
161
228
  <details>
162
229
  <summary><strong>OpenCode</strong> <sup>(Beta)</sup></summary>
163
230
 
@@ -184,7 +251,13 @@ npm install -g context-mode
184
251
 
185
252
  The `mcp` entry gives you the 6 sandbox tools. The `plugin` entry enables hooks — OpenCode calls the plugin's TypeScript functions directly before and after each tool execution, blocking dangerous commands (like raw `curl`) and enforcing sandbox routing.
186
253
 
187
- **Step 3 — Restart OpenCode.** On first run, an `AGENTS.md` routing instructions file is auto-created in your project root. This works alongside the plugin as a parallel enforcement layer — the plugin intercepts tool calls at runtime, while `AGENTS.md` guides the model's tool preferences from session start.
254
+ **Step 3 — Restart OpenCode.** On first plugin init, the plugin automatically manages `AGENTS.md` routing instructions in your project root:
255
+
256
+ - **File does not exist** — the routing instructions file is written.
257
+ - **File exists without context-mode rules** — routing instructions are appended after your existing content.
258
+ - **File already contains context-mode rules** — skipped (idempotent, no duplicate content).
259
+
260
+ This works alongside the plugin as a parallel enforcement layer — the plugin intercepts tool calls at runtime, while `AGENTS.md` guides the model's tool preferences from session start.
188
261
 
189
262
  > **Why the plugin matters:** Without the `plugin` entry, context-mode has no way to intercept tool calls. The model can run raw `curl`, read large files directly, or dump unprocessed output into context — ignoring `AGENTS.md` instructions. With the plugin, `tool.execute.before` fires on every tool call and blocks or redirects data-heavy commands before they execute. The `experimental.session.compacting` hook builds and injects resume snapshots when the conversation compacts, preserving session state.
190
263
  >
@@ -278,15 +351,15 @@ Context Mode captures every meaningful event during your session and persists th
278
351
 
279
352
  Session continuity requires 4 hooks working together:
280
353
 
281
- | Hook | Role | Claude Code | Gemini CLI | VS Code Copilot | OpenCode | Codex CLI |
282
- |---|---|:---:|:---:|:---:|:---:|:---:|
283
- | **PostToolUse** | Captures events after each tool call | Yes | Yes | Yes | Plugin | -- |
284
- | **UserPromptSubmit** | Captures user decisions and corrections | Yes | -- | -- | -- | -- |
285
- | **PreCompact** | Builds snapshot before compaction | Yes | Yes | Yes | Plugin | -- |
286
- | **SessionStart** | Restores state after compaction | Yes | Yes | Yes | -- | -- |
287
- | | **Session completeness** | **Full** | **High** | **High** | **High** | **--** |
354
+ | Hook | Role | Claude Code | Gemini CLI | VS Code Copilot | Cursor | OpenCode | Codex CLI |
355
+ |---|---|:---:|:---:|:---:|:---:|:---:|:---:|
356
+ | **PostToolUse** | Captures events after each tool call | Yes | Yes | Yes | Yes | Plugin | -- |
357
+ | **UserPromptSubmit** | Captures user decisions and corrections | Yes | -- | -- | -- | -- | -- |
358
+ | **PreCompact** | Builds snapshot before compaction | Yes | Yes | Yes | -- | Plugin | -- |
359
+ | **SessionStart** | Restores state after compaction or resume | Yes | Yes | Yes | -- | -- | -- |
360
+ | | **Session completeness** | **Full** | **High** | **High** | **Partial** | **High** | **--** |
288
361
 
289
- > **Note:** Full session continuity (capture + snapshot + restore) works on **Claude Code**, **Gemini CLI**, **VS Code Copilot**, and **OpenCode**. OpenCode uses the `experimental.session.compacting` plugin hook for compaction recovery SessionStart is not yet available ([#14808](https://github.com/sst/opencode/issues/14808)), so startup/resume is not supported. Codex CLI has no hook support, so session tracking is not available.
362
+ > **Note:** Full session continuity (capture + snapshot + restore) works on **Claude Code**, **Gemini CLI**, **VS Code Copilot**, and **OpenCode**. **Cursor** captures tool events via `preToolUse`/`postToolUse`, but `sessionStart` is currently rejected by Cursor's validator ([forum report](https://forum.cursor.com/t/unknown-hook-type-sessionstart/149566)), so session restore after compaction is not available yet. **OpenCode** uses the `experimental.session.compacting` plugin hook for compaction recovery, but SessionStart is not yet available ([#14808](https://github.com/sst/opencode/issues/14808)), so startup/resume is not supported. Codex CLI has no hook support, so session tracking is not available.
290
363
 
291
364
  <details>
292
365
  <summary><strong>What gets captured</strong></summary>
@@ -361,6 +434,8 @@ Detailed event data is also indexed into FTS5 for on-demand retrieval via `searc
361
434
 
362
435
  **VS Code Copilot** — High coverage. Same as Gemini CLI — PostToolUse, PreCompact, and SessionStart all fire. User decisions aren't captured but all tool-level events are.
363
436
 
437
+ **Cursor** — Partial coverage. Native `preToolUse` and `postToolUse` hooks capture tool events. `sessionStart` is documented by Cursor but currently rejected by their validator, so session restore is not available. Routing instructions are delivered via MCP server startup instead.
438
+
364
439
  **OpenCode** — Partial. The TypeScript plugin captures PostToolUse events via `tool.execute.after`, but SessionStart is not yet available ([#14808](https://github.com/sst/opencode/issues/14808)). Events are stored but not automatically restored after compaction. The `AGENTS.md` routing instructions file compensates by re-teaching tool preferences at each session start.
365
440
 
366
441
  **Codex CLI** — No session support. No hooks means no event capture. Each compaction or new session starts fresh. The `AGENTS.md` routing instructions file is the only continuity mechanism.
@@ -369,17 +444,18 @@ Detailed event data is also indexed into FTS5 for on-demand retrieval via `searc
369
444
 
370
445
  ## Platform Compatibility
371
446
 
372
- | Feature | Claude Code | Gemini CLI <sup>(Beta)</sup> | VS Code Copilot <sup>(Beta)</sup> | OpenCode <sup>(Beta)</sup> | Codex CLI <sup>(Beta)</sup> |
373
- |---|:---:|:---:|:---:|:---:|:---:|
374
- | MCP Server | Yes | Yes | Yes | Yes | Yes |
375
- | PreToolUse Hook | Yes | Yes | Yes | Plugin | -- |
376
- | PostToolUse Hook | Yes | Yes | Yes | Plugin | -- |
377
- | SessionStart Hook | Yes | Yes | Yes | -- | -- |
378
- | Can Modify Args | Yes | Yes | Yes | Plugin | -- |
379
- | Can Block Tools | Yes | Yes | Yes | Plugin | -- |
380
- | Utility Commands (ctx) | Yes | Yes | Yes | Yes | Yes |
381
- | Slash Commands | Yes | -- | -- | -- | -- |
382
- | Plugin Marketplace | Yes | -- | -- | -- | -- |
447
+ | Feature | Claude Code | Gemini CLI <sup>(Beta)</sup> | VS Code Copilot <sup>(Beta)</sup> | Cursor <sup>(Beta)</sup> | OpenCode <sup>(Beta)</sup> | Codex CLI <sup>(Beta)</sup> |
448
+ |---|:---:|:---:|:---:|:---:|:---:|:---:|
449
+ | MCP Server | Yes | Yes | Yes | Yes | Yes | Yes |
450
+ | PreToolUse Hook | Yes | Yes | Yes | Yes | Plugin | -- |
451
+ | PostToolUse Hook | Yes | Yes | Yes | Yes | Plugin | -- |
452
+ | SessionStart Hook | Yes | Yes | Yes | -- | -- | -- |
453
+ | PreCompact Hook | Yes | Yes | Yes | -- | Plugin | -- |
454
+ | Can Modify Args | Yes | Yes | Yes | Yes | Plugin | -- |
455
+ | Can Block Tools | Yes | Yes | Yes | Yes | Plugin | -- |
456
+ | Utility Commands (ctx) | Yes | Yes | Yes | Yes | Yes | Yes |
457
+ | Slash Commands | Yes | -- | -- | -- | -- | -- |
458
+ | Plugin Marketplace | Yes | -- | -- | -- | -- | -- |
383
459
 
384
460
  > **OpenCode** uses a TypeScript plugin paradigm — hooks run as in-process functions via `tool.execute.before`, `tool.execute.after`, and `experimental.session.compacting`, providing the same routing enforcement and session continuity as shell-based hooks. SessionStart is not yet available ([#14808](https://github.com/sst/opencode/issues/14808)), but compaction recovery works via the plugin's compacting hook.
385
461
  >
@@ -394,6 +470,7 @@ Hooks intercept tool calls programmatically — they can block dangerous command
394
470
  | Claude Code | Yes (auto) | [`CLAUDE.md`](configs/claude-code/CLAUDE.md) | **~98% saved** | ~60% saved |
395
471
  | Gemini CLI | Yes | [`GEMINI.md`](configs/gemini-cli/GEMINI.md) | **~98% saved** | ~60% saved |
396
472
  | VS Code Copilot | Yes | [`copilot-instructions.md`](configs/vscode-copilot/copilot-instructions.md) | **~98% saved** | ~60% saved |
473
+ | Cursor | Yes | -- | **~98% saved** | Manual tool choice |
397
474
  | OpenCode | Plugin | [`AGENTS.md`](configs/opencode/AGENTS.md) | **~98% saved** | ~60% saved |
398
475
  | Codex CLI | -- | [`AGENTS.md`](configs/codex/AGENTS.md) | -- | ~60% saved |
399
476
 
@@ -34,6 +34,10 @@ export declare class ClaudeCodeAdapter implements HookAdapter {
34
34
  readSettings(): Record<string, unknown> | null;
35
35
  writeSettings(settings: Record<string, unknown>): void;
36
36
  validateHooks(pluginRoot: string): DiagnosticResult[];
37
+ /** Read plugin hooks from hooks/hooks.json or .claude-plugin/hooks/hooks.json */
38
+ private readPluginHooks;
39
+ /** Check if a hook type is configured in either settings.json or plugin hooks */
40
+ private checkHookType;
37
41
  checkPluginRegistration(): DiagnosticResult;
38
42
  getInstalledVersion(): string;
39
43
  configureAllHooks(pluginRoot: string): string[];
@@ -240,49 +240,65 @@ export class ClaudeCodeAdapter {
240
240
  return results;
241
241
  }
242
242
  const hooks = settings.hooks;
243
- // Check PreToolUse
244
- const preToolUse = hooks?.PreToolUse;
245
- if (preToolUse && preToolUse.length > 0) {
246
- const hasHook = preToolUse.some((entry) => isContextModeHook(entry, HOOK_TYPES.PRE_TOOL_USE));
247
- results.push({
248
- check: "PreToolUse hook",
249
- status: hasHook ? "pass" : "fail",
250
- message: hasHook
251
- ? "PreToolUse hook configured"
252
- : "PreToolUse exists but does not point to pretooluse.mjs",
253
- fix: hasHook ? undefined : "context-mode upgrade",
254
- });
255
- }
256
- else {
257
- results.push({
258
- check: "PreToolUse hook",
259
- status: "fail",
260
- message: "No PreToolUse hooks found",
261
- fix: "context-mode upgrade",
262
- });
243
+ // Read plugin hooks.json as fallback (Issue #94: plugin installs
244
+ // register hooks in hooks/hooks.json, not in settings.json)
245
+ const pluginHooks = this.readPluginHooks(pluginRoot);
246
+ // Check PreToolUse (settings.json first, then plugin hooks.json fallback)
247
+ const hasPreToolUse = this.checkHookType(hooks, pluginHooks, HOOK_TYPES.PRE_TOOL_USE);
248
+ results.push({
249
+ check: "PreToolUse hook",
250
+ status: hasPreToolUse ? "pass" : "fail",
251
+ message: hasPreToolUse
252
+ ? "PreToolUse hook configured"
253
+ : "No PreToolUse hooks found",
254
+ fix: hasPreToolUse ? undefined : "context-mode upgrade",
255
+ });
256
+ // Check SessionStart (settings.json first, then plugin hooks.json fallback)
257
+ const hasSessionStart = this.checkHookType(hooks, pluginHooks, HOOK_TYPES.SESSION_START);
258
+ results.push({
259
+ check: "SessionStart hook",
260
+ status: hasSessionStart ? "pass" : "fail",
261
+ message: hasSessionStart
262
+ ? "SessionStart hook configured"
263
+ : "No SessionStart hooks found",
264
+ fix: hasSessionStart ? undefined : "context-mode upgrade",
265
+ });
266
+ return results;
267
+ }
268
+ /** Read plugin hooks from hooks/hooks.json or .claude-plugin/hooks/hooks.json */
269
+ readPluginHooks(pluginRoot) {
270
+ const candidates = [
271
+ join(pluginRoot, "hooks", "hooks.json"),
272
+ join(pluginRoot, ".claude-plugin", "hooks", "hooks.json"),
273
+ ];
274
+ for (const candidate of candidates) {
275
+ try {
276
+ const raw = readFileSync(candidate, "utf-8");
277
+ const parsed = JSON.parse(raw);
278
+ if (parsed.hooks)
279
+ return parsed.hooks;
280
+ }
281
+ catch { /* not available */ }
263
282
  }
264
- // Check SessionStart
265
- const sessionStart = hooks?.SessionStart;
266
- if (sessionStart && sessionStart.length > 0) {
267
- const hasHook = sessionStart.some((entry) => isContextModeHook(entry, HOOK_TYPES.SESSION_START));
268
- results.push({
269
- check: "SessionStart hook",
270
- status: hasHook ? "pass" : "fail",
271
- message: hasHook
272
- ? "SessionStart hook configured"
273
- : "SessionStart exists but does not point to sessionstart.mjs",
274
- fix: hasHook ? undefined : "context-mode upgrade",
275
- });
283
+ return undefined;
284
+ }
285
+ /** Check if a hook type is configured in either settings.json or plugin hooks */
286
+ checkHookType(settingsHooks, pluginHooks, hookType) {
287
+ // Check settings.json
288
+ const fromSettings = settingsHooks?.[hookType];
289
+ if (fromSettings && fromSettings.length > 0) {
290
+ if (fromSettings.some((entry) => isContextModeHook(entry, hookType))) {
291
+ return true;
292
+ }
276
293
  }
277
- else {
278
- results.push({
279
- check: "SessionStart hook",
280
- status: "fail",
281
- message: "No SessionStart hooks found",
282
- fix: "context-mode upgrade",
283
- });
294
+ // Fallback: check plugin hooks.json
295
+ const fromPlugin = pluginHooks?.[hookType];
296
+ if (fromPlugin && fromPlugin.length > 0) {
297
+ if (fromPlugin.some((entry) => isContextModeHook(entry, hookType))) {
298
+ return true;
299
+ }
284
300
  }
285
- return results;
301
+ return false;
286
302
  }
287
303
  checkPluginRegistration() {
288
304
  const settings = this.readSettings();
@@ -0,0 +1,4 @@
1
+ /**
2
+ * adapters/cursor/config — Thin re-exports from CursorAdapter.
3
+ */
4
+ export { CursorAdapter } from "./index.js";
@@ -0,0 +1,4 @@
1
+ /**
2
+ * adapters/cursor/config — Thin re-exports from CursorAdapter.
3
+ */
4
+ export { CursorAdapter } from "./index.js";
@@ -0,0 +1,40 @@
1
+ /**
2
+ * adapters/cursor/hooks — Cursor hook definitions and config helpers.
3
+ *
4
+ * Cursor native hook config lives in `.cursor/hooks.json` or `~/.cursor/hooks.json`.
5
+ * Unlike Claude/Gemini/VS Code Copilot, each hook entry is a flat object rather
6
+ * than a `{ matcher, hooks: [...] }` wrapper.
7
+ */
8
+ /** Cursor hook type names. */
9
+ export declare const HOOK_TYPES: {
10
+ readonly PRE_TOOL_USE: "preToolUse";
11
+ readonly POST_TOOL_USE: "postToolUse";
12
+ readonly SESSION_START: "sessionStart";
13
+ };
14
+ export type HookType = (typeof HOOK_TYPES)[keyof typeof HOOK_TYPES];
15
+ /** Map of hook types to their script file names. */
16
+ export declare const HOOK_SCRIPTS: Record<HookType, string>;
17
+ /** Canonical Cursor-native matchers for tools context-mode routes proactively. */
18
+ export declare const PRE_TOOL_USE_MATCHERS: readonly ["Shell", "Read", "Grep", "WebFetch", "mcp_web_fetch", "mcp_fetch_tool", "Task", "MCP:ctx_execute", "MCP:ctx_execute_file", "MCP:ctx_batch_execute"];
19
+ export declare const PRE_TOOL_USE_MATCHER_PATTERN: string;
20
+ /** Required hooks for native Cursor support. */
21
+ export declare const REQUIRED_HOOKS: HookType[];
22
+ /** Optional hooks that improve behavior but aren't strictly required. */
23
+ export declare const OPTIONAL_HOOKS: HookType[];
24
+ /** Minimal native Cursor hook entry shape. */
25
+ export interface CursorHookCommandEntry {
26
+ type?: string;
27
+ command?: string;
28
+ matcher?: string;
29
+ timeout?: number;
30
+ loop_limit?: number | null;
31
+ failClosed?: boolean;
32
+ }
33
+ /** Check whether a native Cursor hook entry points to context-mode. */
34
+ export declare function isContextModeHook(entry: CursorHookCommandEntry | {
35
+ hooks?: Array<{
36
+ command?: string;
37
+ }>;
38
+ }, hookType: HookType): boolean;
39
+ /** Build the CLI dispatcher command for a Cursor hook type. */
40
+ export declare function buildHookCommand(hookType: HookType): string;
@@ -0,0 +1,53 @@
1
+ /**
2
+ * adapters/cursor/hooks — Cursor hook definitions and config helpers.
3
+ *
4
+ * Cursor native hook config lives in `.cursor/hooks.json` or `~/.cursor/hooks.json`.
5
+ * Unlike Claude/Gemini/VS Code Copilot, each hook entry is a flat object rather
6
+ * than a `{ matcher, hooks: [...] }` wrapper.
7
+ */
8
+ /** Cursor hook type names. */
9
+ export const HOOK_TYPES = {
10
+ PRE_TOOL_USE: "preToolUse",
11
+ POST_TOOL_USE: "postToolUse",
12
+ SESSION_START: "sessionStart",
13
+ };
14
+ /** Map of hook types to their script file names. */
15
+ export const HOOK_SCRIPTS = {
16
+ [HOOK_TYPES.PRE_TOOL_USE]: "pretooluse.mjs",
17
+ [HOOK_TYPES.POST_TOOL_USE]: "posttooluse.mjs",
18
+ [HOOK_TYPES.SESSION_START]: "sessionstart.mjs",
19
+ };
20
+ /** Canonical Cursor-native matchers for tools context-mode routes proactively. */
21
+ export const PRE_TOOL_USE_MATCHERS = [
22
+ "Shell",
23
+ "Read",
24
+ "Grep",
25
+ "WebFetch",
26
+ "mcp_web_fetch",
27
+ "mcp_fetch_tool",
28
+ "Task",
29
+ "MCP:ctx_execute",
30
+ "MCP:ctx_execute_file",
31
+ "MCP:ctx_batch_execute",
32
+ ];
33
+ export const PRE_TOOL_USE_MATCHER_PATTERN = PRE_TOOL_USE_MATCHERS.join("|");
34
+ /** Required hooks for native Cursor support. */
35
+ export const REQUIRED_HOOKS = [
36
+ HOOK_TYPES.PRE_TOOL_USE,
37
+ ];
38
+ /** Optional hooks that improve behavior but aren't strictly required. */
39
+ export const OPTIONAL_HOOKS = [HOOK_TYPES.POST_TOOL_USE];
40
+ /** Check whether a native Cursor hook entry points to context-mode. */
41
+ export function isContextModeHook(entry, hookType) {
42
+ const scriptName = HOOK_SCRIPTS[hookType];
43
+ const cliCommand = buildHookCommand(hookType);
44
+ if ("command" in entry) {
45
+ return entry.command?.includes(scriptName) || entry.command?.includes(cliCommand) || false;
46
+ }
47
+ const wrappedEntry = entry;
48
+ return (wrappedEntry.hooks?.some((hook) => hook.command?.includes(scriptName) || hook.command?.includes(cliCommand)) ?? false);
49
+ }
50
+ /** Build the CLI dispatcher command for a Cursor hook type. */
51
+ export function buildHookCommand(hookType) {
52
+ return `context-mode hook cursor ${hookType.toLowerCase()}`;
53
+ }
@@ -0,0 +1,40 @@
1
+ /**
2
+ * adapters/cursor — Cursor platform adapter.
3
+ *
4
+ * Native Cursor hooks use lower-camel hook names and flat command entries in
5
+ * `.cursor/hooks.json` / `~/.cursor/hooks.json`.
6
+ */
7
+ import type { HookAdapter, HookParadigm, PlatformCapabilities, DiagnosticResult, PreToolUseEvent, PostToolUseEvent, SessionStartEvent, PreToolUseResponse, PostToolUseResponse, SessionStartResponse, HookRegistration, RoutingInstructionsConfig } from "../types.js";
8
+ export declare class CursorAdapter implements HookAdapter {
9
+ readonly name = "Cursor";
10
+ readonly paradigm: HookParadigm;
11
+ readonly capabilities: PlatformCapabilities;
12
+ parsePreToolUseInput(raw: unknown): PreToolUseEvent;
13
+ parsePostToolUseInput(raw: unknown): PostToolUseEvent;
14
+ parseSessionStartInput(raw: unknown): SessionStartEvent;
15
+ formatPreToolUseResponse(response: PreToolUseResponse): unknown;
16
+ formatPostToolUseResponse(response: PostToolUseResponse): unknown;
17
+ formatSessionStartResponse(response: SessionStartResponse): unknown;
18
+ getSettingsPath(): string;
19
+ getSessionDir(): string;
20
+ getSessionDBPath(projectDir: string): string;
21
+ getSessionEventsPath(projectDir: string): string;
22
+ generateHookConfig(_pluginRoot: string): HookRegistration;
23
+ readSettings(): Record<string, unknown> | null;
24
+ writeSettings(settings: Record<string, unknown>): void;
25
+ validateHooks(_pluginRoot: string): DiagnosticResult[];
26
+ checkPluginRegistration(): DiagnosticResult;
27
+ getInstalledVersion(): string;
28
+ configureAllHooks(_pluginRoot: string): string[];
29
+ backupSettings(): string | null;
30
+ setHookPermissions(pluginRoot: string): string[];
31
+ updatePluginRegistry(_pluginRoot: string, _version: string): void;
32
+ getRoutingInstructionsConfig(): RoutingInstructionsConfig;
33
+ writeRoutingInstructions(_projectDir: string, _pluginRoot: string): string | null;
34
+ private getCandidateHookConfigPaths;
35
+ private getProjectDir;
36
+ private extractSessionId;
37
+ private loadNativeHookConfig;
38
+ private hasClaudeCompatibilityHooks;
39
+ private upsertHookEntry;
40
+ }