memtrace-skills 1.1.4 → 1.1.6
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/dist/transformers/claude.d.ts +28 -8
- package/dist/transformers/claude.js +44 -12
- package/package.json +1 -1
|
@@ -20,21 +20,41 @@ export interface SettingsMutationResult {
|
|
|
20
20
|
* Never overwrites a malformed file — backs it up and returns registered=false.
|
|
21
21
|
*/
|
|
22
22
|
export declare function registerMcpInSettingsAt(settingsPath: string, memtraceBinary: string): SettingsMutationResult;
|
|
23
|
+
/**
|
|
24
|
+
* The Claude Code PreToolUse hook command.
|
|
25
|
+
*
|
|
26
|
+
* POSIX hosts POST the hook payload to the running daemon's in-process router
|
|
27
|
+
* (`POST /api/rail/hook`) with one `curl` — ~5ms of process instead of the
|
|
28
|
+
* full memtrace binary (node shim + native pair, ~59MB alive for ~0.5s) per
|
|
29
|
+
* Grep/Glob/Bash call. Fail-open is structural: no daemon (connection
|
|
30
|
+
* refused, bounded by `--connect-timeout`) or an old daemon without the
|
|
31
|
+
* endpoint (`-f` on 404) produces no output, and `|| true` exits 0 — Claude
|
|
32
|
+
* Code treats that as allow-with-no-decision. The full binary is NEVER the
|
|
33
|
+
* fallback. The agent session's `MEMTRACE_RAIL` / `MEMTRACE_RAW_SEARCH` ride
|
|
34
|
+
* along as query params, so per-session mode/escape semantics are identical
|
|
35
|
+
* to the spawn era; `MEMTRACE_RAIL_SEARCH_URL` / `MEMTRACE_UI_PORT` override
|
|
36
|
+
* the endpoint the same way they steered the binary's own daemon lookup.
|
|
37
|
+
*
|
|
38
|
+
* Windows keeps the gen-1 binary spawn: hook commands there do not run under
|
|
39
|
+
* a POSIX shell, so the env-forwarding one-liner has no portable equivalent.
|
|
40
|
+
*/
|
|
41
|
+
export declare function claudeRailHookCommand(memtraceBinary: string, platform?: NodeJS.Platform): string;
|
|
23
42
|
/**
|
|
24
43
|
* Register the Memtrace Rail PreToolUse hook in a Claude settings.json.
|
|
25
44
|
*
|
|
26
45
|
* This is what makes Rail "part of memtrace" rather than a manual install:
|
|
27
46
|
* `memtrace install` wires a PreToolUse hook that pipes every Grep/Glob/Bash
|
|
28
|
-
* attempt through
|
|
29
|
-
* (zero behavior change) —
|
|
30
|
-
*
|
|
31
|
-
* via env without
|
|
47
|
+
* attempt through the Rail router (see {@link claudeRailHookCommand} for the
|
|
48
|
+
* transport). The hook defaults to **observe** (zero behavior change) —
|
|
49
|
+
* `MEMTRACE_RAIL=nudge|rail|strict` opts into more. Mode is intentionally NOT
|
|
50
|
+
* baked into the command so the user can change it via env without
|
|
51
|
+
* re-installing.
|
|
32
52
|
*
|
|
33
|
-
* Idempotent: any prior Rail entry (identified by {@link
|
|
34
|
-
* replaced, and unrelated PreToolUse hooks are preserved. Never overwrites
|
|
35
|
-
* malformed file.
|
|
53
|
+
* Idempotent: any prior Rail entry (identified by {@link RAIL_HOOK_MARKERS})
|
|
54
|
+
* is replaced, and unrelated PreToolUse hooks are preserved. Never overwrites
|
|
55
|
+
* a malformed file.
|
|
36
56
|
*/
|
|
37
|
-
export declare function registerRailHookInSettingsAt(settingsPath: string, memtraceBinary: string): SettingsMutationResult;
|
|
57
|
+
export declare function registerRailHookInSettingsAt(settingsPath: string, memtraceBinary: string, platform?: NodeJS.Platform): SettingsMutationResult;
|
|
38
58
|
/**
|
|
39
59
|
* Remove the Memtrace Rail PreToolUse hook from a Claude settings.json.
|
|
40
60
|
* Preserves unrelated hooks; prunes empty containers. Never touches a
|
|
@@ -214,26 +214,58 @@ export function registerMcpInSettingsAt(settingsPath, memtraceBinary) {
|
|
|
214
214
|
const RAIL_HOOK_MATCHER = 'Grep|Glob|Bash';
|
|
215
215
|
/** Substring that identifies a memtrace-owned Rail hook entry (for idempotent
|
|
216
216
|
* re-register + clean removal). */
|
|
217
|
-
const
|
|
217
|
+
const RAIL_HOOK_MARKERS = [
|
|
218
|
+
// gen-1: the hook spawned the full memtrace binary per tool call.
|
|
219
|
+
'route --hook',
|
|
220
|
+
// gen-2: the hook POSTs the payload to the running daemon's in-process
|
|
221
|
+
// router (one curl, no binary spawn).
|
|
222
|
+
'/api/rail/hook',
|
|
223
|
+
];
|
|
218
224
|
const LEGACY_HOOK_SCRIPT_BASENAMES = [
|
|
219
225
|
'userprompt-claude.sh',
|
|
220
226
|
'posttool-mcp-telemetry.sh',
|
|
221
227
|
];
|
|
228
|
+
/**
|
|
229
|
+
* The Claude Code PreToolUse hook command.
|
|
230
|
+
*
|
|
231
|
+
* POSIX hosts POST the hook payload to the running daemon's in-process router
|
|
232
|
+
* (`POST /api/rail/hook`) with one `curl` — ~5ms of process instead of the
|
|
233
|
+
* full memtrace binary (node shim + native pair, ~59MB alive for ~0.5s) per
|
|
234
|
+
* Grep/Glob/Bash call. Fail-open is structural: no daemon (connection
|
|
235
|
+
* refused, bounded by `--connect-timeout`) or an old daemon without the
|
|
236
|
+
* endpoint (`-f` on 404) produces no output, and `|| true` exits 0 — Claude
|
|
237
|
+
* Code treats that as allow-with-no-decision. The full binary is NEVER the
|
|
238
|
+
* fallback. The agent session's `MEMTRACE_RAIL` / `MEMTRACE_RAW_SEARCH` ride
|
|
239
|
+
* along as query params, so per-session mode/escape semantics are identical
|
|
240
|
+
* to the spawn era; `MEMTRACE_RAIL_SEARCH_URL` / `MEMTRACE_UI_PORT` override
|
|
241
|
+
* the endpoint the same way they steered the binary's own daemon lookup.
|
|
242
|
+
*
|
|
243
|
+
* Windows keeps the gen-1 binary spawn: hook commands there do not run under
|
|
244
|
+
* a POSIX shell, so the env-forwarding one-liner has no portable equivalent.
|
|
245
|
+
*/
|
|
246
|
+
export function claudeRailHookCommand(memtraceBinary, platform = process.platform) {
|
|
247
|
+
if (platform === 'win32')
|
|
248
|
+
return `${memtraceBinary} route --hook`;
|
|
249
|
+
const endpoint = '${MEMTRACE_RAIL_SEARCH_URL:-http://127.0.0.1:${MEMTRACE_UI_PORT:-3030}}';
|
|
250
|
+
const query = 'host=claude-code&mode=${MEMTRACE_RAIL:-}&escape=${MEMTRACE_RAW_SEARCH:-}';
|
|
251
|
+
return `curl -sf --connect-timeout 0.05 --max-time 2 --data-binary @- "${endpoint}/api/rail/hook?${query}" 2>/dev/null || true`;
|
|
252
|
+
}
|
|
222
253
|
/**
|
|
223
254
|
* Register the Memtrace Rail PreToolUse hook in a Claude settings.json.
|
|
224
255
|
*
|
|
225
256
|
* This is what makes Rail "part of memtrace" rather than a manual install:
|
|
226
257
|
* `memtrace install` wires a PreToolUse hook that pipes every Grep/Glob/Bash
|
|
227
|
-
* attempt through
|
|
228
|
-
* (zero behavior change) —
|
|
229
|
-
*
|
|
230
|
-
* via env without
|
|
258
|
+
* attempt through the Rail router (see {@link claudeRailHookCommand} for the
|
|
259
|
+
* transport). The hook defaults to **observe** (zero behavior change) —
|
|
260
|
+
* `MEMTRACE_RAIL=nudge|rail|strict` opts into more. Mode is intentionally NOT
|
|
261
|
+
* baked into the command so the user can change it via env without
|
|
262
|
+
* re-installing.
|
|
231
263
|
*
|
|
232
|
-
* Idempotent: any prior Rail entry (identified by {@link
|
|
233
|
-
* replaced, and unrelated PreToolUse hooks are preserved. Never overwrites
|
|
234
|
-
* malformed file.
|
|
264
|
+
* Idempotent: any prior Rail entry (identified by {@link RAIL_HOOK_MARKERS})
|
|
265
|
+
* is replaced, and unrelated PreToolUse hooks are preserved. Never overwrites
|
|
266
|
+
* a malformed file.
|
|
235
267
|
*/
|
|
236
|
-
export function registerRailHookInSettingsAt(settingsPath, memtraceBinary) {
|
|
268
|
+
export function registerRailHookInSettingsAt(settingsPath, memtraceBinary, platform = process.platform) {
|
|
237
269
|
const { value, corrupted, backupPath } = safeReadJson(settingsPath);
|
|
238
270
|
if (corrupted) {
|
|
239
271
|
console.warn(`memtrace: ${settingsPath} is malformed; backed up to ${backupPath}. Skipped Rail hook registration.`);
|
|
@@ -252,7 +284,7 @@ export function registerRailHookInSettingsAt(settingsPath, memtraceBinary) {
|
|
|
252
284
|
hooks: [
|
|
253
285
|
{
|
|
254
286
|
type: 'command',
|
|
255
|
-
command:
|
|
287
|
+
command: claudeRailHookCommand(memtraceBinary, platform),
|
|
256
288
|
},
|
|
257
289
|
],
|
|
258
290
|
});
|
|
@@ -260,9 +292,9 @@ export function registerRailHookInSettingsAt(settingsPath, memtraceBinary) {
|
|
|
260
292
|
writeJsonAtomic(settingsPath, settings);
|
|
261
293
|
return { registered: true };
|
|
262
294
|
}
|
|
263
|
-
/** True when a PreToolUse entry is a memtrace-owned Rail hook. */
|
|
295
|
+
/** True when a PreToolUse entry is a memtrace-owned Rail hook (any generation). */
|
|
264
296
|
function isRailHookEntry(entry) {
|
|
265
|
-
return hookCommands(entry).some((command) => command.includes(
|
|
297
|
+
return hookCommands(entry).some((command) => RAIL_HOOK_MARKERS.some((marker) => command.includes(marker)));
|
|
266
298
|
}
|
|
267
299
|
function isLegacyMemtraceHookEntry(entry) {
|
|
268
300
|
return hookCommands(entry).some((command) => (LEGACY_HOOK_SCRIPT_BASENAMES.some((basename) => command.includes(basename))));
|