@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.
- package/LICENSE +21 -0
- package/README.md +134 -0
- package/dist/cli/args.d.ts +23 -0
- package/dist/cli/args.d.ts.map +1 -0
- package/dist/cli/args.js +85 -0
- package/dist/cli/args.js.map +1 -0
- package/dist/cli/index.d.ts +10 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +230 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/init.d.ts +2 -0
- package/dist/cli/init.d.ts.map +1 -0
- package/dist/cli/init.js +35 -0
- package/dist/cli/init.js.map +1 -0
- package/dist/cli/probe.d.ts +18 -0
- package/dist/cli/probe.d.ts.map +1 -0
- package/dist/cli/probe.js +83 -0
- package/dist/cli/probe.js.map +1 -0
- package/dist/commits.d.ts +31 -0
- package/dist/commits.d.ts.map +1 -0
- package/dist/commits.js +59 -0
- package/dist/commits.js.map +1 -0
- package/dist/config.d.ts +65 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +189 -0
- package/dist/config.js.map +1 -0
- package/dist/content.d.ts +50 -0
- package/dist/content.d.ts.map +1 -0
- package/dist/content.js +141 -0
- package/dist/content.js.map +1 -0
- package/dist/discover.d.ts +55 -0
- package/dist/discover.d.ts.map +1 -0
- package/dist/discover.js +116 -0
- package/dist/discover.js.map +1 -0
- package/dist/extract.d.ts +47 -0
- package/dist/extract.d.ts.map +1 -0
- package/dist/extract.js +127 -0
- package/dist/extract.js.map +1 -0
- package/dist/index.d.ts +24 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +23 -0
- package/dist/index.js.map +1 -0
- package/dist/paths.d.ts +31 -0
- package/dist/paths.d.ts.map +1 -0
- package/dist/paths.js +47 -0
- package/dist/paths.js.map +1 -0
- package/dist/render/index.d.ts +21 -0
- package/dist/render/index.d.ts.map +1 -0
- package/dist/render/index.js +68 -0
- package/dist/render/index.js.map +1 -0
- package/dist/render/transcript.d.ts +31 -0
- package/dist/render/transcript.d.ts.map +1 -0
- package/dist/render/transcript.js +54 -0
- package/dist/render/transcript.js.map +1 -0
- package/dist/session.d.ts +30 -0
- package/dist/session.d.ts.map +1 -0
- package/dist/session.js +99 -0
- package/dist/session.js.map +1 -0
- package/dist/titles.d.ts +26 -0
- package/dist/titles.d.ts.map +1 -0
- package/dist/titles.js +51 -0
- package/dist/titles.js.map +1 -0
- package/dist/turns.d.ts +62 -0
- package/dist/turns.d.ts.map +1 -0
- package/dist/turns.js +108 -0
- package/dist/turns.js.map +1 -0
- package/dist/types.d.ts +95 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +14 -0
- package/dist/types.js.map +1 -0
- package/dist/write.d.ts +61 -0
- package/dist/write.d.ts.map +1 -0
- package/dist/write.js +126 -0
- package/dist/write.js.map +1 -0
- 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"}
|
package/dist/cli/args.js
ADDED
|
@@ -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"}
|
package/dist/cli/init.js
ADDED
|
@@ -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"}
|