@codeledger/cli 0.1.1

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 (94) hide show
  1. package/LICENSE +27 -0
  2. package/dist/commands/activate.d.ts +18 -0
  3. package/dist/commands/activate.d.ts.map +1 -0
  4. package/dist/commands/activate.js +326 -0
  5. package/dist/commands/activate.js.map +1 -0
  6. package/dist/commands/bundle.d.ts +2 -0
  7. package/dist/commands/bundle.d.ts.map +1 -0
  8. package/dist/commands/bundle.js +144 -0
  9. package/dist/commands/bundle.js.map +1 -0
  10. package/dist/commands/clean.d.ts +2 -0
  11. package/dist/commands/clean.d.ts.map +1 -0
  12. package/dist/commands/clean.js +28 -0
  13. package/dist/commands/clean.js.map +1 -0
  14. package/dist/commands/compare.d.ts +2 -0
  15. package/dist/commands/compare.d.ts.map +1 -0
  16. package/dist/commands/compare.js +216 -0
  17. package/dist/commands/compare.js.map +1 -0
  18. package/dist/commands/init.d.ts +2 -0
  19. package/dist/commands/init.d.ts.map +1 -0
  20. package/dist/commands/init.js +135 -0
  21. package/dist/commands/init.js.map +1 -0
  22. package/dist/commands/run.d.ts +2 -0
  23. package/dist/commands/run.d.ts.map +1 -0
  24. package/dist/commands/run.js +57 -0
  25. package/dist/commands/run.js.map +1 -0
  26. package/dist/commands/scan.d.ts +2 -0
  27. package/dist/commands/scan.d.ts.map +1 -0
  28. package/dist/commands/scan.js +27 -0
  29. package/dist/commands/scan.js.map +1 -0
  30. package/dist/commands/session-cleanup.d.ts +11 -0
  31. package/dist/commands/session-cleanup.d.ts.map +1 -0
  32. package/dist/commands/session-cleanup.js +81 -0
  33. package/dist/commands/session-cleanup.js.map +1 -0
  34. package/dist/commands/session-init.d.ts +10 -0
  35. package/dist/commands/session-init.d.ts.map +1 -0
  36. package/dist/commands/session-init.js +46 -0
  37. package/dist/commands/session-init.js.map +1 -0
  38. package/dist/commands/session-progress.d.ts +12 -0
  39. package/dist/commands/session-progress.d.ts.map +1 -0
  40. package/dist/commands/session-progress.js +259 -0
  41. package/dist/commands/session-progress.js.map +1 -0
  42. package/dist/commands/session-summary.d.ts +14 -0
  43. package/dist/commands/session-summary.d.ts.map +1 -0
  44. package/dist/commands/session-summary.js +287 -0
  45. package/dist/commands/session-summary.js.map +1 -0
  46. package/dist/commands/sessions.d.ts +9 -0
  47. package/dist/commands/sessions.d.ts.map +1 -0
  48. package/dist/commands/sessions.js +60 -0
  49. package/dist/commands/sessions.js.map +1 -0
  50. package/dist/commands/share.d.ts +9 -0
  51. package/dist/commands/share.d.ts.map +1 -0
  52. package/dist/commands/share.js +275 -0
  53. package/dist/commands/share.js.map +1 -0
  54. package/dist/index.d.ts +3 -0
  55. package/dist/index.d.ts.map +1 -0
  56. package/dist/index.js +150 -0
  57. package/dist/index.js.map +1 -0
  58. package/dist/session-id.d.ts +22 -0
  59. package/dist/session-id.d.ts.map +1 -0
  60. package/dist/session-id.js +49 -0
  61. package/dist/session-id.js.map +1 -0
  62. package/dist/session-paths.d.ts +23 -0
  63. package/dist/session-paths.d.ts.map +1 -0
  64. package/dist/session-paths.js +44 -0
  65. package/dist/session-paths.js.map +1 -0
  66. package/dist/session-registry.d.ts +19 -0
  67. package/dist/session-registry.d.ts.map +1 -0
  68. package/dist/session-registry.js +180 -0
  69. package/dist/session-registry.js.map +1 -0
  70. package/dist/templates/claude-md.d.ts +10 -0
  71. package/dist/templates/claude-md.d.ts.map +1 -0
  72. package/dist/templates/claude-md.js +107 -0
  73. package/dist/templates/claude-md.js.map +1 -0
  74. package/dist/templates/config.d.ts +3 -0
  75. package/dist/templates/config.d.ts.map +1 -0
  76. package/dist/templates/config.js +82 -0
  77. package/dist/templates/config.js.map +1 -0
  78. package/dist/templates/harness-pack.d.ts +3 -0
  79. package/dist/templates/harness-pack.d.ts.map +1 -0
  80. package/dist/templates/harness-pack.js +26 -0
  81. package/dist/templates/harness-pack.js.map +1 -0
  82. package/dist/templates/hooks.d.ts +34 -0
  83. package/dist/templates/hooks.d.ts.map +1 -0
  84. package/dist/templates/hooks.js +149 -0
  85. package/dist/templates/hooks.js.map +1 -0
  86. package/dist/templates/scenarios.d.ts +3 -0
  87. package/dist/templates/scenarios.d.ts.map +1 -0
  88. package/dist/templates/scenarios.js +335 -0
  89. package/dist/templates/scenarios.js.map +1 -0
  90. package/dist/version.d.ts +2 -0
  91. package/dist/version.d.ts.map +1 -0
  92. package/dist/version.js +5 -0
  93. package/dist/version.js.map +1 -0
  94. package/package.json +45 -0
