@mnemonik/claude-code-hooks 0.9.21 → 0.9.23

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,115 @@
1
+ import { createHash, randomUUID } from 'node:crypto';
2
+ import { link, mkdir, readFile, rename, unlink, writeFile } from 'node:fs/promises';
3
+ import { homedir } from 'node:os';
4
+ import { join } from 'node:path';
5
+ function errorCode(error) {
6
+ return error && typeof error === 'object' && 'code' in error
7
+ ? String(error.code)
8
+ : undefined;
9
+ }
10
+ function lifecyclePath(input) {
11
+ const key = createHash('sha256')
12
+ .update(input.server.replace(/\/$/, ''))
13
+ .update('\0')
14
+ .update(input.cwd)
15
+ .update('\0')
16
+ .update(input.sessionId)
17
+ .digest('hex');
18
+ return join(homedir(), '.mnemonik', 'hooks', 'claude-code-hooks', 'session-incarnations', `${key}.json`);
19
+ }
20
+ export async function storeSessionLifecycleToken(input) {
21
+ const path = lifecyclePath(input);
22
+ const tmp = `${path}.${process.pid}.tmp`;
23
+ try {
24
+ await mkdir(join(path, '..'), { recursive: true, mode: 0o700 });
25
+ await writeFile(tmp, JSON.stringify({ lifecycleToken: input.lifecycleToken, receivedAt: Date.now() }), { encoding: 'utf8', mode: 0o600 });
26
+ await rename(tmp, path);
27
+ return true;
28
+ }
29
+ catch {
30
+ await unlink(tmp).catch(() => { });
31
+ return false;
32
+ }
33
+ }
34
+ /**
35
+ * Read the token that existed when this hook subprocess started. If a newer
36
+ * SessionStart overwrote the file while an older SessionEnd was delayed, the
37
+ * local receive timestamp makes the old process fail closed instead of reading
38
+ * and presenting the new incarnation's capability. Equality also fails closed:
39
+ * Date.now() has millisecond resolution, so a newer write can share the hook's
40
+ * captured start timestamp.
41
+ */
42
+ export async function readSessionLifecycleToken(input) {
43
+ try {
44
+ const parsed = JSON.parse(await readFile(lifecyclePath(input), 'utf8'));
45
+ if (typeof parsed.lifecycleToken !== 'string' ||
46
+ parsed.lifecycleToken.length === 0 ||
47
+ typeof parsed.receivedAt !== 'number' ||
48
+ parsed.receivedAt >= input.invocationStartedAt) {
49
+ return null;
50
+ }
51
+ return parsed.lifecycleToken;
52
+ }
53
+ catch {
54
+ return null;
55
+ }
56
+ }
57
+ /**
58
+ * Compare-and-remove without a read→unlink TOCTOU. Rename the current record to
59
+ * a unique quarantine path first, then inspect the exact inode we moved. If a
60
+ * resumed SessionStart won the race, restore that newer record only when the
61
+ * canonical path is still absent; hard-link creation is atomic and never
62
+ * overwrites a still-newer token.
63
+ */
64
+ export async function removeSessionLifecycleToken(input) {
65
+ const path = lifecyclePath(input);
66
+ const quarantine = `${path}.${process.pid}.${randomUUID()}.remove`;
67
+ let moved = false;
68
+ try {
69
+ // Confirm the source is readable before moving it. The content is read
70
+ // again from quarantine because another process may replace the path after
71
+ // this check and before rename.
72
+ await readFile(path, 'utf8');
73
+ await rename(path, quarantine);
74
+ moved = true;
75
+ const raw = await readFile(quarantine, 'utf8');
76
+ let matches = false;
77
+ try {
78
+ matches = JSON.parse(raw).lifecycleToken === input.lifecycleToken;
79
+ }
80
+ catch {
81
+ // Malformed/unknown state is never safe to delete; restore it below.
82
+ }
83
+ if (matches) {
84
+ await unlink(quarantine);
85
+ moved = false;
86
+ return;
87
+ }
88
+ try {
89
+ await link(quarantine, path);
90
+ }
91
+ catch (error) {
92
+ if (errorCode(error) !== 'EEXIST')
93
+ throw error;
94
+ }
95
+ await unlink(quarantine);
96
+ moved = false;
97
+ }
98
+ catch {
99
+ if (moved) {
100
+ let safeToRemoveQuarantine = false;
101
+ try {
102
+ await link(quarantine, path);
103
+ safeToRemoveQuarantine = true;
104
+ }
105
+ catch (error) {
106
+ safeToRemoveQuarantine = ['EEXIST', 'ENOENT'].includes(errorCode(error) ?? '');
107
+ }
108
+ if (safeToRemoveQuarantine)
109
+ await unlink(quarantine).catch(() => { });
110
+ }
111
+ // Best-effort local cleanup; the server token remains authoritative and a
112
+ // missing capability merely defers to normal inactivity expiry.
113
+ }
114
+ }
115
+ //# sourceMappingURL=sessionLifecycle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessionLifecycle.js","sourceRoot":"","sources":["../../src/lib/sessionLifecycle.ts"],"names":[],"mappings":"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"}
@@ -9,6 +9,8 @@ export type HookEventName = 'PreToolUse' | 'PostToolUse' | 'SessionStart' | 'Sto
9
9
  export interface HookInput {
10
10
  session_id: string;
11
11
  transcript_path?: string;
12
+ trigger?: string;
13
+ custom_instructions?: string;
12
14
  cwd: string;
13
15
  hook_event_name: HookEventName;
14
16
  permission_mode?: string;
@@ -17,6 +19,8 @@ export interface HookInput {
17
19
  tool_input?: Record<string, unknown>;
18
20
  tool_response?: Record<string, unknown>;
19
21
  tool_use_id?: string;
22
+ /** Claude SessionEnd reason (for example clear/logout/exit). */
23
+ reason?: string;
20
24
  }
21
25
  /** PreToolUse decision shape recognised by Claude Code. */
22
26
  export type PermissionDecision = 'allow' | 'deny' | 'ask' | 'defer';
@@ -93,6 +97,8 @@ export interface PolicyReminderResponse {
93
97
  export interface InjectionsResponse {
94
98
  ok: boolean;
95
99
  reason?: 'unauthorized' | 'no_project';
100
+ /** SessionStart recovery readback for a lost /hooks/session-start response. */
101
+ lifecycleToken?: string;
96
102
  injections: Array<{
97
103
  signal: string;
98
104
  kind: 'directive' | 'nudge';
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/lib/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAmOH,MAAM,CAAC,MAAM,cAAc,GAAG,0BAA0B,CAAC"}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/lib/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAyOH,MAAM,CAAC,MAAM,cAAc,GAAG,0BAA0B,CAAC"}
@@ -20,6 +20,7 @@
20
20
  * The report is skipped silently when used_percentage is null (no live window
21
21
  * yet) or the API key / config is unavailable.
22
22
  */
23
+ import { type StatusDigest } from './lib/http.js';
23
24
  interface StatusInput {
24
25
  session_id?: string;
25
26
  cwd?: string;
@@ -37,6 +38,19 @@ interface StatusInput {
37
38
  total_cost_usd?: number | null;
38
39
  };
39
40
  }
40
- /** Build the single status line. Pure — never throws on missing fields. */
41
- declare function renderLine(input: StatusInput): string;
42
- export { renderLine };
41
+ /**
42
+ * Compact Mnemonik-state segment appended to the status line (task 2f57b87d):
43
+ * `mnk[tasks=3|ckpt=21m|scan=ok|policy=15]`. The `ckpt` token is rendered by the
44
+ * SERVER (humanDeltaShort in the developer's zone) and printed VERBATIM — the
45
+ * client does no time math. `null`/degraded (server unreachable, non-ok, or no
46
+ * attempt made) yields the known-degraded marker `mnk[?]`; the caller decides
47
+ * whether to append it.
48
+ */
49
+ declare function renderDigest(digest: StatusDigest | null): string;
50
+ /**
51
+ * Build the single status line. Pure — never throws on missing fields. When a
52
+ * `digestSegment` is supplied it is appended after the local model/ctx/cost
53
+ * segment (`… | mnk[…]`); omit it entirely on hosts/configs with no digest.
54
+ */
55
+ declare function renderLine(input: StatusInput, digestSegment?: string): string;
56
+ export { renderLine, renderDigest };
@@ -21,9 +21,10 @@
21
21
  * yet) or the API key / config is unavailable.
22
22
  */
23
23
  import { stdin, stdout, exit } from 'node:process';
24
+ import { pathToFileURL } from 'node:url';
24
25
  import { resolveConfig } from './lib/env.js';
25
26
  import { findProjectIdentity } from './lib/identity.js';
26
- import { postContextStats } from './lib/http.js';
27
+ import { postContextStats, fetchStatusDigest } from './lib/http.js';
27
28
  const FALLBACK_LINE = 'mnemonik';
28
29
  async function readStdin() {
29
30
  return new Promise((res) => {
@@ -47,8 +48,31 @@ async function readStdin() {
47
48
  setTimeout(finish, 500);
48
49
  });
49
50
  }
50
- /** Build the single status line. Pure — never throws on missing fields. */
51
- function renderLine(input) {
51
+ /**
52
+ * Compact Mnemonik-state segment appended to the status line (task 2f57b87d):
53
+ * `mnk[tasks=3|ckpt=21m|scan=ok|policy=15]`. The `ckpt` token is rendered by the
54
+ * SERVER (humanDeltaShort in the developer's zone) and printed VERBATIM — the
55
+ * client does no time math. `null`/degraded (server unreachable, non-ok, or no
56
+ * attempt made) yields the known-degraded marker `mnk[?]`; the caller decides
57
+ * whether to append it.
58
+ */
59
+ function renderDigest(digest) {
60
+ if (!digest || digest.ok !== true)
61
+ return 'mnk[?]';
62
+ const parts = [
63
+ `tasks=${typeof digest.tasks === 'number' ? digest.tasks : 0}`,
64
+ `ckpt=${digest.ckpt ?? 'none'}`,
65
+ `scan=${digest.scan ?? 'off'}`,
66
+ `policy=${typeof digest.policy === 'number' ? digest.policy : 0}`,
67
+ ];
68
+ return `mnk[${parts.join('|')}]`;
69
+ }
70
+ /**
71
+ * Build the single status line. Pure — never throws on missing fields. When a
72
+ * `digestSegment` is supplied it is appended after the local model/ctx/cost
73
+ * segment (`… | mnk[…]`); omit it entirely on hosts/configs with no digest.
74
+ */
75
+ function renderLine(input, digestSegment) {
52
76
  const model = input.model?.display_name || input.model?.id || 'Claude';
53
77
  const cw = input.context_window ?? {};
54
78
  const pct = typeof cw.used_percentage === 'number' ? Math.round(cw.used_percentage) : null;
@@ -62,7 +86,8 @@ function renderLine(input) {
62
86
  : 'ctx —';
63
87
  const cost = input.cost?.total_cost_usd;
64
88
  const costPart = typeof cost === 'number' && cost > 0 ? ` | $${cost.toFixed(2)}` : '';
65
- return `${model} | ${ctx}${costPart}`;
89
+ const digestPart = digestSegment ? ` | ${digestSegment}` : '';
90
+ return `${model} | ${ctx}${costPart}${digestPart}`;
66
91
  }
67
92
  async function main() {
68
93
  let input;
@@ -73,9 +98,26 @@ async function main() {
73
98
  stdout.write(`${FALLBACK_LINE}\n`);
74
99
  return;
75
100
  }
76
- // Print first so the status line renders immediately, regardless of the POST.
101
+ // Resolve config up front needed for both the digest GET and the context
102
+ // POST. It's a local env/file read (single-digit ms).
103
+ const config = input.cwd ? await resolveConfig(input.cwd) : null;
104
+ // Statusline digest (task 2f57b87d). Fetch BEFORE printing so it can ride the
105
+ // single first line (Claude Code renders line 1 only). Bounded + fail-open:
106
+ // on any failure we render `mnk[?]` (known-degraded) rather than nothing, and
107
+ // only when we actually attempted a fetch. Configs with no API key append no
108
+ // segment at all — identical to today's local-only line.
109
+ let digestSegment;
110
+ if (config?.apiKey && input.cwd) {
111
+ const digest = await fetchStatusDigest({
112
+ server: config.server,
113
+ apiKey: config.apiKey,
114
+ cwd: input.cwd,
115
+ sessionId: input.session_id,
116
+ });
117
+ digestSegment = renderDigest(digest);
118
+ }
77
119
  try {
78
- stdout.write(`${renderLine(input)}\n`);
120
+ stdout.write(`${renderLine(input, digestSegment)}\n`);
79
121
  }
80
122
  catch {
81
123
  stdout.write(`${FALLBACK_LINE}\n`);
@@ -87,12 +129,10 @@ async function main() {
87
129
  if (typeof cw.used_percentage !== 'number' ||
88
130
  typeof tokens !== 'number' ||
89
131
  !input.session_id ||
90
- !input.cwd) {
132
+ !input.cwd ||
133
+ !config?.apiKey) {
91
134
  return;
92
135
  }
93
- const config = await resolveConfig(input.cwd);
94
- if (!config.apiKey)
95
- return;
96
136
  await postContextStats({
97
137
  server: config.server,
98
138
  apiKey: config.apiKey,
@@ -102,17 +142,23 @@ async function main() {
102
142
  contextTokens: Math.max(0, Math.floor(tokens)),
103
143
  });
104
144
  }
105
- main()
106
- .then(() => exit(0))
107
- .catch(() => {
108
- // Absolute last resort a status line must never error out.
109
- try {
110
- stdout.write(`${FALLBACK_LINE}\n`);
111
- }
112
- catch {
113
- /* nothing left to do */
114
- }
115
- exit(0);
116
- });
117
- export { renderLine };
145
+ // Entry-point guard: only run (and exit-0) when executed as the statusline
146
+ // binary. Importing this module for renderLine/renderDigest (the test suite
147
+ // does) must never read stdin or call exit — pre-guard, the import killed the
148
+ // vitest worker via the exit(0) below.
149
+ if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
150
+ main()
151
+ .then(() => exit(0))
152
+ .catch(() => {
153
+ // Absolute last resort a status line must never error out.
154
+ try {
155
+ stdout.write(`${FALLBACK_LINE}\n`);
156
+ }
157
+ catch {
158
+ /* nothing left to do */
159
+ }
160
+ exit(0);
161
+ });
162
+ }
163
+ export { renderLine, renderDigest };
118
164
  //# sourceMappingURL=statusline.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"statusline.js","sourceRoot":"","sources":["../src/statusline.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"statusline.js","sourceRoot":"","sources":["../src/statusline.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@mnemonik/claude-code-hooks",
3
- "version": "0.9.21",
4
- "description": "Claude Code lifecycle contextual hooks for Mnemonik. PreToolUse Edit/Write/NotebookEdit/Bash gates plus SessionStart bootstrap pre-injection, Stop checkpoint gate (advisory), PreCompact context_snapshot pre-injection, SessionEnd save, and UserPromptSubmit context inject. filesToWrite delivery of skill/rules/.mnemonik.json continues to flow for ALL clients including Claude Code — this package adds host-side hook gating only. Versioned independently from the @mnemonik/server release cadence (mirrors @mnemonik/scanner).",
3
+ "version": "0.9.23",
4
+ "description": "Claude Code lifecycle contextual hooks for Mnemonik. PreToolUse Edit/Write/NotebookEdit/Bash gates plus SessionStart bootstrap warming, clean Stop, PreCompact context_snapshot creation, bounded SessionEnd cleanup, and UserPromptSubmit context injection. This hooks-only package does not install skills, rules, project identity, or MCP config. Versioned independently from the @mnemonik/server release cadence (mirrors @mnemonik/scanner).",
5
5
  "type": "module",
6
6
  "bin": {
7
7
  "mnemonik-claude-code-hooks": "dist/install.js"
@@ -14,7 +14,8 @@
14
14
  "build": "tsc",
15
15
  "typecheck": "tsc --noEmit",
16
16
  "test": "vitest run",
17
- "test:watch": "vitest"
17
+ "test:watch": "vitest",
18
+ "prepublishOnly": "npm run build"
18
19
  },
19
20
  "engines": {
20
21
  "node": ">=20"