@mnemonik/cursor-hooks 0.1.0

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.
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Irreducible deny-floor for catastrophic, irreversible commands.
3
+ * Kept in sync with @mnemonik/codex-hooks/src/lib/shellTokens.ts and
4
+ * @mnemonik/claude-code-hooks/src/lib/shellTokens.ts — see those files
5
+ * for the full rationale.
6
+ *
7
+ * Phase 1 / 0.1.0 of cursor-hooks: this is the ONE place the dispatcher
8
+ * does local pattern matching. Every other policy decision lives behind
9
+ * /api/v1/hooks/policy-reminder (Bash) or /api/v1/hooks/mcp-precheck (MCP).
10
+ */
11
+ export const IRREDUCIBLE_DENY = [
12
+ {
13
+ name: 'rm-rf-root-or-home',
14
+ pattern: /\brm\s+-[a-zA-Z]*r[a-zA-Z]*f?[a-zA-Z]*\s+(?:\/|~|\$HOME)(?![A-Za-z0-9/_-])/,
15
+ },
16
+ {
17
+ name: 'dd-of-whole-disk',
18
+ pattern: /\bdd\b[^|;&]*\bof=\/dev\/(?:sd[a-z]|nvme\d+n\d+|hd[a-z]|vd[a-z])(?![A-Za-z0-9])/,
19
+ },
20
+ {
21
+ name: 'mkfs-whole-disk',
22
+ pattern: /\bmkfs(?:\.[a-z0-9]+)?\b[^|;&]*?\s\/dev\/(?:sd[a-z]|nvme\d+n\d+|hd[a-z]|vd[a-z])(?![A-Za-z0-9])/,
23
+ },
24
+ ];
25
+ export function matchIrreducibleDeny(command) {
26
+ for (const { name, pattern } of IRREDUCIBLE_DENY) {
27
+ if (pattern.test(command))
28
+ return name;
29
+ }
30
+ return null;
31
+ }
32
+ //# sourceMappingURL=shellTokens.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shellTokens.js","sourceRoot":"","sources":["../../src/lib/shellTokens.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,MAAM,CAAC,MAAM,gBAAgB,GAAqD;IAChF;QACE,IAAI,EAAE,oBAAoB;QAC1B,OAAO,EAAE,4EAA4E;KACtF;IACD;QACE,IAAI,EAAE,kBAAkB;QACxB,OAAO,EAAE,iFAAiF;KAC3F;IACD;QACE,IAAI,EAAE,iBAAiB;QACvB,OAAO,EACL,iGAAiG;KACpG;CACF,CAAC;AAEF,MAAM,UAAU,oBAAoB,CAAC,OAAe;IAClD,KAAK,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,gBAAgB,EAAE,CAAC;QACjD,IAAI,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC;YAAE,OAAO,IAAI,CAAC;IACzC,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -0,0 +1,125 @@
1
+ export type CursorHookEvent = 'sessionStart' | 'beforeSubmitPrompt' | 'preToolUse' | 'postToolUse' | 'beforeShellExecution' | 'beforeMCPExecution' | 'afterMCPExecution' | 'afterFileEdit' | 'stop' | 'subagentStart' | 'subagentStop' | 'preCompact';
2
+ /**
3
+ * Stdin payload Cursor delivers to a hook. Per cursor.com/docs/hooks (verified
4
+ * 2026-05-12). Common fields appear on every event; per-event fields are
5
+ * union-typed and accessed by the dispatcher branch that recognises them.
6
+ */
7
+ export interface CursorHookInput {
8
+ conversation_id?: string;
9
+ generation_id?: string;
10
+ hook_event_name: CursorHookEvent;
11
+ model?: string;
12
+ cursor_version?: string;
13
+ workspace_roots?: string[];
14
+ user_email?: string;
15
+ transcript_path?: string;
16
+ cwd?: string;
17
+ prompt?: string;
18
+ context_usage_percent?: number;
19
+ messages_to_compact?: number;
20
+ is_first_compaction?: boolean;
21
+ tool_name?: string;
22
+ tool_input?: Record<string, unknown>;
23
+ tool_output?: unknown;
24
+ command?: string;
25
+ mcp_tool?: string;
26
+ mcp_args?: Record<string, unknown>;
27
+ mcp_result?: unknown;
28
+ file_path?: string;
29
+ followup_count?: number;
30
+ subagent_id?: string;
31
+ subagent_type?: string;
32
+ task?: string;
33
+ parent_conversation_id?: string;
34
+ tool_call_id?: string;
35
+ subagent_model?: string;
36
+ is_parallel_worker?: boolean;
37
+ git_branch?: string;
38
+ status?: string;
39
+ duration_ms?: number;
40
+ }
41
+ /**
42
+ * Cursor accepts a small family of output shapes depending on the event.
43
+ * Rather than encode each precisely, we expose a permissive union and rely
44
+ * on the output builders in `cursorOutput.ts` to produce well-formed shapes
45
+ * per event.
46
+ */
47
+ export interface CursorHookOutput {
48
+ permission?: 'allow' | 'deny' | 'ask';
49
+ user_message?: string;
50
+ agent_message?: string;
51
+ followup_message?: string;
52
+ additional_context?: string;
53
+ continue?: boolean;
54
+ env?: Record<string, string>;
55
+ }
56
+ export type BypassType = 'typo' | 'formatting' | 'regenerated' | 'already_grounded' | 'other';
57
+ export interface BypassEnvelope {
58
+ active: boolean;
59
+ type: BypassType | null;
60
+ detail: string | null;
61
+ invalidReason: string | null;
62
+ }
63
+ /**
64
+ * Server snapshot response (existing /api/v1/hooks/snapshot endpoint —
65
+ * host-agnostic). Mirrors codex-hooks types.
66
+ */
67
+ export interface SnapshotResponse {
68
+ ok: boolean;
69
+ reason?: 'unauthorized' | 'no_project' | 'no_active_session';
70
+ coveredFiles: string[];
71
+ editedFiles: string[];
72
+ policies?: {
73
+ forbiddenCommand: Array<{
74
+ pattern: string;
75
+ description: string;
76
+ }>;
77
+ mustConfirm: Array<{
78
+ pattern: string;
79
+ description: string;
80
+ replacement: string | null;
81
+ }>;
82
+ };
83
+ sessionsMerged: number;
84
+ now: number;
85
+ }
86
+ export interface HookContextResponse {
87
+ ok: boolean;
88
+ reason?: 'unauthorized' | 'no_project' | 'invalid' | 'unavailable';
89
+ additionalContext?: string;
90
+ systemMessage?: string;
91
+ continuationReason?: string;
92
+ contextBytes?: number;
93
+ }
94
+ export interface PolicyReminderResponse {
95
+ ok: boolean;
96
+ reason?: 'unauthorized' | 'no_project' | 'no_context' | 'lookup_failed';
97
+ policies: Array<{
98
+ id: string;
99
+ kind: string;
100
+ pattern: string;
101
+ description: string | null;
102
+ replacement: string | null;
103
+ }>;
104
+ }
105
+ /**
106
+ * Response from /api/v1/hooks/mcp-precheck (new in Phase 1).
107
+ */
108
+ export interface McpPrecheckResponse {
109
+ ok: boolean;
110
+ verdict: 'allow' | 'deny' | 'ask';
111
+ reason: string | null;
112
+ agent_message: string | null;
113
+ cacheHint?: {
114
+ ttlSeconds: number;
115
+ } | null;
116
+ }
117
+ /**
118
+ * Minimal config — apiKey + server only. Gate enforcement modes are
119
+ * package-level constants in `behavior.ts`, NOT user config.
120
+ */
121
+ export interface HookConfig {
122
+ apiKey: string | null;
123
+ server: string;
124
+ }
125
+ export declare const DEFAULT_SERVER = "https://api.mnemonik.dev";
@@ -0,0 +1,2 @@
1
+ export const DEFAULT_SERVER = 'https://api.mnemonik.dev';
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/lib/types.ts"],"names":[],"mappings":"AAiJA,MAAM,CAAC,MAAM,cAAc,GAAG,0BAA0B,CAAC"}
package/package.json ADDED
@@ -0,0 +1,33 @@
1
+ {
2
+ "name": "@mnemonik/cursor-hooks",
3
+ "version": "0.1.0",
4
+ "description": "Cursor IDE hooks for Mnemonik memory awareness and host-side grounding gates. Hooks only: does not install skills, rules, AGENTS.md, .mnemonik.json, or MCP config.",
5
+ "type": "module",
6
+ "bin": {
7
+ "mnemonik-cursor-hooks": "dist/install.js"
8
+ },
9
+ "main": "dist/install.js",
10
+ "files": [
11
+ "dist"
12
+ ],
13
+ "scripts": {
14
+ "build": "tsc",
15
+ "typecheck": "tsc --noEmit",
16
+ "test": "vitest run",
17
+ "test:watch": "vitest"
18
+ },
19
+ "engines": {
20
+ "node": ">=20"
21
+ },
22
+ "keywords": [
23
+ "mnemonik",
24
+ "cursor",
25
+ "hooks"
26
+ ],
27
+ "license": "MIT",
28
+ "devDependencies": {
29
+ "@types/node": "^20.19.40",
30
+ "typescript": "^5.3.3",
31
+ "vitest": "^4.1.5"
32
+ }
33
+ }