prtape-cli 0.0.0-stage → 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 (75) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +140 -2
  3. package/dist/adapters/claude.d.ts +2 -0
  4. package/dist/adapters/claude.js +309 -0
  5. package/dist/adapters/claude.js.map +1 -0
  6. package/dist/bash-edits.d.ts +41 -0
  7. package/dist/bash-edits.js +440 -0
  8. package/dist/bash-edits.js.map +1 -0
  9. package/dist/cli.d.ts +2 -0
  10. package/dist/cli.js +216 -0
  11. package/dist/cli.js.map +1 -0
  12. package/dist/decision.d.ts +7 -0
  13. package/dist/decision.js +224 -0
  14. package/dist/decision.js.map +1 -0
  15. package/dist/discover.d.ts +32 -0
  16. package/dist/discover.js +179 -0
  17. package/dist/discover.js.map +1 -0
  18. package/dist/display.d.ts +28 -0
  19. package/dist/display.js +311 -0
  20. package/dist/display.js.map +1 -0
  21. package/dist/env.d.ts +5 -0
  22. package/dist/env.js +11 -0
  23. package/dist/env.js.map +1 -0
  24. package/dist/gh.d.ts +46 -0
  25. package/dist/gh.js +190 -0
  26. package/dist/gh.js.map +1 -0
  27. package/dist/glance.d.ts +15 -0
  28. package/dist/glance.js +75 -0
  29. package/dist/glance.js.map +1 -0
  30. package/dist/index.d.ts +12 -0
  31. package/dist/index.js +12 -0
  32. package/dist/index.js.map +1 -0
  33. package/dist/orphan.d.ts +44 -0
  34. package/dist/orphan.js +152 -0
  35. package/dist/orphan.js.map +1 -0
  36. package/dist/png.d.ts +2 -0
  37. package/dist/png.js +13 -0
  38. package/dist/png.js.map +1 -0
  39. package/dist/privacy.d.ts +7 -0
  40. package/dist/privacy.js +39 -0
  41. package/dist/privacy.js.map +1 -0
  42. package/dist/redact.d.ts +17 -0
  43. package/dist/redact.js +101 -0
  44. package/dist/redact.js.map +1 -0
  45. package/dist/run.d.ts +48 -0
  46. package/dist/run.js +218 -0
  47. package/dist/run.js.map +1 -0
  48. package/dist/summary.d.ts +7 -0
  49. package/dist/summary.js +134 -0
  50. package/dist/summary.js.map +1 -0
  51. package/dist/tests-detect.d.ts +19 -0
  52. package/dist/tests-detect.js +97 -0
  53. package/dist/tests-detect.js.map +1 -0
  54. package/dist/text.d.ts +8 -0
  55. package/dist/text.js +31 -0
  56. package/dist/text.js.map +1 -0
  57. package/dist/timeline/format.d.ts +28 -0
  58. package/dist/timeline/format.js +127 -0
  59. package/dist/timeline/format.js.map +1 -0
  60. package/dist/timeline/md.d.ts +17 -0
  61. package/dist/timeline/md.js +129 -0
  62. package/dist/timeline/md.js.map +1 -0
  63. package/dist/timeline/svg.d.ts +7 -0
  64. package/dist/timeline/svg.js +260 -0
  65. package/dist/timeline/svg.js.map +1 -0
  66. package/dist/timeline/wrap.d.ts +7 -0
  67. package/dist/timeline/wrap.js +77 -0
  68. package/dist/timeline/wrap.js.map +1 -0
  69. package/dist/types.d.ts +96 -0
  70. package/dist/types.js +5 -0
  71. package/dist/types.js.map +1 -0
  72. package/dist/version.d.ts +1 -0
  73. package/dist/version.js +2 -0
  74. package/dist/version.js.map +1 -0
  75. package/package.json +57 -4
