@alexgsdev/claude-code-transcript-export 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +134 -0
  3. package/dist/cli/args.d.ts +23 -0
  4. package/dist/cli/args.d.ts.map +1 -0
  5. package/dist/cli/args.js +85 -0
  6. package/dist/cli/args.js.map +1 -0
  7. package/dist/cli/index.d.ts +10 -0
  8. package/dist/cli/index.d.ts.map +1 -0
  9. package/dist/cli/index.js +230 -0
  10. package/dist/cli/index.js.map +1 -0
  11. package/dist/cli/init.d.ts +2 -0
  12. package/dist/cli/init.d.ts.map +1 -0
  13. package/dist/cli/init.js +35 -0
  14. package/dist/cli/init.js.map +1 -0
  15. package/dist/cli/probe.d.ts +18 -0
  16. package/dist/cli/probe.d.ts.map +1 -0
  17. package/dist/cli/probe.js +83 -0
  18. package/dist/cli/probe.js.map +1 -0
  19. package/dist/commits.d.ts +31 -0
  20. package/dist/commits.d.ts.map +1 -0
  21. package/dist/commits.js +59 -0
  22. package/dist/commits.js.map +1 -0
  23. package/dist/config.d.ts +65 -0
  24. package/dist/config.d.ts.map +1 -0
  25. package/dist/config.js +189 -0
  26. package/dist/config.js.map +1 -0
  27. package/dist/content.d.ts +50 -0
  28. package/dist/content.d.ts.map +1 -0
  29. package/dist/content.js +141 -0
  30. package/dist/content.js.map +1 -0
  31. package/dist/discover.d.ts +55 -0
  32. package/dist/discover.d.ts.map +1 -0
  33. package/dist/discover.js +116 -0
  34. package/dist/discover.js.map +1 -0
  35. package/dist/extract.d.ts +47 -0
  36. package/dist/extract.d.ts.map +1 -0
  37. package/dist/extract.js +127 -0
  38. package/dist/extract.js.map +1 -0
  39. package/dist/index.d.ts +24 -0
  40. package/dist/index.d.ts.map +1 -0
  41. package/dist/index.js +23 -0
  42. package/dist/index.js.map +1 -0
  43. package/dist/paths.d.ts +31 -0
  44. package/dist/paths.d.ts.map +1 -0
  45. package/dist/paths.js +47 -0
  46. package/dist/paths.js.map +1 -0
  47. package/dist/render/index.d.ts +21 -0
  48. package/dist/render/index.d.ts.map +1 -0
  49. package/dist/render/index.js +68 -0
  50. package/dist/render/index.js.map +1 -0
  51. package/dist/render/transcript.d.ts +31 -0
  52. package/dist/render/transcript.d.ts.map +1 -0
  53. package/dist/render/transcript.js +54 -0
  54. package/dist/render/transcript.js.map +1 -0
  55. package/dist/session.d.ts +30 -0
  56. package/dist/session.d.ts.map +1 -0
  57. package/dist/session.js +99 -0
  58. package/dist/session.js.map +1 -0
  59. package/dist/titles.d.ts +26 -0
  60. package/dist/titles.d.ts.map +1 -0
  61. package/dist/titles.js +51 -0
  62. package/dist/titles.js.map +1 -0
  63. package/dist/turns.d.ts +62 -0
  64. package/dist/turns.d.ts.map +1 -0
  65. package/dist/turns.js +108 -0
  66. package/dist/turns.js.map +1 -0
  67. package/dist/types.d.ts +95 -0
  68. package/dist/types.d.ts.map +1 -0
  69. package/dist/types.js +14 -0
  70. package/dist/types.js.map +1 -0
  71. package/dist/write.d.ts +61 -0
  72. package/dist/write.d.ts.map +1 -0
  73. package/dist/write.js +126 -0
  74. package/dist/write.js.map +1 -0
  75. package/package.json +64 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Alex Gates-Shannon
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,134 @@
1
+ # Claude Code Transcript Export (cctx)
2
+
3
+ Extract Claude Code session logs into readable, committable markdown transcripts.
4
+
5
+ Claude Code transcripts exist in exactly one place: JSONL files under
6
+ `~/.claude/projects/`, on the machine where the work happened. They are not in
7
+ the claude.ai account export and never will be. They are also not durable —
8
+ they are a cache, subject to pruning by a tool that does not consider them
9
+ precious.
10
+
11
+ `cctx` moves them from a location that forgets into one that remembers.
12
+
13
+ ## Install
14
+
15
+ ```sh
16
+ npm install -g cctx
17
+ ```
18
+
19
+ Requires Node 22 or newer.
20
+
21
+ ## Use
22
+
23
+ From anywhere inside your project:
24
+
25
+ ```sh
26
+ cctx init # write .claude-export.yaml — its location marks the project root
27
+ cctx list # see every session, with its UUID
28
+ cctx # write transcripts
29
+ ```
30
+
31
+ Output looks like this:
32
+
33
+ ```
34
+ docs/sessions/
35
+ index.md
36
+ 2026-08-29--consolidating-the-two-sites--0ba0029e.md
37
+ images/
38
+ 0ba0029e-3f9c1a72.png
39
+ ```
40
+
41
+ Each transcript carries YAML frontmatter (title, session id, dates, turn count,
42
+ links to continued sessions) and the conversation as numbered, speaker-labelled
43
+ turns.
44
+
45
+ ### Commands
46
+
47
+ | | |
48
+ | --- | --- |
49
+ | `cctx` / `cctx extract` | Write transcripts for this project |
50
+ | `cctx list` | Every session with UUID, date, turn count and status |
51
+ | `cctx probe` | Report the observed log schema |
52
+ | `cctx init` | Write a starter config in the current directory |
53
+
54
+ Useful flags: `--project <path>` to work outside a configured project,
55
+ `--dry-run`, `--json`, `--keep-tools`, `--keep-thinking`, `--ignore-config`.
56
+
57
+ ## How it decides things
58
+
59
+ **A turn is one exchange, not one record.** A single reply is spread across many
60
+ records — text, a tool call, its result, more text. Those coalesce into one
61
+ turn, because that is what a citation wants to name. The cost: turn numbers are
62
+ stable only while the filter is.
63
+
64
+ **Most `user` records are not you.** Across the corpus this was built against,
65
+ 775 of 10,600 `user` records are the human actually speaking — 7.3%. The rest
66
+ are tool results the harness feeds back. Treating them all as turns would
67
+ inflate a transcript fourteenfold.
68
+
69
+ **Tool payloads and thinking are dropped by default.** Anything authored in a
70
+ Claude Code session lands in your working tree and is captured by the commit, so
71
+ the payload is redundant with git while making up most of the bytes. What is
72
+ unique to the transcript is the prose. Pass `--keep-tools` if you disagree.
73
+
74
+ **Images are kept.** Screenshots you paste exist nowhere but the log, so they
75
+ are written alongside the transcript, named by a hash of their content.
76
+
77
+ **Dates are local.** A session beginning `2026-08-25T00:13Z` is 17:13 on
78
+ 2026-08-24 where you were sitting, and so is the commit it produced.
79
+
80
+ **A rerun over unchanged logs writes nothing.** `extracted:` means the day a
81
+ transcript's content last changed, not the day the tool last ran, so reruns do
82
+ not produce a wall of one-line diffs.
83
+
84
+ **Deletion is narrow.** Renamed and newly-excluded transcripts are removed and
85
+ reported. Nothing else, ever — the logs are ephemeral and this output is the
86
+ durable copy, so a directory sync would delete precisely the transcripts that
87
+ can no longer be regenerated. Orphaned images are reported but never deleted.
88
+
89
+ ## Configuration
90
+
91
+ `.claude-export.yaml`, at the project root. `cctx init` writes a commented
92
+ starter. Every key is optional; see
93
+ [the specification](docs/specs/01-initial-specification.md) for the full list.
94
+
95
+ Sessions are selected by UUID — titles are model-generated and change while you
96
+ work, so they are not a stable selector. Run `cctx list` to get the ids.
97
+
98
+ > A blocklist is permanent. The logs are a cache: a session you exclude today,
99
+ > whose log Claude Code prunes next month, is unrecoverable. `cctx
100
+ > --ignore-config --out <scratch>` captures everything if you want to look
101
+ > first.
102
+
103
+ ## On schema drift
104
+
105
+ The Claude Code log format is undocumented and it moves. This package was
106
+ written against 84 logs on one machine, and during a single afternoon of
107
+ drafting, two design decisions had to be reversed by observation.
108
+
109
+ The test suite guards against *our* regressions. **It cannot detect Claude Code
110
+ changing its format**, because CI has no real logs to look at. A green badge
111
+ here does not mean the parser still fits your logs.
112
+
113
+ Detecting that stays a manual act:
114
+
115
+ ```sh
116
+ cctx probe
117
+ ```
118
+
119
+ It reports every record and block type it sees, and names the ones this version
120
+ does not handle. Run it when output looks wrong.
121
+
122
+ ## Library
123
+
124
+ ```ts
125
+ import { discover, readSession, renderTranscript } from 'cctx';
126
+ ```
127
+
128
+ Everything is pure unless its name says otherwise — nothing below the CLI layer
129
+ reads the clock, the environment, or your home directory. See
130
+ [the specification](docs/specs/01-initial-specification.md) §12.
131
+
132
+ ## License
133
+
134
+ MIT
@@ -0,0 +1,23 @@
1
+ export type Command = 'extract' | 'list' | 'probe' | 'init' | 'help' | 'version';
2
+ export interface Options {
3
+ command: Command;
4
+ config?: string;
5
+ project?: string;
6
+ out?: string;
7
+ logRoot?: string;
8
+ keepTools: boolean;
9
+ keepThinking: boolean;
10
+ commits?: boolean;
11
+ ignoreConfig: boolean;
12
+ dryRun: boolean;
13
+ json: boolean;
14
+ }
15
+ /**
16
+ * Parses argv.
17
+ *
18
+ * An unrecognized flag is an error naming the flag, never a silent ignore: a
19
+ * misspelled `--project` that quietly extracts the wrong directory is worse
20
+ * than a failure.
21
+ */
22
+ export declare function parseArgs(argv: string[]): Options;
23
+ //# sourceMappingURL=args.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"args.d.ts","sourceRoot":"","sources":["../../src/cli/args.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,OAAO,GAAG,SAAS,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;AAEjF,MAAM,WAAW,OAAO;IACtB,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,OAAO,CAAC;IACnB,YAAY,EAAE,OAAO,CAAC;IACtB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,YAAY,EAAE,OAAO,CAAC;IACtB,MAAM,EAAE,OAAO,CAAC;IAChB,IAAI,EAAE,OAAO,CAAC;CACf;AAMD;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CA2EjD"}
@@ -0,0 +1,85 @@
1
+ import { UsageError } from '../config.js';
2
+ const COMMANDS = ['extract', 'list', 'probe', 'init'];
3
+ const VALUE_FLAGS = new Set(['--config', '--project', '--out', '--log-root']);
4
+ /**
5
+ * Parses argv.
6
+ *
7
+ * An unrecognized flag is an error naming the flag, never a silent ignore: a
8
+ * misspelled `--project` that quietly extracts the wrong directory is worse
9
+ * than a failure.
10
+ */
11
+ export function parseArgs(argv) {
12
+ const options = {
13
+ command: 'extract',
14
+ keepTools: false,
15
+ keepThinking: false,
16
+ ignoreConfig: false,
17
+ dryRun: false,
18
+ json: false,
19
+ };
20
+ let index = 0;
21
+ const first = argv[0];
22
+ if (first !== undefined && !first.startsWith('-')) {
23
+ if (!COMMANDS.includes(first)) {
24
+ throw new UsageError(`unknown command \`${first}\`. Expected one of ${COMMANDS.join(', ')}.`);
25
+ }
26
+ options.command = first;
27
+ index = 1;
28
+ }
29
+ for (; index < argv.length; index += 1) {
30
+ const arg = argv[index];
31
+ if (arg === undefined)
32
+ continue;
33
+ if (VALUE_FLAGS.has(arg)) {
34
+ const value = argv[index + 1];
35
+ if (value === undefined || value.startsWith('--')) {
36
+ throw new UsageError(`${arg} needs a path.`);
37
+ }
38
+ if (arg === '--config')
39
+ options.config = value;
40
+ else if (arg === '--project')
41
+ options.project = value;
42
+ else if (arg === '--out')
43
+ options.out = value;
44
+ else
45
+ options.logRoot = value;
46
+ index += 1;
47
+ continue;
48
+ }
49
+ switch (arg) {
50
+ case '--help':
51
+ case '-h':
52
+ options.command = 'help';
53
+ break;
54
+ case '--version':
55
+ case '-v':
56
+ options.command = 'version';
57
+ break;
58
+ case '--keep-tools':
59
+ options.keepTools = true;
60
+ break;
61
+ case '--keep-thinking':
62
+ options.keepThinking = true;
63
+ break;
64
+ case '--commits':
65
+ options.commits = true;
66
+ break;
67
+ case '--no-commits':
68
+ options.commits = false;
69
+ break;
70
+ case '--ignore-config':
71
+ options.ignoreConfig = true;
72
+ break;
73
+ case '--dry-run':
74
+ options.dryRun = true;
75
+ break;
76
+ case '--json':
77
+ options.json = true;
78
+ break;
79
+ default:
80
+ throw new UsageError(`unrecognized argument \`${arg}\`.`);
81
+ }
82
+ }
83
+ return options;
84
+ }
85
+ //# sourceMappingURL=args.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"args.js","sourceRoot":"","sources":["../../src/cli/args.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env node
2
+ import { DEFAULT_CONFIG } from '../config.js';
3
+ export declare function main(argv: string[], io: {
4
+ stdout: NodeJS.WritableStream;
5
+ stderr: NodeJS.WritableStream;
6
+ cwd: string;
7
+ env: NodeJS.ProcessEnv;
8
+ }): number;
9
+ export { DEFAULT_CONFIG };
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":";AAKA,OAAO,EAEL,cAAc,EAIf,MAAM,cAAc,CAAC;AA2GtB,wBAAgB,IAAI,CAClB,IAAI,EAAE,MAAM,EAAE,EACd,EAAE,EAAE;IACF,MAAM,EAAE,MAAM,CAAC,cAAc,CAAC;IAC9B,MAAM,EAAE,MAAM,CAAC,cAAc,CAAC;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;CACxB,GACA,MAAM,CA+HR;AA+BD,OAAO,EAAE,cAAc,EAAE,CAAC"}
@@ -0,0 +1,230 @@
1
+ #!/usr/bin/env node
2
+ import { existsSync, realpathSync, writeFileSync } from 'node:fs';
3
+ import { homedir } from 'node:os';
4
+ import { join, relative, resolve } from 'node:path';
5
+ import { pathToFileURL } from 'node:url';
6
+ import { CONFIG_NAMES, DEFAULT_CONFIG, UsageError, loadConfig, } from '../config.js';
7
+ import { discover, listLogFiles } from '../discover.js';
8
+ import { extract, readSessions } from '../extract.js';
9
+ import { defaultLogRoot } from '../paths.js';
10
+ import { TEMPLATE } from './init.js';
11
+ import { formatProbe, probeRecords } from './probe.js';
12
+ import { parseArgs } from './args.js';
13
+ const USAGE = `cctx — extract Claude Code session logs into markdown transcripts.
14
+
15
+ Usage:
16
+ cctx [extract] Write transcripts for this project (default)
17
+ cctx list Show every session and its status
18
+ cctx probe Report the observed log schema
19
+ cctx init Write a .claude-export.yaml here
20
+
21
+ Options:
22
+ --config <path> Use this config file
23
+ --project <path> Treat this directory as the project root
24
+ --out <path> Override the output directory
25
+ --log-root <path> Where Claude Code keeps logs (default ~/.claude/projects)
26
+ --keep-tools Keep tool_use and tool_result payloads
27
+ --keep-thinking Keep thinking blocks
28
+ --commits Pair sessions with commits made while they were open
29
+ --ignore-config Ignore include/exclude, capturing everything
30
+ --dry-run Report what would happen, write nothing
31
+ --json Emit the summary as JSON
32
+ -h, --help This message
33
+ -v, --version Print the version`;
34
+ /** Applies command-line overrides on top of a loaded config. */
35
+ function applyOverrides(config, options) {
36
+ const merged = { ...config, index: { ...config.index } };
37
+ if (options.out !== undefined)
38
+ merged.out = options.out;
39
+ if (options.keepTools)
40
+ merged.tools = 'keep';
41
+ if (options.keepThinking)
42
+ merged.thinking = 'keep';
43
+ if (options.commits !== undefined)
44
+ merged.commits = options.commits;
45
+ if (options.ignoreConfig) {
46
+ merged.include = [];
47
+ merged.exclude = [];
48
+ }
49
+ return merged;
50
+ }
51
+ function resolveContext(options, cwd) {
52
+ const logRoot = resolve(options.logRoot ?? defaultLogRoot(homedir()));
53
+ if (options.config !== undefined) {
54
+ const path = resolve(options.config);
55
+ if (!existsSync(path))
56
+ throw new UsageError(`no such config file: ${path}`);
57
+ const loaded = loadConfig(path.replace(/\/[^/]+$/, ''));
58
+ if (loaded === null)
59
+ throw new UsageError(`could not read config at ${path}`);
60
+ return { ...loaded, config: applyOverrides(loaded.config, options), logRoot };
61
+ }
62
+ const loaded = loadConfig(cwd, options.project);
63
+ if (loaded === null) {
64
+ throw new UsageError(`no ${CONFIG_NAMES[0]} found in ${cwd} or any parent directory. ` +
65
+ 'Run `cctx init` to create one, or pass --project <path>.');
66
+ }
67
+ return { ...loaded, config: applyOverrides(loaded.config, options), logRoot };
68
+ }
69
+ function todayLocal(now = new Date()) {
70
+ const year = now.getFullYear();
71
+ const month = `${now.getMonth() + 1}`.padStart(2, '0');
72
+ const day = `${now.getDate()}`.padStart(2, '0');
73
+ return `${year}-${month}-${day}`;
74
+ }
75
+ function reportExtract(summary, out) {
76
+ const rel = relative(summary.root, summary.outDir) || '.';
77
+ out.write(`project root: ${summary.root}\n`);
78
+ out.write(`output: ${rel}\n`);
79
+ out.write(`sessions: ${summary.sessions}, written: ${summary.written}, ` +
80
+ `unchanged: ${summary.unchanged}, turns: ${summary.turns}\n`);
81
+ for (const image of summary.imagesWritten)
82
+ out.write(`image written: ${image}\n`);
83
+ for (const skip of summary.skipped) {
84
+ out.write(`skipped (${skip.reason}): ${skip.title} [${skip.id.slice(0, 8)}]\n`);
85
+ }
86
+ // Reported rather than silent: a deletion in a generated directory should be
87
+ // something the author sees in the output as well as the diff.
88
+ for (const removed of summary.removed) {
89
+ out.write(`removed (${removed.reason}): ${removed.name}\n`);
90
+ }
91
+ if (summary.orphanImages.length > 0) {
92
+ out.write(`\n${summary.orphanImages.length} image(s) no transcript references. ` +
93
+ 'Not deleted — an image cannot be regenerated once its log is pruned:\n');
94
+ for (const name of summary.orphanImages)
95
+ out.write(` ${name}\n`);
96
+ }
97
+ }
98
+ export function main(argv, io) {
99
+ let options;
100
+ try {
101
+ options = parseArgs(argv);
102
+ }
103
+ catch (cause) {
104
+ if (cause instanceof UsageError) {
105
+ io.stderr.write(`cctx: ${cause.message}\n`);
106
+ return 2;
107
+ }
108
+ throw cause;
109
+ }
110
+ try {
111
+ if (options.command === 'help') {
112
+ io.stdout.write(`${USAGE}\n`);
113
+ return 0;
114
+ }
115
+ if (options.command === 'version') {
116
+ io.stdout.write('0.1.0\n');
117
+ return 0;
118
+ }
119
+ if (options.command === 'init') {
120
+ const path = join(io.cwd, CONFIG_NAMES[0]);
121
+ if (existsSync(path)) {
122
+ io.stderr.write(`cctx: ${path} already exists.\n`);
123
+ return 1;
124
+ }
125
+ writeFileSync(path, TEMPLATE);
126
+ io.stdout.write(`wrote ${path}\nproject root: ${io.cwd}\n`);
127
+ return 0;
128
+ }
129
+ const context = resolveContext(options, io.cwd);
130
+ // The only clock and environment reads in the package live here.
131
+ const today = todayLocal();
132
+ const currentSessionId = io.env.CLAUDE_CODE_SESSION_ID;
133
+ if (options.command === 'probe') {
134
+ const paths = listLogFiles(context.logRoot);
135
+ const report = probeRecords(discover(context.logRoot, context.root).map((log) => ({
136
+ path: log.path,
137
+ records: log.records,
138
+ })));
139
+ io.stdout.write(`project root: ${context.root}\n`);
140
+ io.stdout.write(`log root: ${context.logRoot} (${paths.length} logs, all projects)\n\n`);
141
+ io.stdout.write(options.json
142
+ ? `${JSON.stringify(report, null, 2)}\n`
143
+ : `${formatProbe(report)}\n`);
144
+ return 0;
145
+ }
146
+ if (options.command === 'list') {
147
+ const sessions = readSessions(discover(context.logRoot, context.root), context.config);
148
+ if (options.json) {
149
+ io.stdout.write(`${JSON.stringify(sessions.map((s) => ({
150
+ id: s.id,
151
+ created: s.created,
152
+ title: s.title,
153
+ turns: s.turns.length,
154
+ kind: s.kind,
155
+ excluded: context.config.exclude.includes(s.id),
156
+ })), null, 2)}\n`);
157
+ return 0;
158
+ }
159
+ io.stdout.write(`project root: ${context.root}\n\n`);
160
+ if (sessions.length === 0) {
161
+ io.stdout.write('no sessions found for this project\n');
162
+ return 0;
163
+ }
164
+ for (const session of sessions) {
165
+ const status = context.config.exclude.includes(session.id)
166
+ ? 'excluded'
167
+ : session.turns.length === 0
168
+ ? 'empty'
169
+ : 'included';
170
+ io.stdout.write(`${session.id} ${session.created} ${String(session.turns.length).padStart(4)} turns ` +
171
+ `${status.padEnd(8)} ${session.title}\n`);
172
+ }
173
+ return 0;
174
+ }
175
+ const summary = extract({
176
+ root: context.root,
177
+ logRoot: context.logRoot,
178
+ config: context.config,
179
+ today,
180
+ currentSessionId,
181
+ dryRun: options.dryRun,
182
+ });
183
+ if (options.json) {
184
+ io.stdout.write(`${JSON.stringify(summary, null, 2)}\n`);
185
+ }
186
+ else {
187
+ if (options.dryRun)
188
+ io.stdout.write('dry run: nothing written\n');
189
+ reportExtract(summary, io.stdout);
190
+ }
191
+ return 0;
192
+ }
193
+ catch (cause) {
194
+ if (cause instanceof UsageError) {
195
+ io.stderr.write(`cctx: ${cause.message}\n`);
196
+ return 2;
197
+ }
198
+ io.stderr.write(`cctx: ${cause instanceof Error ? (cause.stack ?? cause.message) : String(cause)}\n`);
199
+ return 1;
200
+ }
201
+ }
202
+ /**
203
+ * Run only when this file is the entry point.
204
+ *
205
+ * Two things this has to get right, both of which were wrong first:
206
+ *
207
+ * - Testing that `process.argv[1]` is merely defined is not a main-module
208
+ * check. It is true on any import, so importing `main` in a test executed
209
+ * the whole CLI as a side effect.
210
+ *
211
+ * - `process.argv[1]` is the path node was invoked with, which for an
212
+ * installed package is the `node_modules/.bin/cctx` **symlink**, while
213
+ * `import.meta.url` is the real file it points at. Comparing them without
214
+ * resolving the link means the installed binary silently does nothing.
215
+ */
216
+ /* c8 ignore start */
217
+ const entry = process.argv[1];
218
+ const entryUrl = entry === undefined ? undefined : pathToFileURL(realpathSync(entry)).href;
219
+ if (entryUrl !== undefined && import.meta.url === entryUrl) {
220
+ const code = main(process.argv.slice(2), {
221
+ stdout: process.stdout,
222
+ stderr: process.stderr,
223
+ cwd: process.cwd(),
224
+ env: process.env,
225
+ });
226
+ process.exitCode = code;
227
+ }
228
+ /* c8 ignore stop */
229
+ export { DEFAULT_CONFIG };
230
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare const TEMPLATE = "# cctx configuration. This file's location marks the project root.\n\n# Where transcripts are written, relative to this file.\nout: docs/sessions\n\n# Session UUIDs. Block always wins over allow, and a non-empty `include`\n# switches to opt-in-only. Run `cctx list` to see the ids.\n#\n# Note: the logs are a cache Claude Code prunes. A session excluded here whose\n# log is later pruned is gone permanently.\nexclude: []\ninclude: []\n\n# Content policy.\ntools: strip # strip | keep\nthinking: drop # drop | keep\nimages: extract # extract | marker\nimageDir: images\nsubagents: ignore # ignore | capture\nskipEmpty: true\n\n# Sessions still being written are captured by default; a partial transcript\n# beats no transcript and self-heals on the next run.\nskipActive: false\nactiveGraceMinutes: 30\n\n# Pair each session with commits authored while it was open.\ncommits: false\n\nindex:\n enabled: true\n preamble: null # project-specific prose, inserted verbatim\n listExcluded: count # count | ids | none\n";
2
+ //# sourceMappingURL=init.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/cli/init.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,QAAQ,6/BAiCpB,CAAC"}
@@ -0,0 +1,35 @@
1
+ export const TEMPLATE = `# cctx configuration. This file's location marks the project root.
2
+
3
+ # Where transcripts are written, relative to this file.
4
+ out: docs/sessions
5
+
6
+ # Session UUIDs. Block always wins over allow, and a non-empty \`include\`
7
+ # switches to opt-in-only. Run \`cctx list\` to see the ids.
8
+ #
9
+ # Note: the logs are a cache Claude Code prunes. A session excluded here whose
10
+ # log is later pruned is gone permanently.
11
+ exclude: []
12
+ include: []
13
+
14
+ # Content policy.
15
+ tools: strip # strip | keep
16
+ thinking: drop # drop | keep
17
+ images: extract # extract | marker
18
+ imageDir: images
19
+ subagents: ignore # ignore | capture
20
+ skipEmpty: true
21
+
22
+ # Sessions still being written are captured by default; a partial transcript
23
+ # beats no transcript and self-heals on the next run.
24
+ skipActive: false
25
+ activeGraceMinutes: 30
26
+
27
+ # Pair each session with commits authored while it was open.
28
+ commits: false
29
+
30
+ index:
31
+ enabled: true
32
+ preamble: null # project-specific prose, inserted verbatim
33
+ listExcluded: count # count | ids | none
34
+ `;
35
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/cli/init.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,QAAQ,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiCvB,CAAC"}
@@ -0,0 +1,18 @@
1
+ import type { RawRecord } from '../types.js';
2
+ export interface ProbeReport {
3
+ files: number;
4
+ recordTypes: Record<string, number>;
5
+ blockTypes: Record<string, number>;
6
+ userRecords: number;
7
+ humanTurns: number;
8
+ /** Record types seen that the renderer does not handle. */
9
+ unhandledRecords: string[];
10
+ unhandledBlocks: string[];
11
+ }
12
+ export declare function probeRecords(files: {
13
+ path: string;
14
+ records: RawRecord[];
15
+ }[]): ProbeReport;
16
+ export declare function probe(paths: string[]): ProbeReport;
17
+ export declare function formatProbe(report: ProbeReport): string;
18
+ //# sourceMappingURL=probe.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"probe.d.ts","sourceRoot":"","sources":["../../src/cli/probe.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAqB7C,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,2DAA2D;IAC3D,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,eAAe,EAAE,MAAM,EAAE,CAAC;CAC3B;AAED,wBAAgB,YAAY,CAC1B,KAAK,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,SAAS,EAAE,CAAA;CAAE,EAAE,GAC9C,WAAW,CA0Cb;AAED,wBAAgB,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,WAAW,CAElD;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CA+BvD"}