@@ -0,0 +1,49 @@
1
+ import { randomBytes } from 'node:crypto';
2
+ import { readFileSync, existsSync } from 'node:fs';
3
+ /**
4
+ * Generate a short, human-readable session ID.
5
+ * Format: "s-" + 6 hex characters (e.g. "s-a3f2c1").
6
+ *
7
+ * 3 random bytes = 16,777,216 possible values. Collision probability is
8
+ * negligible for typical usage (< 100 concurrent sessions), but not
9
+ * cryptographically guaranteed. For birthday-paradox safety at 1000
10
+ * concurrent sessions the collision chance is ~0.003%.
11
+ */
12
+ export function generateSessionId() {
13
+ return `s-${randomBytes(3).toString('hex')}`;
14
+ }
15
+ /**
16
+ * Resolve a session ID from multiple sources in priority order:
17
+ * 1. Explicit --session CLI flag
18
+ * 2. CODELEDGER_SESSION env var (set by SessionStart hook)
19
+ * 3. PID-tagged marker file (.codeledger/.current-session-pid-{PPID})
20
+ * 4. null (single-session fallback — today's behavior)
21
+ */
22
+ export function resolveSessionId(flags) {
23
+ // 1. Explicit flag
24
+ if (flags.session) {
25
+ return flags.session;
26
+ }
27
+ // 2. Environment variable (set by hook or user)
28
+ const envSession = process.env['CODELEDGER_SESSION'];
29
+ if (envSession) {
30
+ return envSession;
31
+ }
32
+ // 3. PID-tagged marker file
33
+ const ppid = process.ppid;
34
+ if (ppid) {
35
+ const markerPath = `.codeledger/.current-session-pid-${ppid}`;
36
+ if (existsSync(markerPath)) {
37
+ try {
38
+ const id = readFileSync(markerPath, 'utf-8').trim();
39
+ if (id)
40
+ return id;
41
+ }
42
+ catch {
43
+ // Non-fatal
44
+ }
45
+ }
46
+ }
47
+ return null;
48
+ }
49
+ //# sourceMappingURL=session-id.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-id.js","sourceRoot":"","sources":["../src/session-id.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAGnD;;;;;;;;GAQG;AACH,MAAM,UAAU,iBAAiB;IAC/B,OAAO,KAAK,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;AAC/C,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAA2B;IAC1D,mBAAmB;IACnB,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;QAClB,OAAO,KAAK,CAAC,OAAO,CAAC;IACvB,CAAC;IAED,gDAAgD;IAChD,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;IACrD,IAAI,UAAU,EAAE,CAAC;QACf,OAAO,UAAU,CAAC;IACpB,CAAC;IAED,4BAA4B;IAC5B,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAC1B,IAAI,IAAI,EAAE,CAAC;QACT,MAAM,UAAU,GAAG,oCAAoC,IAAI,EAAE,CAAC;QAC9D,IAAI,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;YAC3B,IAAI,CAAC;gBACH,MAAM,EAAE,GAAG,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;gBACpD,IAAI,EAAE;oBAAE,OAAO,EAAE,CAAC;YACpB,CAAC;YAAC,MAAM,CAAC;gBACP,YAAY;YACd,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -0,0 +1,23 @@
1
+ import type { SessionId } from '@codeledger/types';
2
+ /**
3
+ * Returns the session-specific directory, or the legacy .codeledger/ root
4
+ * when no session ID is provided.
5
+ */
6
+ export declare function sessionDir(cwd: string, sessionId: SessionId | null): string;
7
+ /** Path to the active bundle markdown for this session. */
8
+ export declare function sessionBundlePath(cwd: string, sessionId: SessionId | null): string;
9
+ /** Path to the activate ref (per-task git HEAD snapshot). */
10
+ export declare function sessionActivateRef(cwd: string, sessionId: SessionId | null): string;
11
+ /** Path to the session start ref (first activate of the session). */
12
+ export declare function sessionStartRef(cwd: string, sessionId: SessionId | null): string;
13
+ /** Path to the session progress markdown. */
14
+ export declare function sessionProgressPath(cwd: string, sessionId: SessionId | null): string;
15
+ /** Path to the hook-reminded marker. */
16
+ export declare function sessionHookRemindedPath(cwd: string, sessionId: SessionId | null): string;
17
+ /** Legacy fallback bundle path (always .codeledger/active-bundle.md). */
18
+ export declare function legacyBundlePath(cwd: string): string;
19
+ /** Sessions root directory. */
20
+ export declare function sessionsRootDir(cwd: string): string;
21
+ /** Registry file path. */
22
+ export declare function registryPath(cwd: string): string;
23
+ //# sourceMappingURL=session-paths.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-paths.d.ts","sourceRoot":"","sources":["../src/session-paths.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAEnD;;;GAGG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,GAAG,IAAI,GAAG,MAAM,CAK3E;AAED,2DAA2D;AAC3D,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,GAAG,IAAI,GAAG,MAAM,CAElF;AAED,6DAA6D;AAC7D,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,GAAG,IAAI,GAAG,MAAM,CAEnF;AAED,qEAAqE;AACrE,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,GAAG,IAAI,GAAG,MAAM,CAEhF;AAED,6CAA6C;AAC7C,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,GAAG,IAAI,GAAG,MAAM,CAEpF;AAED,wCAAwC;AACxC,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,GAAG,IAAI,GAAG,MAAM,CAExF;AAED,yEAAyE;AACzE,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEpD;AAED,+BAA+B;AAC/B,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEnD;AAED,0BAA0B;AAC1B,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEhD"}
@@ -0,0 +1,44 @@
1
+ import { join } from 'node:path';
2
+ /**
3
+ * Returns the session-specific directory, or the legacy .codeledger/ root
4
+ * when no session ID is provided.
5
+ */
6
+ export function sessionDir(cwd, sessionId) {
7
+ if (sessionId) {
8
+ return join(cwd, '.codeledger', 'sessions', sessionId);
9
+ }
10
+ return join(cwd, '.codeledger');
11
+ }
12
+ /** Path to the active bundle markdown for this session. */
13
+ export function sessionBundlePath(cwd, sessionId) {
14
+ return join(sessionDir(cwd, sessionId), 'active-bundle.md');
15
+ }
16
+ /** Path to the activate ref (per-task git HEAD snapshot). */
17
+ export function sessionActivateRef(cwd, sessionId) {
18
+ return join(sessionDir(cwd, sessionId), '.activate-ref');
19
+ }
20
+ /** Path to the session start ref (first activate of the session). */
21
+ export function sessionStartRef(cwd, sessionId) {
22
+ return join(sessionDir(cwd, sessionId), '.session-start-ref');
23
+ }
24
+ /** Path to the session progress markdown. */
25
+ export function sessionProgressPath(cwd, sessionId) {
26
+ return join(sessionDir(cwd, sessionId), 'session-progress.md');
27
+ }
28
+ /** Path to the hook-reminded marker. */
29
+ export function sessionHookRemindedPath(cwd, sessionId) {
30
+ return join(sessionDir(cwd, sessionId), '.hook-reminded');
31
+ }
32
+ /** Legacy fallback bundle path (always .codeledger/active-bundle.md). */
33
+ export function legacyBundlePath(cwd) {
34
+ return join(cwd, '.codeledger', 'active-bundle.md');
35
+ }
36
+ /** Sessions root directory. */
37
+ export function sessionsRootDir(cwd) {
38
+ return join(cwd, '.codeledger', 'sessions');
39
+ }
40
+ /** Registry file path. */
41
+ export function registryPath(cwd) {
42
+ return join(cwd, '.codeledger', 'sessions', 'registry.json');
43
+ }
44
+ //# sourceMappingURL=session-paths.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-paths.js","sourceRoot":"","sources":["../src/session-paths.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAGjC;;;GAGG;AACH,MAAM,UAAU,UAAU,CAAC,GAAW,EAAE,SAA2B;IACjE,IAAI,SAAS,EAAE,CAAC;QACd,OAAO,IAAI,CAAC,GAAG,EAAE,aAAa,EAAE,UAAU,EAAE,SAAS,CAAC,CAAC;IACzD,CAAC;IACD,OAAO,IAAI,CAAC,GAAG,EAAE,aAAa,CAAC,CAAC;AAClC,CAAC;AAED,2DAA2D;AAC3D,MAAM,UAAU,iBAAiB,CAAC,GAAW,EAAE,SAA2B;IACxE,OAAO,IAAI,CAAC,UAAU,CAAC,GAAG,EAAE,SAAS,CAAC,EAAE,kBAAkB,CAAC,CAAC;AAC9D,CAAC;AAED,6DAA6D;AAC7D,MAAM,UAAU,kBAAkB,CAAC,GAAW,EAAE,SAA2B;IACzE,OAAO,IAAI,CAAC,UAAU,CAAC,GAAG,EAAE,SAAS,CAAC,EAAE,eAAe,CAAC,CAAC;AAC3D,CAAC;AAED,qEAAqE;AACrE,MAAM,UAAU,eAAe,CAAC,GAAW,EAAE,SAA2B;IACtE,OAAO,IAAI,CAAC,UAAU,CAAC,GAAG,EAAE,SAAS,CAAC,EAAE,oBAAoB,CAAC,CAAC;AAChE,CAAC;AAED,6CAA6C;AAC7C,MAAM,UAAU,mBAAmB,CAAC,GAAW,EAAE,SAA2B;IAC1E,OAAO,IAAI,CAAC,UAAU,CAAC,GAAG,EAAE,SAAS,CAAC,EAAE,qBAAqB,CAAC,CAAC;AACjE,CAAC;AAED,wCAAwC;AACxC,MAAM,UAAU,uBAAuB,CAAC,GAAW,EAAE,SAA2B;IAC9E,OAAO,IAAI,CAAC,UAAU,CAAC,GAAG,EAAE,SAAS,CAAC,EAAE,gBAAgB,CAAC,CAAC;AAC5D,CAAC;AAED,yEAAyE;AACzE,MAAM,UAAU,gBAAgB,CAAC,GAAW;IAC1C,OAAO,IAAI,CAAC,GAAG,EAAE,aAAa,EAAE,kBAAkB,CAAC,CAAC;AACtD,CAAC;AAED,+BAA+B;AAC/B,MAAM,UAAU,eAAe,CAAC,GAAW;IACzC,OAAO,IAAI,CAAC,GAAG,EAAE,aAAa,EAAE,UAAU,CAAC,CAAC;AAC9C,CAAC;AAED,0BAA0B;AAC1B,MAAM,UAAU,YAAY,CAAC,GAAW;IACtC,OAAO,IAAI,CAAC,GAAG,EAAE,aAAa,EAAE,UAAU,EAAE,eAAe,CAAC,CAAC;AAC/D,CAAC"}
@@ -0,0 +1,19 @@
1
+ import type { SessionId, SessionRecord } from '@codeledger/types';
2
+ /** Register a new session, pruning stale ones in the process. */
3
+ export declare function registerSession(cwd: string, record: SessionRecord): void;
4
+ /** Update an existing session's fields. */
5
+ export declare function updateSession(cwd: string, sessionId: SessionId, updates: Partial<Pick<SessionRecord, 'task' | 'last_active_at' | 'bundle_files' | 'status'>>): void;
6
+ /** Deregister a session (mark stopped and remove from registry). */
7
+ export declare function deregisterSession(cwd: string, sessionId: SessionId): void;
8
+ /** Get all sessions with 'active' status. */
9
+ export declare function getActiveSessions(cwd: string): SessionRecord[];
10
+ /** Get all sessions (including stopped). */
11
+ export declare function getAllSessions(cwd: string): SessionRecord[];
12
+ /**
13
+ * Find files that overlap between a candidate bundle and other active sessions.
14
+ * Returns a map of session_id -> overlapping file paths.
15
+ *
16
+ * This is a read-only operation — does not prune the registry.
17
+ */
18
+ export declare function findOverlappingFiles(cwd: string, excludeSessionId: SessionId, candidateFiles: string[]): Map<SessionId, string[]>;
19
+ //# sourceMappingURL=session-registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-registry.d.ts","sourceRoot":"","sources":["../src/session-registry.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAkElE,iEAAiE;AACjE,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,GAAG,IAAI,CAaxE;AAED,2CAA2C;AAC3C,wBAAgB,aAAa,CAC3B,GAAG,EAAE,MAAM,EACX,SAAS,EAAE,SAAS,EACpB,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,aAAa,EAAE,MAAM,GAAG,gBAAgB,GAAG,cAAc,GAAG,QAAQ,CAAC,CAAC,GAC3F,IAAI,CAgBN;AAED,oEAAoE;AACpE,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,GAAG,IAAI,CASzE;AAED,6CAA6C;AAC7C,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,aAAa,EAAE,CAU9D;AAED,4CAA4C;AAC5C,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,aAAa,EAAE,CAE3D;AAyBD;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAClC,GAAG,EAAE,MAAM,EACX,gBAAgB,EAAE,SAAS,EAC3B,cAAc,EAAE,MAAM,EAAE,GACvB,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,CAAC,CAgB1B"}
@@ -0,0 +1,180 @@
1
+ import { readFileSync, writeFileSync, existsSync, mkdirSync, renameSync, openSync, closeSync, unlinkSync } from 'node:fs';
2
+ import { dirname } from 'node:path';
3
+ import { registryPath } from './session-paths.js';
4
+ const STALE_AGE_MS = 24 * 60 * 60 * 1000; // 24 hours
5
+ const LOCK_TIMEOUT_MS = 5000;
6
+ const LOCK_RETRY_MS = 50;
7
+ /** Acquire a simple file-based lock. Returns unlock function. */
8
+ function acquireLock(cwd) {
9
+ const lockPath = registryPath(cwd) + '.lock';
10
+ const dir = dirname(lockPath);
11
+ if (!existsSync(dir))
12
+ mkdirSync(dir, { recursive: true });
13
+ const deadline = Date.now() + LOCK_TIMEOUT_MS;
14
+ while (Date.now() < deadline) {
15
+ try {
16
+ // O_CREAT | O_EXCL: fails if file already exists (atomic)
17
+ const fd = openSync(lockPath, 'wx');
18
+ closeSync(fd);
19
+ return () => {
20
+ try {
21
+ unlinkSync(lockPath);
22
+ }
23
+ catch { /* best effort */ }
24
+ };
25
+ }
26
+ catch {
27
+ // Lock held by another process — spin-wait
28
+ const waitMs = Math.min(LOCK_RETRY_MS, deadline - Date.now());
29
+ if (waitMs <= 0)
30
+ break;
31
+ // Synchronous sleep to avoid making all callers async
32
+ Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, waitMs);
33
+ }
34
+ }
35
+ // Timeout: steal the stale lock (the holder likely crashed)
36
+ try {
37
+ unlinkSync(lockPath);
38
+ }
39
+ catch { /* ignore */ }
40
+ const fd = openSync(lockPath, 'wx');
41
+ closeSync(fd);
42
+ return () => {
43
+ try {
44
+ unlinkSync(lockPath);
45
+ }
46
+ catch { /* best effort */ }
47
+ };
48
+ }
49
+ /** Read the registry file, returning an empty registry if missing or corrupt. */
50
+ function readRegistry(cwd) {
51
+ const path = registryPath(cwd);
52
+ if (!existsSync(path))
53
+ return { sessions: [] };
54
+ try {
55
+ return JSON.parse(readFileSync(path, 'utf-8'));
56
+ }
57
+ catch {
58
+ return { sessions: [] };
59
+ }
60
+ }
61
+ /** Write registry atomically (write to .tmp then rename). */
62
+ function writeRegistry(cwd, data) {
63
+ const path = registryPath(cwd);
64
+ const dir = dirname(path);
65
+ if (!existsSync(dir))
66
+ mkdirSync(dir, { recursive: true });
67
+ const tmpPath = path + '.tmp';
68
+ writeFileSync(tmpPath, JSON.stringify(data, null, 2) + '\n');
69
+ renameSync(tmpPath, path);
70
+ }
71
+ /** Register a new session, pruning stale ones in the process. */
72
+ export function registerSession(cwd, record) {
73
+ const unlock = acquireLock(cwd);
74
+ try {
75
+ const data = readRegistry(cwd);
76
+ pruneStaleEntries(data);
77
+ // Remove any existing entry for this session ID (re-registration)
78
+ data.sessions = data.sessions.filter((s) => s.session_id !== record.session_id);
79
+ data.sessions.push(record);
80
+ writeRegistry(cwd, data);
81
+ }
82
+ finally {
83
+ unlock();
84
+ }
85
+ }
86
+ /** Update an existing session's fields. */
87
+ export function updateSession(cwd, sessionId, updates) {
88
+ const unlock = acquireLock(cwd);
89
+ try {
90
+ const data = readRegistry(cwd);
91
+ const session = data.sessions.find((s) => s.session_id === sessionId);
92
+ if (!session)
93
+ return;
94
+ if (updates.task !== undefined)
95
+ session.task = updates.task;
96
+ if (updates.last_active_at !== undefined)
97
+ session.last_active_at = updates.last_active_at;
98
+ if (updates.bundle_files !== undefined)
99
+ session.bundle_files = updates.bundle_files;
100
+ if (updates.status !== undefined)
101
+ session.status = updates.status;
102
+ writeRegistry(cwd, data);
103
+ }
104
+ finally {
105
+ unlock();
106
+ }
107
+ }
108
+ /** Deregister a session (mark stopped and remove from registry). */
109
+ export function deregisterSession(cwd, sessionId) {
110
+ const unlock = acquireLock(cwd);
111
+ try {
112
+ const data = readRegistry(cwd);
113
+ data.sessions = data.sessions.filter((s) => s.session_id !== sessionId);
114
+ writeRegistry(cwd, data);
115
+ }
116
+ finally {
117
+ unlock();
118
+ }
119
+ }
120
+ /** Get all sessions with 'active' status. */
121
+ export function getActiveSessions(cwd) {
122
+ const unlock = acquireLock(cwd);
123
+ try {
124
+ const data = readRegistry(cwd);
125
+ pruneStaleEntries(data);
126
+ writeRegistry(cwd, data);
127
+ return data.sessions.filter((s) => s.status === 'active');
128
+ }
129
+ finally {
130
+ unlock();
131
+ }
132
+ }
133
+ /** Get all sessions (including stopped). */
134
+ export function getAllSessions(cwd) {
135
+ return readRegistry(cwd).sessions;
136
+ }
137
+ /**
138
+ * Prune sessions that are stale:
139
+ * - status is 'stopped'
140
+ * - last_active_at is older than 24 hours
141
+ *
142
+ * Note: PID-based liveness is not used for automatic pruning because CLI
143
+ * commands run as short-lived subprocesses — the PID stored at session-init
144
+ * time will always be dead by the time another command reads the registry.
145
+ * PID liveness is only checked in the explicit `pruneByPid` path.
146
+ */
147
+ function pruneStaleEntries(data) {
148
+ const now = Date.now();
149
+ data.sessions = data.sessions.filter((s) => {
150
+ if (s.status === 'stopped')
151
+ return false;
152
+ // Age-based staleness
153
+ const lastActive = new Date(s.last_active_at).getTime();
154
+ if (now - lastActive > STALE_AGE_MS)
155
+ return false;
156
+ return true;
157
+ });
158
+ }
159
+ /**
160
+ * Find files that overlap between a candidate bundle and other active sessions.
161
+ * Returns a map of session_id -> overlapping file paths.
162
+ *
163
+ * This is a read-only operation — does not prune the registry.
164
+ */
165
+ export function findOverlappingFiles(cwd, excludeSessionId, candidateFiles) {
166
+ const data = readRegistry(cwd);
167
+ const active = data.sessions.filter((s) => s.status === 'active');
168
+ const candidateSet = new Set(candidateFiles);
169
+ const overlaps = new Map();
170
+ for (const session of active) {
171
+ if (session.session_id === excludeSessionId)
172
+ continue;
173
+ const overlap = session.bundle_files.filter((f) => candidateSet.has(f));
174
+ if (overlap.length > 0) {
175
+ overlaps.set(session.session_id, overlap);
176
+ }
177
+ }
178
+ return overlaps;
179
+ }
180
+ //# sourceMappingURL=session-registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-registry.js","sourceRoot":"","sources":["../src/session-registry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * CLAUDE.md section template generated by `codeledger init`.
3
+ *
4
+ * This section instructs AI coding agents (Claude Code, Cursor, Codex, etc.)
5
+ * to execute CodeLedger CLI commands via their shell/terminal tool instead of
6
+ * simulating or fabricating output. Without this, agents tend to "fake" the
7
+ * output by manually reading files and constructing their own summaries.
8
+ */
9
+ export declare function claudeMdSection(): string;
10
+ //# sourceMappingURL=claude-md.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude-md.d.ts","sourceRoot":"","sources":["../../src/templates/claude-md.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,wBAAgB,eAAe,IAAI,MAAM,CAiGxC"}
@@ -0,0 +1,107 @@
1
+ /**
2
+ * CLAUDE.md section template generated by `codeledger init`.
3
+ *
4
+ * This section instructs AI coding agents (Claude Code, Cursor, Codex, etc.)
5
+ * to execute CodeLedger CLI commands via their shell/terminal tool instead of
6
+ * simulating or fabricating output. Without this, agents tend to "fake" the
7
+ * output by manually reading files and constructing their own summaries.
8
+ */
9
+ export function claudeMdSection() {
10
+ return [
11
+ '## CodeLedger Integration',
12
+ '',
13
+ 'This repo uses [CodeLedger](https://github.com/codeledgerECF/codeledger-blackbox) for deterministic context selection.',
14
+ 'CodeLedger is a **real CLI tool** installed in this repo — not a prompt technique or convention.',
15
+ '',
16
+ '### Rule 1: ALWAYS Execute via Shell',
17
+ '',
18
+ 'Every `codeledger` command **must** be executed in a real shell (Bash tool, terminal, subprocess).',
19
+ '**NEVER** do any of the following:',
20
+ '',
21
+ '- Simulate or approximate CodeLedger output',
22
+ '- Manually construct bundle recall/precision/token numbers',
23
+ '- Write to any file under `.codeledger/` directly',
24
+ '- Claim CodeLedger "ran" without actually executing the command',
25
+ '- Fabricate a session summary, session progress, or bundle',
26
+ '- Paraphrase or reformat CodeLedger output as if you ran it',
27
+ '',
28
+ 'If a command fails or is unavailable, **say so** — do not invent output.',
29
+ '',
30
+ '### Rule 2: Verify Before Claiming Success',
31
+ '',
32
+ 'After running any `codeledger` command, check the exit code and output.',
33
+ 'If the command prints an error or returns a non-zero exit code:',
34
+ '',
35
+ '1. Show the user the actual error message',
36
+ '2. Do NOT proceed as if the command succeeded',
37
+ '3. Suggest `npx codeledger init` if the error mentions missing config',
38
+ '',
39
+ '### Available Commands',
40
+ '',
41
+ '| Command | What It Does |',
42
+ '|---------|-------------|',
43
+ '| `npx codeledger activate --task "..."` | Scan repo (if stale), generate context bundle, write `.codeledger/active-bundle.md` |',
44
+ '| `npx codeledger scan` | Rebuild the repo index (dependency graph, churn, test map) |',
45
+ '| `npx codeledger bundle --task "..."` | Generate a context bundle (JSON only, no active-bundle write) |',
46
+ '| `npx codeledger session-progress` | Write a ground-truth session progress snapshot |',
47
+ '| `npx codeledger session-summary` | Show session-end value recap (recall, precision, token savings) |',
48
+ '| `npx codeledger init` | Initialize CodeLedger in a repo (creates `.codeledger/`, config, hooks) |',
49
+ '',
50
+ '**Trigger phrases:** If the user asks for a "session summary", "session recap", "codeledger summary", "how did the bundle do", or anything similar — run `npx codeledger session-summary` in your shell. Do not construct the output yourself.',
51
+ '',
52
+ '### Rule 3: .codeledger/ Is Read-Only to Agents',
53
+ '',
54
+ 'All files under `.codeledger/` are managed exclusively by the CLI.',
55
+ '**Never create, edit, or overwrite** any file in `.codeledger/` — not even to "help" or "fix" something.',
56
+ '',
57
+ '| Instead of writing to... | Run this command |',
58
+ '|--------------------------|-----------------|',
59
+ '| `.codeledger/active-bundle.md` | `npx codeledger activate --task "..."` |',
60
+ '| `.codeledger/session-progress.md` | `npx codeledger session-progress` |',
61
+ '| `.codeledger/config.json` | `npx codeledger init --force` (or user edits manually) |',
62
+ '| Session summary output | `npx codeledger session-summary` |',
63
+ '',
64
+ '### Hooks (Automatic)',
65
+ '',
66
+ 'CodeLedger hooks (`.claude/hooks.json`) run automatically:',
67
+ '',
68
+ '- **On session start:** warms the repo index and generates an initial bundle',
69
+ '- **On git commit:** shows bundle recall/precision for the current task',
70
+ '- **Before compaction:** saves a progress snapshot you can read after compaction',
71
+ '- **On session end:** shows a final session recap',
72
+ '',
73
+ 'You do not need to run `codeledger session-summary` manually after commits — the hook does it. But you can run it if the user explicitly asks.',
74
+ '',
75
+ '### Using the Context Bundle',
76
+ '',
77
+ 'If `.codeledger/active-bundle.md` exists and is not empty, it lists the most relevant files ranked by score with reasons and code excerpts.',
78
+ '**Prioritize reading and working within the files listed in that bundle** — they were selected deterministically based on the task description.',
79
+ '',
80
+ 'To refresh the bundle for a new task:',
81
+ '',
82
+ '```bash',
83
+ 'npx codeledger activate --task "describe the task here"',
84
+ '```',
85
+ '',
86
+ '### Multi-Session Awareness',
87
+ '',
88
+ 'If you see a session ID in your environment (`CODELEDGER_SESSION`) or in a PID marker file,',
89
+ 'always pass `--session $CODELEDGER_SESSION` when running codeledger commands.',
90
+ 'Your session-specific bundle is at `.codeledger/sessions/{session-id}/active-bundle.md`.',
91
+ 'If no session ID is set, use the default: `.codeledger/active-bundle.md`.',
92
+ '',
93
+ 'To see all active sessions: `npx codeledger sessions`',
94
+ '',
95
+ '### Quick Verification',
96
+ '',
97
+ 'To verify CodeLedger is installed and working:',
98
+ '',
99
+ '```bash',
100
+ 'npx codeledger --version',
101
+ '```',
102
+ '',
103
+ 'If this fails, CodeLedger may not be installed. Run `npm install` or see the project README.',
104
+ '',
105
+ ].join('\n');
106
+ }
107
+ //# sourceMappingURL=claude-md.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude-md.js","sourceRoot":"","sources":["../../src/templates/claude-md.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,MAAM,UAAU,eAAe;IAC7B,OAAO;QACL,2BAA2B;QAC3B,EAAE;QACF,wHAAwH;QACxH,kGAAkG;QAClG,EAAE;QACF,sCAAsC;QACtC,EAAE;QACF,oGAAoG;QACpG,oCAAoC;QACpC,EAAE;QACF,6CAA6C;QAC7C,4DAA4D;QAC5D,mDAAmD;QACnD,iEAAiE;QACjE,4DAA4D;QAC5D,6DAA6D;QAC7D,EAAE;QACF,0EAA0E;QAC1E,EAAE;QACF,4CAA4C;QAC5C,EAAE;QACF,yEAAyE;QACzE,iEAAiE;QACjE,EAAE;QACF,2CAA2C;QAC3C,+CAA+C;QAC/C,uEAAuE;QACvE,EAAE;QACF,wBAAwB;QACxB,EAAE;QACF,4BAA4B;QAC5B,2BAA2B;QAC3B,kIAAkI;QAClI,wFAAwF;QACxF,0GAA0G;QAC1G,wFAAwF;QACxF,wGAAwG;QACxG,qGAAqG;QACrG,EAAE;QACF,gPAAgP;QAChP,EAAE;QACF,iDAAiD;QACjD,EAAE;QACF,oEAAoE;QACpE,0GAA0G;QAC1G,EAAE;QACF,iDAAiD;QACjD,gDAAgD;QAChD,6EAA6E;QAC7E,2EAA2E;QAC3E,wFAAwF;QACxF,+DAA+D;QAC/D,EAAE;QACF,uBAAuB;QACvB,EAAE;QACF,4DAA4D;QAC5D,EAAE;QACF,8EAA8E;QAC9E,yEAAyE;QACzE,kFAAkF;QAClF,mDAAmD;QACnD,EAAE;QACF,gJAAgJ;QAChJ,EAAE;QACF,8BAA8B;QAC9B,EAAE;QACF,6IAA6I;QAC7I,iJAAiJ;QACjJ,EAAE;QACF,uCAAuC;QACvC,EAAE;QACF,SAAS;QACT,yDAAyD;QACzD,KAAK;QACL,EAAE;QACF,6BAA6B;QAC7B,EAAE;QACF,6FAA6F;QAC7F,+EAA+E;QAC/E,0FAA0F;QAC1F,2EAA2E;QAC3E,EAAE;QACF,uDAAuD;QACvD,EAAE;QACF,wBAAwB;QACxB,EAAE;QACF,gDAAgD;QAChD,EAAE;QACF,SAAS;QACT,0BAA0B;QAC1B,KAAK;QACL,EAAE;QACF,8FAA8F;QAC9F,EAAE;KACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { CodeLedgerConfig } from '@codeledger/types';
2
+ export declare function defaultConfig(): CodeLedgerConfig;
3
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/templates/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAG1D,wBAAgB,aAAa,IAAI,gBAAgB,CA+EhD"}
@@ -0,0 +1,82 @@
1
+ import { CLI_VERSION } from '../version.js';
2
+ export function defaultConfig() {
3
+ return {
4
+ version: CLI_VERSION,
5
+ workspace: {
6
+ db_path: '.codeledger/ledger.db',
7
+ cache_dir: '.codeledger/cache',
8
+ artifacts_dir: '.codeledger/artifacts',
9
+ reports_dir: '.codeledger/reports',
10
+ worktree_root: '.codeledger/worktrees',
11
+ },
12
+ repo: {
13
+ include: ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx', '**/*.mjs', '**/*.cjs'],
14
+ exclude: [
15
+ 'node_modules/**',
16
+ 'dist/**',
17
+ 'build/**',
18
+ '.git/**',
19
+ '.codeledger/**',
20
+ 'coverage/**',
21
+ '*.min.js',
22
+ '*.bundle.js',
23
+ ],
24
+ test_patterns: [
25
+ '**/*.test.*',
26
+ '**/*.spec.*',
27
+ '**/__tests__/**',
28
+ '**/test/**',
29
+ ],
30
+ language_extensions: {
31
+ '.ts': 'typescript',
32
+ '.tsx': 'typescript-react',
33
+ '.js': 'javascript',
34
+ '.jsx': 'javascript-react',
35
+ '.mjs': 'javascript',
36
+ '.cjs': 'javascript',
37
+ },
38
+ },
39
+ selector: {
40
+ weights: {
41
+ keyword: 0.30,
42
+ centrality: 0.15,
43
+ churn: 0.15,
44
+ recent_touch: 0.10,
45
+ test_relevance: 0.10,
46
+ size_penalty: 0.10,
47
+ success_prior: 0.05,
48
+ fail_prior: 0.05,
49
+ error_infrastructure: 0.08,
50
+ },
51
+ default_budget: {
52
+ tokens: 8000,
53
+ max_files: 25,
54
+ },
55
+ sufficiency_threshold: 0.85,
56
+ hot_zone_count: 15,
57
+ dependency_depth: 2,
58
+ dependency_cap_per_seed: 10,
59
+ excerpt_full_file_max_lines: 250,
60
+ excerpt_window_lines: 40,
61
+ },
62
+ injection: {
63
+ default_mode: 'prompt_prepend',
64
+ file_drop_path: '.codeledger/active-bundle.md',
65
+ },
66
+ harness: {
67
+ default_repeats: 3,
68
+ default_timeout_sec: 1800,
69
+ guided_timeout_sec: 600,
70
+ worktree_dependency_mode: 'symlink',
71
+ },
72
+ preflight: {
73
+ allow_dirty_repo: false,
74
+ },
75
+ reporting: {
76
+ markdown: true,
77
+ badge: true,
78
+ share_pack: false,
79
+ },
80
+ };
81
+ }
82
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/templates/config.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C,MAAM,UAAU,aAAa;IAC3B,OAAO;QACL,OAAO,EAAE,WAAW;QACpB,SAAS,EAAE;YACT,OAAO,EAAE,uBAAuB;YAChC,SAAS,EAAE,mBAAmB;YAC9B,aAAa,EAAE,uBAAuB;YACtC,WAAW,EAAE,qBAAqB;YAClC,aAAa,EAAE,uBAAuB;SACvC;QACD,IAAI,EAAE;YACJ,OAAO,EAAE,CAAC,SAAS,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,CAAC;YAC/E,OAAO,EAAE;gBACP,iBAAiB;gBACjB,SAAS;gBACT,UAAU;gBACV,SAAS;gBACT,gBAAgB;gBAChB,aAAa;gBACb,UAAU;gBACV,aAAa;aACd;YACD,aAAa,EAAE;gBACb,aAAa;gBACb,aAAa;gBACb,iBAAiB;gBACjB,YAAY;aACb;YACD,mBAAmB,EAAE;gBACnB,KAAK,EAAE,YAAY;gBACnB,MAAM,EAAE,kBAAkB;gBAC1B,KAAK,EAAE,YAAY;gBACnB,MAAM,EAAE,kBAAkB;gBAC1B,MAAM,EAAE,YAAY;gBACpB,MAAM,EAAE,YAAY;aACrB;SACF;QACD,QAAQ,EAAE;YACR,OAAO,EAAE;gBACP,OAAO,EAAE,IAAI;gBACb,UAAU,EAAE,IAAI;gBAChB,KAAK,EAAE,IAAI;gBACX,YAAY,EAAE,IAAI;gBAClB,cAAc,EAAE,IAAI;gBACpB,YAAY,EAAE,IAAI;gBAClB,aAAa,EAAE,IAAI;gBACnB,UAAU,EAAE,IAAI;gBAChB,oBAAoB,EAAE,IAAI;aAC3B;YACD,cAAc,EAAE;gBACd,MAAM,EAAE,IAAI;gBACZ,SAAS,EAAE,EAAE;aACd;YACD,qBAAqB,EAAE,IAAI;YAC3B,cAAc,EAAE,EAAE;YAClB,gBAAgB,EAAE,CAAC;YACnB,uBAAuB,EAAE,EAAE;YAC3B,2BAA2B,EAAE,GAAG;YAChC,oBAAoB,EAAE,EAAE;SACzB;QACD,SAAS,EAAE;YACT,YAAY,EAAE,gBAAgB;YAC9B,cAAc,EAAE,8BAA8B;SAC/C;QACD,OAAO,EAAE;YACP,eAAe,EAAE,CAAC;YAClB,mBAAmB,EAAE,IAAI;YACzB,kBAAkB,EAAE,GAAG;YACvB,wBAAwB,EAAE,SAAS;SACpC;QACD,SAAS,EAAE;YACT,gBAAgB,EAAE,KAAK;SACxB;QACD,SAAS,EAAE;YACT,QAAQ,EAAE,IAAI;YACd,KAAK,EAAE,IAAI;YACX,UAAU,EAAE,KAAK;SAClB;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { HarnessPack } from '@codeledger/types';
2
+ export declare function defaultHarnessPack(): HarnessPack;
3
+ //# sourceMappingURL=harness-pack.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"harness-pack.d.ts","sourceRoot":"","sources":["../../src/templates/harness-pack.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGrD,wBAAgB,kBAAkB,IAAI,WAAW,CAuBhD"}
@@ -0,0 +1,26 @@
1
+ import { CLI_VERSION } from '../version.js';
2
+ export function defaultHarnessPack() {
3
+ return {
4
+ name: 'codeledger-starter-pack',
5
+ version: CLI_VERSION,
6
+ description: 'Default benchmark scenarios for CodeLedger Blackbox',
7
+ scenarios: [
8
+ '01-auth-middleware-refactor.json',
9
+ '02-bugfix-null-handling.json',
10
+ '03-add-feature-flag.json',
11
+ '04-perf-hot-path.json',
12
+ '05-test-fix-flaky.json',
13
+ '06-api-contract-update.json',
14
+ '07-rename-module-safely.json',
15
+ '08-security-input-validation.json',
16
+ '09-cli-arg-parsing.json',
17
+ '10-observability-logging.json',
18
+ '11-db-migration-safety.json',
19
+ '12-cache-invalidation-bugfix.json',
20
+ '13-background-job-retry-policy.json',
21
+ '14-access-control-hardening.json',
22
+ '15-monorepo-build-optimization.json',
23
+ ],
24
+ };
25
+ }
26
+ //# sourceMappingURL=harness-pack.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"harness-pack.js","sourceRoot":"","sources":["../../src/templates/harness-pack.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C,MAAM,UAAU,kBAAkB;IAChC,OAAO;QACL,IAAI,EAAE,yBAAyB;QAC/B,OAAO,EAAE,WAAW;QACpB,WAAW,EAAE,qDAAqD;QAClE,SAAS,EAAE;YACT,kCAAkC;YAClC,8BAA8B;YAC9B,0BAA0B;YAC1B,uBAAuB;YACvB,wBAAwB;YACxB,6BAA6B;YAC7B,8BAA8B;YAC9B,mCAAmC;YACnC,yBAAyB;YACzB,+BAA+B;YAC/B,6BAA6B;YAC7B,mCAAmC;YACnC,qCAAqC;YACrC,kCAAkC;YAClC,qCAAqC;SACtC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Claude Code hooks template generated by `codeledger init`.
3
+ *
4
+ * These hooks integrate CodeLedger into the Claude Code lifecycle:
5
+ * - SessionStart: initialize session ID, scan repo, warm index
6
+ * - PreToolUse: remind agent to check active bundle on edits
7
+ * - PostToolUse: auto-run session-summary after git commits
8
+ * - PreCompact: write session progress snapshot before compaction
9
+ * - Stop: final session recap, session cleanup
10
+ *
11
+ * Multi-session support: SessionStart generates a session ID and writes
12
+ * a PID-tagged marker file. Downstream hooks discover the session ID
13
+ * via the CODELEDGER_SESSION env var or PID marker, ensuring each
14
+ * Claude Code tab gets its own isolated bundle and state files.
15
+ *
16
+ * All hooks gracefully degrade: if the CLI is missing or a command fails,
17
+ * the hook prints a diagnostic message instead of silently breaking.
18
+ */
19
+ export interface HookEntry {
20
+ type: 'command';
21
+ command: string;
22
+ timeout: number;
23
+ }
24
+ export interface HooksConfig {
25
+ hooks: {
26
+ SessionStart?: HookEntry[];
27
+ PreToolUse?: HookEntry[];
28
+ PostToolUse?: HookEntry[];
29
+ PreCompact?: HookEntry[];
30
+ Stop?: HookEntry[];
31
+ };
32
+ }
33
+ export declare function defaultHooks(): HooksConfig;
34
+ //# sourceMappingURL=hooks.d.ts.map