package/dist/cli.js ADDED
@@ -0,0 +1,216 @@
1
+ #!/usr/bin/env node
2
+ import path from "node:path";
3
+ import { runPr, toPublicJson, formatPosted } from "./run.js";
4
+ import { NoSessionError } from "./discover.js";
5
+ import { envValue } from "./env.js";
6
+ import { VERSION } from "./version.js";
7
+ const HELP = `PRtape puts one image on the pull request.
8
+ See what your AI agent actually did.
9
+
10
+ Install:
11
+ npm i -g prtape-cli
12
+ npx prtape-cli pr
13
+
14
+ After a global install (npm i -g prtape-cli) the command is \`prtape\`.
15
+
16
+ Usage:
17
+ npx prtape-cli pr [options]
18
+
19
+ Options:
20
+ --cwd <dir> Project directory (default: current directory)
21
+ --session <file> Claude Code JSONL to read
22
+ --pr <number> Comment on this pull request (default: PR for the current branch)
23
+ --source auto|claude Claude Code only for now (default: auto)
24
+ --claude-home <dir> Claude config directory (default: ~/.claude or $CLAUDE_CONFIG_DIR)
25
+ --dry-run Print the comment and do not call gh
26
+ --json Print the redacted summary as JSON on stdout
27
+ --redact-emails Also redact email addresses
28
+ --demo Tag the timeline as a Demo project
29
+ --label demo Same as --demo
30
+ -h, --help Show this help
31
+ -V, --version Show the version
32
+
33
+ Examples:
34
+ npx prtape-cli pr
35
+ npx prtape-cli pr --dry-run
36
+ npx prtape-cli pr --json --dry-run
37
+ npx prtape-cli pr --session fixtures/claude-session.jsonl --dry-run
38
+
39
+ A real run pushes timeline.png to the orphan ref refs/prtape/<head> and
40
+ the comment leads with github.com/.../raw/<sha>/timeline.png. That ref is not
41
+ your branch. If gh is missing, not authenticated, or the push is denied,
42
+ PRtape prints what failed and how to fix it, then uses the text timeline.
43
+ --dry-run writes the PNG locally and does not push or comment.
44
+ Claude Code only for now.
45
+ `;
46
+ async function main(argv) {
47
+ let args;
48
+ try {
49
+ args = parseArgs(argv);
50
+ }
51
+ catch (error) {
52
+ const message = error instanceof Error ? error.message : String(error);
53
+ process.stderr.write(`${message}\n\n${HELP}`);
54
+ return 1;
55
+ }
56
+ if (args.version) {
57
+ process.stdout.write(`${VERSION}\n`);
58
+ return 0;
59
+ }
60
+ if (args.help || !args.command) {
61
+ process.stdout.write(HELP);
62
+ return args.help || !args.command ? 0 : 1;
63
+ }
64
+ if (args.command !== "pr") {
65
+ process.stderr.write(`Unknown command ${args.command}.\n\n${HELP}`);
66
+ return 1;
67
+ }
68
+ try {
69
+ const result = await runPr({
70
+ cwd: args.cwd ?? process.cwd(),
71
+ sessionPath: args.session,
72
+ source: args.source,
73
+ claudeHome: args.claudeHome,
74
+ dryRun: args.dryRun,
75
+ redactEmails: args.redactEmails,
76
+ prNumber: args.prNumber,
77
+ demo: args.demo,
78
+ });
79
+ writeResult(result, args.json);
80
+ return 0;
81
+ }
82
+ catch (error) {
83
+ const message = error instanceof Error ? error.message : String(error);
84
+ process.stderr.write(`${message}\n`);
85
+ if (envValue("DEBUG") && error instanceof Error && error.stack) {
86
+ process.stderr.write(`${error.stack}\n`);
87
+ }
88
+ return error instanceof NoSessionError ? 1 : 1;
89
+ }
90
+ }
91
+ function writeResult(result, json) {
92
+ const diagnostics = [
93
+ result.sessionNote,
94
+ result.posted ? undefined : result.note,
95
+ `SVG: ${result.svgPath}`,
96
+ result.pngPath ? `PNG: ${result.pngPath}` : undefined,
97
+ ]
98
+ .filter((line) => Boolean(line))
99
+ .join("\n");
100
+ if (json) {
101
+ if (diagnostics)
102
+ process.stderr.write(`${diagnostics}\n`);
103
+ if (result.posted) {
104
+ process.stderr.write(`${result.note}\n`);
105
+ if (result.prUrl)
106
+ process.stderr.write(`${result.prUrl}\n`);
107
+ }
108
+ process.stdout.write(`${JSON.stringify(toPublicJson(result.summary, { imageHosted: result.imageHosted, imageUrl: result.imageUrl }), null, 2)}\n`);
109
+ return;
110
+ }
111
+ if (result.posted) {
112
+ process.stdout.write(formatPosted(result));
113
+ if (result.sessionNote)
114
+ process.stderr.write(`${result.sessionNote}\n`);
115
+ return;
116
+ }
117
+ if (diagnostics)
118
+ process.stderr.write(`${diagnostics}\n`);
119
+ process.stdout.write(result.comment.endsWith("\n") ? result.comment : `${result.comment}\n`);
120
+ }
121
+ function parseArgs(argv) {
122
+ const args = {
123
+ help: false,
124
+ version: false,
125
+ source: "auto",
126
+ dryRun: false,
127
+ json: false,
128
+ redactEmails: false,
129
+ demo: false,
130
+ };
131
+ const rest = argv.slice(2);
132
+ const positional = [];
133
+ for (let index = 0; index < rest.length; index += 1) {
134
+ const token = rest[index];
135
+ if (token === undefined)
136
+ continue;
137
+ const take = () => {
138
+ const value = rest[index + 1];
139
+ if (value === undefined || value.startsWith("-")) {
140
+ throw new Error(`Missing value for ${token}`);
141
+ }
142
+ index += 1;
143
+ return value;
144
+ };
145
+ switch (token) {
146
+ case "-h":
147
+ case "--help":
148
+ args.help = true;
149
+ break;
150
+ case "-V":
151
+ case "--version":
152
+ args.version = true;
153
+ break;
154
+ case "--dry-run":
155
+ args.dryRun = true;
156
+ break;
157
+ case "--json":
158
+ args.json = true;
159
+ break;
160
+ case "--redact-emails":
161
+ args.redactEmails = true;
162
+ break;
163
+ case "--demo":
164
+ args.demo = true;
165
+ break;
166
+ case "--label":
167
+ if (take() === "demo")
168
+ args.demo = true;
169
+ break;
170
+ case "--cwd":
171
+ args.cwd = take();
172
+ break;
173
+ case "--session":
174
+ args.session = take();
175
+ break;
176
+ case "--pr": {
177
+ const value = Number(take());
178
+ if (!Number.isInteger(value) || value <= 0) {
179
+ throw new Error("--pr expects a positive pull request number");
180
+ }
181
+ args.prNumber = value;
182
+ break;
183
+ }
184
+ case "--claude-home":
185
+ args.claudeHome = take();
186
+ break;
187
+ case "--source": {
188
+ const value = take();
189
+ if (value !== "auto" && value !== "claude") {
190
+ throw new Error(`Unknown --source ${value}. Use auto or claude.`);
191
+ }
192
+ args.source = value;
193
+ break;
194
+ }
195
+ default:
196
+ if (token.startsWith("-"))
197
+ throw new Error(`Unknown option ${token}`);
198
+ positional.push(token);
199
+ }
200
+ }
201
+ if (positional.length > 1) {
202
+ throw new Error(`Unexpected argument ${positional.slice(1).join(" ")}`);
203
+ }
204
+ args.command = positional[0];
205
+ if (args.cwd)
206
+ args.cwd = path.resolve(args.cwd);
207
+ return args;
208
+ }
209
+ main(process.argv).then((code) => {
210
+ process.exitCode = code;
211
+ }, (error) => {
212
+ const message = error instanceof Error ? error.message : String(error);
213
+ process.stderr.write(`${message}\n`);
214
+ process.exitCode = 1;
215
+ });
216
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { SessionSummary } from "./types.js";
2
+ /**
3
+ * One short decision from the edits that actually happened.
4
+ * A test-file expectation change is not described as a source-code fix.
5
+ * Returns undefined when the diff does not establish a single change.
6
+ */
7
+ export declare function decisionFromEvents(summary: SessionSummary): string | undefined;
@@ -0,0 +1,224 @@
1
+ import { bashSubstitutions } from "./bash-edits.js";
2
+ /**
3
+ * One short decision from the edits that actually happened.
4
+ * A test-file expectation change is not described as a source-code fix.
5
+ * Returns undefined when the diff does not establish a single change.
6
+ */
7
+ export function decisionFromEvents(summary) {
8
+ const substitutions = substitutionsOf(summary);
9
+ const expectation = substitutions.filter((item) => item.shift && isTestFile(item.file));
10
+ const source = sourceReturn(summary);
11
+ if (expectation.length === 1 && !source) {
12
+ const item = expectation[0];
13
+ const shift = item?.shift;
14
+ if (!shift)
15
+ return undefined;
16
+ const sourceEdited = summary.events.some((event) => event.kind === "edit" && !isTestFile(event.path));
17
+ if (!sourceEdited && shift.callee) {
18
+ return `Correct test expectation from ${shift.from} to ${shift.to}; leave ${shift.callee}() unchanged.`;
19
+ }
20
+ return `Correct test expectation from ${shift.from} to ${shift.to}.`;
21
+ }
22
+ const small = expectation.length === 0 ? smallSourceEdit(summary) : undefined;
23
+ if (expectation.length === 0 && source && small)
24
+ return preferSpecific(source, small);
25
+ if (expectation.length === 0 && source)
26
+ return source;
27
+ if (expectation.length === 0 && small)
28
+ return small;
29
+ return undefined;
30
+ }
31
+ function preferSpecific(source, small) {
32
+ const span = /use (.+) instead of /.exec(small)?.[1] ?? "";
33
+ const expr = /return (.+)\.$/.exec(source)?.[1] ?? "";
34
+ if (span && expr.includes(span) && span.length + 8 < expr.length)
35
+ return small;
36
+ return source.length <= small.length ? source : small;
37
+ }
38
+ function smallSourceEdit(summary) {
39
+ const edits = summary.events.filter((event) => event.kind === "edit" && !isTestFile(event.path) && Boolean(event.before) && Boolean(event.after));
40
+ if (edits.length !== 1)
41
+ return undefined;
42
+ const edit = edits[0];
43
+ if (!edit?.before || !edit.after)
44
+ return undefined;
45
+ const change = spanChange(edit.before, edit.after);
46
+ if (!change)
47
+ return undefined;
48
+ const extracted = sessionSentence(summary);
49
+ if (extracted)
50
+ return capitalizeFirst(extracted);
51
+ const sentence = `In ${edit.path}, use ${change.added} instead of ${change.removed}.`;
52
+ if (sentence.length > 180)
53
+ return undefined;
54
+ return sentence;
55
+ }
56
+ /**
57
+ * A complete sentence copied from a commit message, a failing test name, or
58
+ * the assistant text. Hard-wrapped lines are joined before the split, and the
59
+ * result is never glued to a synthesized clause.
60
+ */
61
+ function sessionSentence(summary) {
62
+ const sources = [
63
+ ...summary.events.flatMap((event) => (event.kind === "commit" && event.message ? [event.message] : [])),
64
+ ...summary.events.flatMap((event) => (event.kind === "test" && event.failedName ? [event.failedName] : [])),
65
+ summary.decision,
66
+ ];
67
+ for (const source of sources) {
68
+ const sentence = firstCompleteSentence(source);
69
+ if (!sentence || isStatusReason(sentence))
70
+ continue;
71
+ if (normalizeSpace(source).includes(normalizeSpace(sentence)))
72
+ return sentence;
73
+ }
74
+ return undefined;
75
+ }
76
+ function firstCompleteSentence(message) {
77
+ const unwrapped = unwrapHardBreaks(message);
78
+ for (const paragraph of unwrapped.split("\n")) {
79
+ const parts = paragraph.split(/(?<=[.!?])\s+/);
80
+ for (const part of parts) {
81
+ const sentence = part.trim();
82
+ if (sentence.length < 12 || sentence.length > 180)
83
+ continue;
84
+ if (normalizeSpace(unwrapped).includes(normalizeSpace(sentence)))
85
+ return sentence;
86
+ }
87
+ }
88
+ return undefined;
89
+ }
90
+ /** Join a line that was wrapped in the editor. A blank line stays a paragraph break. */
91
+ function unwrapHardBreaks(message) {
92
+ return message
93
+ .replace(/\r\n/g, "\n")
94
+ .trim()
95
+ .split(/\n[ \t]*\n/)
96
+ .map((paragraph) => paragraph.replace(/[ \t]*\n[ \t]*/g, " ").replace(/[ \t]+/g, " ").trim())
97
+ .filter(Boolean)
98
+ .join("\n");
99
+ }
100
+ function normalizeSpace(value) {
101
+ return value.replace(/\s+/g, " ").trim();
102
+ }
103
+ function capitalizeFirst(text) {
104
+ const trimmed = text.trim();
105
+ if (!trimmed)
106
+ return trimmed;
107
+ return trimmed.charAt(0).toUpperCase() + trimmed.slice(1);
108
+ }
109
+ function isStatusReason(text) {
110
+ return /\b(?:tests?|suite) (?:passed|passes|failed)\b/i.test(text) || /全部通過|測試通過|edited \d+ file/i.test(text);
111
+ }
112
+ function spanChange(before, after) {
113
+ if (!before || !after || before === after)
114
+ return undefined;
115
+ if (before.length > 2000 || after.length > 2000)
116
+ return undefined;
117
+ let start = 0;
118
+ while (start < before.length && start < after.length && before[start] === after[start])
119
+ start += 1;
120
+ let endBefore = before.length;
121
+ let endAfter = after.length;
122
+ while (endBefore > start && endAfter > start && before[endBefore - 1] === after[endAfter - 1]) {
123
+ endBefore -= 1;
124
+ endAfter -= 1;
125
+ }
126
+ let removed = before.slice(start, endBefore);
127
+ let added = after.slice(start, endAfter);
128
+ if (!added && removed) {
129
+ const extra = /[\w.]+$/.exec(before.slice(0, start))?.[0] ?? "";
130
+ if (!extra)
131
+ return undefined;
132
+ removed = extra + removed;
133
+ added = extra;
134
+ }
135
+ else if (!removed && added) {
136
+ const extra = /[\w.]+$/.exec(after.slice(0, start))?.[0] ?? "";
137
+ if (!extra)
138
+ return undefined;
139
+ added = extra + added;
140
+ removed = extra;
141
+ }
142
+ removed = removed.trim();
143
+ added = added.trim();
144
+ if (!removed || !added || removed.length > 80 || added.length > 80)
145
+ return undefined;
146
+ return { removed, added };
147
+ }
148
+ function substitutionsOf(summary) {
149
+ const found = [];
150
+ for (const event of summary.events) {
151
+ if (event.kind === "test") {
152
+ for (const item of bashSubstitutions(event.command)) {
153
+ found.push({ file: item.file, shift: expectationShift(item.old, item.next) });
154
+ }
155
+ }
156
+ if (event.kind === "edit" && event.before && event.after && isTestFile(event.path)) {
157
+ found.push({ file: event.path, shift: expectationShift(event.before, event.after) });
158
+ }
159
+ }
160
+ const seen = new Set();
161
+ return found.filter((item) => {
162
+ const key = `${item.file}\0${item.shift?.from}\0${item.shift?.to}\0${item.shift?.callee ?? ""}`;
163
+ if (seen.has(key))
164
+ return false;
165
+ seen.add(key);
166
+ return true;
167
+ });
168
+ }
169
+ function expectationShift(before, after) {
170
+ if (!before || !after || before === after)
171
+ return undefined;
172
+ if (before.length > 2000 || after.length > 2000)
173
+ return undefined;
174
+ const skeleton = (value) => value.replace(/-?\d+(?:\.\d+)?/g, "#");
175
+ if (skeleton(before) !== skeleton(after))
176
+ return undefined;
177
+ const numbers = (value) => [...value.matchAll(/-?\d+(?:\.\d+)?/g)].map((match) => match[0]);
178
+ const left = numbers(before);
179
+ const right = numbers(after);
180
+ if (left.length === 0 || left.length !== right.length)
181
+ return undefined;
182
+ let from = "";
183
+ let to = "";
184
+ let diffs = 0;
185
+ for (let index = 0; index < left.length; index += 1) {
186
+ if (left[index] !== right[index]) {
187
+ diffs += 1;
188
+ from = left[index] ?? "";
189
+ to = right[index] ?? "";
190
+ }
191
+ }
192
+ if (diffs !== 1)
193
+ return undefined;
194
+ return { from, to, callee: calleeName(before) };
195
+ }
196
+ function calleeName(text) {
197
+ const wrapped = /(?:assert\.\w+|expect)\s*\(\s*([A-Za-z_][A-Za-z0-9_]*)\s*\(/.exec(text);
198
+ if (wrapped?.[1])
199
+ return wrapped[1];
200
+ const direct = /(?:^|[^\w.])([A-Za-z_][A-Za-z0-9_]*)\s*\(/.exec(text);
201
+ return direct?.[1];
202
+ }
203
+ function sourceReturn(summary) {
204
+ const edits = summary.events.filter((event) => event.kind === "edit" && !isTestFile(event.path) && Boolean(event.before) && Boolean(event.after));
205
+ if (edits.length !== 1)
206
+ return undefined;
207
+ const edit = edits[0];
208
+ if (!edit?.before || !edit.after)
209
+ return undefined;
210
+ const before = /return\s+([^;\n]+)/.exec(edit.before);
211
+ const after = /return\s+([^;\n]+)/.exec(edit.after);
212
+ if (!before?.[1] || !after?.[1] || before[1].trim() === after[1].trim())
213
+ return undefined;
214
+ const name = /function\s+([A-Za-z_][A-Za-z0-9_]*)/.exec(edit.before)?.[1] ??
215
+ /(?:const|let|var)\s+([A-Za-z_][A-Za-z0-9_]*)/.exec(edit.before)?.[1];
216
+ const expr = after[1].trim();
217
+ if (!name || expr.length > 40)
218
+ return undefined;
219
+ return `Change ${name}() to return ${expr}.`;
220
+ }
221
+ function isTestFile(filePath) {
222
+ return /\.(?:test|spec)\.[cm]?[jt]sx?$/i.test(filePath) || /_test\.[a-z]+$/i.test(filePath);
223
+ }
224
+ //# sourceMappingURL=decision.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decision.js","sourceRoot":"","sources":["../src/decision.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAGpD;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAAC,OAAuB;IACxD,MAAM,aAAa,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC;IAC/C,MAAM,WAAW,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IACxF,MAAM,MAAM,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC;IACrC,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;QACxC,MAAM,IAAI,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC;QAC5B,MAAM,KAAK,GAAG,IAAI,EAAE,KAAK,CAAC;QAC1B,IAAI,CAAC,KAAK;YAAE,OAAO,SAAS,CAAC;QAC7B,MAAM,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,MAAM,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;QACtG,IAAI,CAAC,YAAY,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;YAClC,OAAO,iCAAiC,KAAK,CAAC,IAAI,OAAO,KAAK,CAAC,EAAE,WAAW,KAAK,CAAC,MAAM,eAAe,CAAC;QAC1G,CAAC;QACD,OAAO,iCAAiC,KAAK,CAAC,IAAI,OAAO,KAAK,CAAC,EAAE,GAAG,CAAC;IACvE,CAAC;IACD,MAAM,KAAK,GAAG,WAAW,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAC9E,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,IAAI,MAAM,IAAI,KAAK;QAAE,OAAO,cAAc,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IACtF,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,IAAI,MAAM;QAAE,OAAO,MAAM,CAAC;IACtD,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,IAAI,KAAK;QAAE,OAAO,KAAK,CAAC;IACpD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAS,cAAc,CAAC,MAAc,EAAE,KAAa;IACnD,MAAM,IAAI,GAAG,sBAAsB,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAC3D,MAAM,IAAI,GAAG,gBAAgB,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IACtD,IAAI,IAAI,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,GAAG,IAAI,CAAC,MAAM;QAAE,OAAO,KAAK,CAAC;IAC/E,OAAO,MAAM,CAAC,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC;AACxD,CAAC;AAED,SAAS,eAAe,CAAC,OAAuB;IAC9C,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,CACjC,CAAC,KAAK,EAAwE,EAAE,CAC9E,KAAK,CAAC,IAAI,KAAK,MAAM,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CACpG,CAAC;IACF,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IACzC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;IACtB,IAAI,CAAC,IAAI,EAAE,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK;QAAE,OAAO,SAAS,CAAC;IACnD,MAAM,MAAM,GAAG,UAAU,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;IACnD,IAAI,CAAC,MAAM;QAAE,OAAO,SAAS,CAAC;IAC9B,MAAM,SAAS,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC;IAC3C,IAAI,SAAS;QAAE,OAAO,eAAe,CAAC,SAAS,CAAC,CAAC;IACjD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,IAAI,SAAS,MAAM,CAAC,KAAK,eAAe,MAAM,CAAC,OAAO,GAAG,CAAC;IACtF,IAAI,QAAQ,CAAC,MAAM,GAAG,GAAG;QAAE,OAAO,SAAS,CAAC;IAC5C,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;;;GAIG;AACH,SAAS,eAAe,CAAC,OAAuB;IAC9C,MAAM,OAAO,GAAG;QACd,GAAG,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,IAAI,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACvG,GAAG,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,IAAI,KAAK,MAAM,IAAI,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAC3G,OAAO,CAAC,QAAQ;KACjB,CAAC;IACF,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,MAAM,QAAQ,GAAG,qBAAqB,CAAC,MAAM,CAAC,CAAC;QAC/C,IAAI,CAAC,QAAQ,IAAI,cAAc,CAAC,QAAQ,CAAC;YAAE,SAAS;QACpD,IAAI,cAAc,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;YAAE,OAAO,QAAQ,CAAC;IACjF,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAS,qBAAqB,CAAC,OAAe;IAC5C,MAAM,SAAS,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAC;IAC5C,KAAK,MAAM,SAAS,IAAI,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QAC9C,MAAM,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;QAC/C,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;YAC7B,IAAI,QAAQ,CAAC,MAAM,GAAG,EAAE,IAAI,QAAQ,CAAC,MAAM,GAAG,GAAG;gBAAE,SAAS;YAC5D,IAAI,cAAc,CAAC,SAAS,CAAC,CAAC,QAAQ,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;gBAAE,OAAO,QAAQ,CAAC;QACpF,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,wFAAwF;AACxF,SAAS,gBAAgB,CAAC,OAAe;IACvC,OAAO,OAAO;SACX,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC;SACtB,IAAI,EAAE;SACN,KAAK,CAAC,YAAY,CAAC;SACnB,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,OAAO,CAAC,iBAAiB,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;SAC5F,MAAM,CAAC,OAAO,CAAC;SACf,IAAI,CAAC,IAAI,CAAC,CAAC;AAChB,CAAC;AAED,SAAS,cAAc,CAAC,KAAa;IACnC,OAAO,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;AAC3C,CAAC;AAED,SAAS,eAAe,CAAC,IAAY;IACnC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;IAC5B,IAAI,CAAC,OAAO;QAAE,OAAO,OAAO,CAAC;IAC7B,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAC5D,CAAC;AAED,SAAS,cAAc,CAAC,IAAY;IAClC,OAAO,gDAAgD,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,4BAA4B,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAChH,CAAC;AAED,SAAS,UAAU,CAAC,MAAc,EAAE,KAAa;IAC/C,IAAI,CAAC,MAAM,IAAI,CAAC,KAAK,IAAI,MAAM,KAAK,KAAK;QAAE,OAAO,SAAS,CAAC;IAC5D,IAAI,MAAM,CAAC,MAAM,GAAG,IAAI,IAAI,KAAK,CAAC,MAAM,GAAG,IAAI;QAAE,OAAO,SAAS,CAAC;IAClE,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,OAAO,KAAK,GAAG,MAAM,CAAC,MAAM,IAAI,KAAK,GAAG,KAAK,CAAC,MAAM,IAAI,MAAM,CAAC,KAAK,CAAC,KAAK,KAAK,CAAC,KAAK,CAAC;QAAE,KAAK,IAAI,CAAC,CAAC;IACnG,IAAI,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC;IAC9B,IAAI,QAAQ,GAAG,KAAK,CAAC,MAAM,CAAC;IAC5B,OAAO,SAAS,GAAG,KAAK,IAAI,QAAQ,GAAG,KAAK,IAAI,MAAM,CAAC,SAAS,GAAG,CAAC,CAAC,KAAK,KAAK,CAAC,QAAQ,GAAG,CAAC,CAAC,EAAE,CAAC;QAC9F,SAAS,IAAI,CAAC,CAAC;QACf,QAAQ,IAAI,CAAC,CAAC;IAChB,CAAC;IACD,IAAI,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;IAC7C,IAAI,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;IACzC,IAAI,CAAC,KAAK,IAAI,OAAO,EAAE,CAAC;QACtB,MAAM,KAAK,GAAG,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAChE,IAAI,CAAC,KAAK;YAAE,OAAO,SAAS,CAAC;QAC7B,OAAO,GAAG,KAAK,GAAG,OAAO,CAAC;QAC1B,KAAK,GAAG,KAAK,CAAC;IAChB,CAAC;SAAM,IAAI,CAAC,OAAO,IAAI,KAAK,EAAE,CAAC;QAC7B,MAAM,KAAK,GAAG,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAC/D,IAAI,CAAC,KAAK;YAAE,OAAO,SAAS,CAAC;QAC7B,KAAK,GAAG,KAAK,GAAG,KAAK,CAAC;QACtB,OAAO,GAAG,KAAK,CAAC;IAClB,CAAC;IACD,OAAO,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;IACzB,KAAK,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IACrB,IAAI,CAAC,OAAO,IAAI,CAAC,KAAK,IAAI,OAAO,CAAC,MAAM,GAAG,EAAE,IAAI,KAAK,CAAC,MAAM,GAAG,EAAE;QAAE,OAAO,SAAS,CAAC;IACrF,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;AAC5B,CAAC;AAQD,SAAS,eAAe,CAAC,OAAuB;IAC9C,MAAM,KAAK,GAAsC,EAAE,CAAC;IACpD,KAAK,MAAM,KAAK,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;QACnC,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YAC1B,KAAK,MAAM,IAAI,IAAI,iBAAiB,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;gBACpD,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,gBAAgB,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAChF,CAAC;QACH,CAAC;QACD,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,IAAI,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,KAAK,IAAI,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;YACnF,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,gBAAgB,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACvF,CAAC;IACH,CAAC;IACD,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE;QAC3B,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,KAAK,EAAE,IAAI,KAAK,IAAI,CAAC,KAAK,EAAE,EAAE,KAAK,IAAI,CAAC,KAAK,EAAE,MAAM,IAAI,EAAE,EAAE,CAAC;QAChG,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,OAAO,KAAK,CAAC;QAChC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACd,OAAO,IAAI,CAAC;IACd,CAAC,CAAC,CAAC;AACL,CAAC;AAED,SAAS,gBAAgB,CAAC,MAAc,EAAE,KAAa;IACrD,IAAI,CAAC,MAAM,IAAI,CAAC,KAAK,IAAI,MAAM,KAAK,KAAK;QAAE,OAAO,SAAS,CAAC;IAC5D,IAAI,MAAM,CAAC,MAAM,GAAG,IAAI,IAAI,KAAK,CAAC,MAAM,GAAG,IAAI;QAAE,OAAO,SAAS,CAAC;IAClE,MAAM,QAAQ,GAAG,CAAC,KAAa,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,kBAAkB,EAAE,GAAG,CAAC,CAAC;IAC3E,IAAI,QAAQ,CAAC,MAAM,CAAC,KAAK,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IAC3D,MAAM,OAAO,GAAG,CAAC,KAAa,EAAE,EAAE,CAAC,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,kBAAkB,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IACpG,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC7B,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;IAC7B,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,IAAI,IAAI,CAAC,MAAM,KAAK,KAAK,CAAC,MAAM;QAAE,OAAO,SAAS,CAAC;IACxE,IAAI,IAAI,GAAG,EAAE,CAAC;IACd,IAAI,EAAE,GAAG,EAAE,CAAC;IACZ,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC,MAAM,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;QACpD,IAAI,IAAI,CAAC,KAAK,CAAC,KAAK,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;YACjC,KAAK,IAAI,CAAC,CAAC;YACX,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;YACzB,EAAE,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;QAC1B,CAAC;IACH,CAAC;IACD,IAAI,KAAK,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IAClC,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,MAAM,EAAE,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;AAClD,CAAC;AAED,SAAS,UAAU,CAAC,IAAY;IAC9B,MAAM,OAAO,GAAG,6DAA6D,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACzF,IAAI,OAAO,EAAE,CAAC,CAAC,CAAC;QAAE,OAAO,OAAO,CAAC,CAAC,CAAC,CAAC;IACpC,MAAM,MAAM,GAAG,2CAA2C,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACtE,OAAO,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC;AACrB,CAAC;AAED,SAAS,YAAY,CAAC,OAAuB;IAC3C,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,CACjC,CAAC,KAAK,EAAwE,EAAE,CAC9E,KAAK,CAAC,IAAI,KAAK,MAAM,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CACpG,CAAC;IACF,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IACzC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;IACtB,IAAI,CAAC,IAAI,EAAE,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK;QAAE,OAAO,SAAS,CAAC;IACnD,MAAM,MAAM,GAAG,oBAAoB,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACtD,MAAM,KAAK,GAAG,oBAAoB,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACpD,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE;QAAE,OAAO,SAAS,CAAC;IAC1F,MAAM,IAAI,GACR,qCAAqC,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;QAC5D,8CAA8C,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IACxE,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAC7B,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,GAAG,EAAE;QAAE,OAAO,SAAS,CAAC;IAChD,OAAO,UAAU,IAAI,gBAAgB,IAAI,GAAG,CAAC;AAC/C,CAAC;AAED,SAAS,UAAU,CAAC,QAAgB;IAClC,OAAO,iCAAiC,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,iBAAiB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;AAC9F,CAAC"}
@@ -0,0 +1,32 @@
1
+ import type { SourceKind } from "./types.js";
2
+ export type SourceChoice = "auto" | "claude";
3
+ export interface DiscoverOptions {
4
+ cwd: string;
5
+ source: SourceChoice;
6
+ claudeHome: string;
7
+ /** Injected so tests do not need a git repository. */
8
+ recentFiles?: string[];
9
+ }
10
+ export interface FoundSession {
11
+ source: SourceKind;
12
+ path: string;
13
+ note?: string;
14
+ }
15
+ export declare class NoSessionError extends Error {
16
+ constructor(message: string);
17
+ }
18
+ /** Claude config dir. `CLAUDE_CONFIG_DIR` is honored when set; otherwise `~/.claude`. */
19
+ export declare function defaultClaudeHome(env?: NodeJS.ProcessEnv, home?: string): string;
20
+ /**
21
+ * Directory slug Claude Code uses under `projects/`.
22
+ * Replaces ":", "\", and "/" with "-". The encoding is lossy when the path
23
+ * itself contains dashes, so selection still reads the `cwd` field.
24
+ */
25
+ export declare function claudeProjectSlug(cwd: string): string;
26
+ export declare function pathsRelated(leftPath: string, rightPath: string): boolean;
27
+ export declare function listClaudeSessions(claudeHome: string): string[];
28
+ export declare function selectClaudeSession(files: string[], targetCwd: string, recentFiles?: string[]): string | null;
29
+ export declare function findSession(options: DiscoverOptions): FoundSession;
30
+ export declare function gitChangedFiles(cwd: string): string[];
31
+ /** Read `cwd` from the head of a session file. The first record normally carries it. */
32
+ export declare function sniffCwd(file: string): string | undefined;