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.
- package/.claude-plugin/marketplace.json +2 -2
- package/.claude-plugin/plugin.json +1 -1
- package/README.md +99 -22
- package/build/adapters/claude-code/index.d.ts +4 -0
- package/build/adapters/claude-code/index.js +56 -40
- package/build/adapters/cursor/config.d.ts +4 -0
- package/build/adapters/cursor/config.js +4 -0
- package/build/adapters/cursor/hooks.d.ts +40 -0
- package/build/adapters/cursor/hooks.js +53 -0
- package/build/adapters/cursor/index.d.ts +40 -0
- package/build/adapters/cursor/index.js +413 -0
- package/build/adapters/detect.d.ts +1 -0
- package/build/adapters/detect.js +19 -0
- package/build/adapters/opencode/index.js +3 -1
- package/build/adapters/types.d.ts +1 -1
- package/build/cli.js +5 -0
- package/build/opencode-plugin.js +8 -0
- package/build/server.js +7 -3
- package/build/session/db.js +21 -0
- package/build/sync/batcher.d.ts +23 -0
- package/build/sync/batcher.js +74 -0
- package/build/sync/cloud-post.d.ts +12 -0
- package/build/sync/cloud-post.js +38 -0
- package/build/sync/config.d.ts +4 -0
- package/build/sync/config.js +64 -0
- package/build/sync/index.d.ts +12 -0
- package/build/sync/index.js +55 -0
- package/build/sync/sanitizer.d.ts +13 -0
- package/build/sync/sanitizer.js +86 -0
- package/build/sync/sender.d.ts +15 -0
- package/build/sync/sender.js +30 -0
- package/build/sync/types.d.ts +31 -0
- package/build/sync/types.js +1 -0
- package/cli.bundle.mjs +89 -88
- package/configs/cursor/hooks.json +16 -0
- package/configs/cursor/mcp.json +7 -0
- package/hooks/core/formatters.mjs +16 -0
- package/hooks/core/routing.mjs +18 -4
- package/hooks/cursor/posttooluse.mjs +70 -0
- package/hooks/cursor/pretooluse.mjs +26 -0
- package/hooks/cursor/sessionstart.mjs +97 -0
- package/hooks/formatters/cursor.mjs +37 -0
- package/hooks/gemini-cli/sessionstart.mjs +7 -0
- package/hooks/session-helpers.mjs +22 -0
- package/hooks/vscode-copilot/sessionstart.mjs +7 -0
- package/package.json +3 -2
- package/server.bundle.mjs +67 -66
- package/skills/context-mode/SKILL.md +7 -9
- package/skills/ctx-cloud-setup/SKILL.md +98 -0
- package/skills/ctx-cloud-status/SKILL.md +96 -0
- package/skills/ctx-doctor/SKILL.md +1 -1
- package/skills/ctx-stats/SKILL.md +1 -1
- 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.
|
|
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.
|
|
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.
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
|
379
|
-
| Can
|
|
380
|
-
|
|
|
381
|
-
|
|
|
382
|
-
|
|
|
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
|
-
//
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
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
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
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
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
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
|
|
301
|
+
return false;
|
|
286
302
|
}
|
|
287
303
|
checkPluginRegistration() {
|
|
288
304
|
const settings = this.readSettings();
|
|
@@ -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
|
+
}
|