@ankurhalder/codebase-snapshot 3.0.0 → 4.0.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/README.md +161 -310
- package/dist/bin.js +1939 -570
- package/dist/{chunk-5B4UVQLR.js → chunk-FM4OOQPF.js} +1558 -390
- package/dist/cli.cjs +1907 -537
- package/dist/cli.d.cts +3 -1
- package/dist/cli.d.ts +3 -1
- package/dist/cli.js +265 -64
- package/dist/index.cjs +1557 -387
- package/dist/index.d.cts +22 -28
- package/dist/index.d.ts +22 -28
- package/dist/index.js +1 -1
- package/dist/{types-CJqkePM4.d.cts → types-BdpT_4b8.d.cts} +37 -4
- package/dist/{types-CJqkePM4.d.ts → types-BdpT_4b8.d.ts} +37 -4
- package/docs/agent.md +77 -37
- package/docs/cli.md +315 -0
- package/docs/configuration.md +254 -226
- package/docs/install.md +114 -86
- package/docs/output.md +213 -0
- package/docs/troubleshooting.md +277 -0
- package/package.json +7 -4
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
# Troubleshooting
|
|
2
|
+
|
|
3
|
+
Every message below is the real text the tool prints. Find your symptom, then the cause and
|
|
4
|
+
the fix.
|
|
5
|
+
|
|
6
|
+
## The command does nothing
|
|
7
|
+
|
|
8
|
+
**Symptom** — `npx @ankurhalder/codebase-snapshot generate` exits `0` and prints nothing. No
|
|
9
|
+
`snapshot/` directory appears.
|
|
10
|
+
|
|
11
|
+
**Cause** — a **stale global install** is shadowing `npx`. When a global copy exists, npm
|
|
12
|
+
runs it instead of the published package, and a leftover `npm link` (pointing at a
|
|
13
|
+
development checkout) resolves to a binary that is not there.
|
|
14
|
+
|
|
15
|
+
**Fix**
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm ls -g --depth=0 | grep codebase-snapshot
|
|
19
|
+
npm rm -g @ankurhalder/codebase-snapshot
|
|
20
|
+
npx @ankurhalder/codebase-snapshot generate
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
If nothing is installed globally, clear the npx cache (`npm cache clean --force`) and retry.
|
|
24
|
+
This is a local environment problem, not a package problem: on a machine without a global
|
|
25
|
+
copy the same command works.
|
|
26
|
+
|
|
27
|
+
## `command not found`
|
|
28
|
+
|
|
29
|
+
**Cause** — when the package is installed as a project dependency, its binary lives in
|
|
30
|
+
`node_modules/.bin` and is only on `PATH` inside a client runner or a package script.
|
|
31
|
+
|
|
32
|
+
**Fix** — use `npx codebase-snapshot`, `pnpm exec codebase-snapshot`,
|
|
33
|
+
`yarn codebase-snapshot`, `bun run codebase-snapshot`, or `./node_modules/.bin/codebase-snapshot`
|
|
34
|
+
in scripts.
|
|
35
|
+
|
|
36
|
+
## Exit code 2 — the command itself was wrong
|
|
37
|
+
|
|
38
|
+
Exit `2` always means "retrying this unchanged will fail the same way". The message names the
|
|
39
|
+
problem, and for an option the command does not take it also names the commands that do:
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
❌ --watch does not apply to `report` and was not applied. It is accepted by: `generate`.
|
|
43
|
+
❌ --cwd does not apply to `describe` and was not applied. It is accepted by: `generate`, `validate`, `report`, `init`, `explain`, `skill`.
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Nothing is silently ignored — that is the point of the message. The per-option `Applies to`
|
|
47
|
+
column is in the [CLI reference](cli.md#options).
|
|
48
|
+
|
|
49
|
+
| Message | Fix |
|
|
50
|
+
| :--- | :--- |
|
|
51
|
+
| `Unknown command "frobnicate". Expected one of: …` | Use one of the commands in the [CLI reference](cli.md). |
|
|
52
|
+
| `--preset does not apply to \`generate\` and was not applied. It is accepted by: \`init\`. To scope a run, set include/excludePatterns/preset in snapshot.config.ts (or run \`codebase-snapshot init\` to generate one).` | `--preset`, `--include`, `--exclude`, `--yes`, `--minimal` and `--force` configure `init`, which writes them into the config. Set them at generation time in `snapshot.config.ts` instead. |
|
|
53
|
+
| `--install does not apply to \`generate\` and was not applied. It is accepted by: \`skill\`.` | `--install` and `--target` configure `skill` only. |
|
|
54
|
+
| `--cwd directory does not exist: …` / `--cwd is not a directory: …` | Point `--cwd` at an existing repository directory. |
|
|
55
|
+
| `--out-dir requires a value (received an empty string).` | An unset shell variable expanded to nothing. Quote it or drop the flag. Every string option rejects `""` rather than silently using the default. |
|
|
56
|
+
| `--max-part-bytes received a value that looks like another flag (for example a negative number). Use the "--option=value" form, and note that sizes must be positive.` | A negative number reads as a flag. Use `--max-part-bytes=-5`, and note that sizes must be positive. |
|
|
57
|
+
| `Unknown preset "nope". Expected one of: …` | The message lists all 25 valid names. |
|
|
58
|
+
| `--target must be one of: claude, agents, cursor, all (received "bogus").` | Fix the value. |
|
|
59
|
+
| `diff expects exactly two arguments …` / `explain expects exactly one path.` | Fix the arity. |
|
|
60
|
+
|
|
61
|
+
## Exit code 1 — the state was wrong
|
|
62
|
+
|
|
63
|
+
### `Refusing to replace outDir …`
|
|
64
|
+
|
|
65
|
+
```
|
|
66
|
+
❌ Failed to generate snapshot: Refusing to replace outDir /repo/src: it holds no .codebase-snapshot marker (found app.ts). Remove the directory yourself, or point outDir at a new or empty directory.
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
**Cause** — the output directory contains files this tool did not write, and it cannot prove
|
|
70
|
+
it wrote them. This guard exists because a mistyped `outDir` used to replace the directory:
|
|
71
|
+
`outDir: "src"` deleted source code while reporting success.
|
|
72
|
+
|
|
73
|
+
Ownership is proved by a `.codebase-snapshot` marker that parses as ours — a JSON object
|
|
74
|
+
naming this generator, carrying a schema version this build understands, a per-snapshot `id`
|
|
75
|
+
and the digest of the manifest it shipped. A file with the right name is not enough:
|
|
76
|
+
|
|
77
|
+
| The directory | What the tool says |
|
|
78
|
+
| :--- | :--- |
|
|
79
|
+
| has files, no marker | `it holds no .codebase-snapshot marker (found app.ts)` |
|
|
80
|
+
| has a zero-byte marker | `its .codebase-snapshot marker is empty (found .codebase-snapshot, app.ts)` |
|
|
81
|
+
| has a marker that is not JSON | `its .codebase-snapshot marker is not valid JSON (found .codebase-snapshot, app.ts)` |
|
|
82
|
+
| was written by 3.0.0 | `its .codebase-snapshot marker carries no snapshot id (found .codebase-snapshot, manifest.json)` |
|
|
83
|
+
| carries our marker but you added files | `it carries this generator's ownership marker, but these entries are not part of the snapshot it recorded: custom.txt. Remove them yourself, or point outDir at a new or empty directory.` |
|
|
84
|
+
|
|
85
|
+
**Fix** — point `--out-dir` somewhere new, or delete the directory yourself. Do not delete
|
|
86
|
+
your source. Accepted without complaint: a missing directory, an empty directory, one
|
|
87
|
+
holding only `.gitkeep`/`.gitignore`/`.DS_Store`, and a complete snapshot this build wrote.
|
|
88
|
+
|
|
89
|
+
A snapshot written by 3.0.0 or earlier is **not** upgraded in place: its marker has three keys
|
|
90
|
+
and no `id`, so the new build cannot prove it wrote the directory and refuses. Delete the old
|
|
91
|
+
snapshot directory and generate again.
|
|
92
|
+
|
|
93
|
+
### `Refusing to write into outDir …: it exists but is not a directory.`
|
|
94
|
+
|
|
95
|
+
```
|
|
96
|
+
❌ Failed to generate snapshot: Refusing to write into outDir /repo/notes.txt: it exists but is not a directory.
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
A regular file has the same name as the output directory. Rename or remove it.
|
|
100
|
+
|
|
101
|
+
### `The config file could not be read`
|
|
102
|
+
|
|
103
|
+
```
|
|
104
|
+
⚠ Config: Could not parse /repo/snapshot.config.json: Expected property name or '}' …
|
|
105
|
+
❌ The config file could not be read. Fix it, or delete it to use the defaults.
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
**Cause** — a config file exists but does not parse, or a `.ts` config cannot be loaded. This
|
|
109
|
+
is fatal on purpose: skipping a broken config would generate a snapshot with none of your
|
|
110
|
+
settings and still report success.
|
|
111
|
+
|
|
112
|
+
**Fix** — fix the syntax, or delete the file to run on defaults. Check that the config is
|
|
113
|
+
loadable on your Node version: a `.ts` config needs Node ≥ 22.6 **and** an ES-module project.
|
|
114
|
+
`codebase-snapshot init` picks the right filename for the project automatically.
|
|
115
|
+
|
|
116
|
+
### `Refusing to generate: …`
|
|
117
|
+
|
|
118
|
+
```
|
|
119
|
+
❌ Failed to generate snapshot: Refusing to generate: outDir is the working directory or one of its ancestors. outDir=/repo tmpDir=/repo/snapshot.tmp cwd=/repo
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
The output paths are unsafe: `outDir` or `tmpDir` is the working directory, an ancestor, the
|
|
123
|
+
filesystem root, or they contain one another. The message prints the resolved paths so you
|
|
124
|
+
can see why. Use a subdirectory.
|
|
125
|
+
|
|
126
|
+
### Budget errors
|
|
127
|
+
|
|
128
|
+
A budget set in a **config file** exits `1`, and names the setting as you wrote it:
|
|
129
|
+
|
|
130
|
+
| Message | Fix |
|
|
131
|
+
| :--- | :--- |
|
|
132
|
+
| `maxPartBytes must be a positive byte count (received 0).` | Zero and negative values are errors, not "use the default". |
|
|
133
|
+
| `maxPartBytes must be at least 4096 bytes (received 1000).` | Raise it to 4096 or more (`"120k"` is 122880). |
|
|
134
|
+
| `maxPartBytes must be a byte count such as 120000, "120k" or "1.5mb" (received "abc").` | The value is not a number or a supported size string. |
|
|
135
|
+
|
|
136
|
+
The same mistake on the **command line** is a usage error, exits `2`, names the flag, and is
|
|
137
|
+
followed by the usage text:
|
|
138
|
+
|
|
139
|
+
| Message | Fix |
|
|
140
|
+
| :--- | :--- |
|
|
141
|
+
| `--max-part-bytes must be at least 4096, received "1000".` | Raise it to 4096 or more. `--max-part-bytes 0` and `--max-part-bytes 1000` both produce this form. |
|
|
142
|
+
| `--max-part-bytes expects a byte count such as 120000 or "120k", received "abc".` | The value is not a number or a supported size string. `--max-part-bytes=-5` produces this form too. |
|
|
143
|
+
|
|
144
|
+
`--large-file-bytes` and `--max-monolith-bytes` share the second message, with their own flag
|
|
145
|
+
name, and their minimum is 1 rather than 4096:
|
|
146
|
+
`--large-file-bytes must be at least 1, received "0".`
|
|
147
|
+
|
|
148
|
+
### `Cannot write the snapshot: permission denied under …`
|
|
149
|
+
|
|
150
|
+
The output directory is not writable (or a parent is not readable). The previous snapshot is
|
|
151
|
+
left intact. Fix the permissions, or choose another `--out-dir`.
|
|
152
|
+
|
|
153
|
+
### `Snapshot validation failed` (from `validate`)
|
|
154
|
+
|
|
155
|
+
Exit `1` with one line per class of drift:
|
|
156
|
+
|
|
157
|
+
| Line | Meaning |
|
|
158
|
+
| :--- | :--- |
|
|
159
|
+
| `- modified: path` | The file changed since the snapshot. |
|
|
160
|
+
| `- deleted: path` | The file is in the snapshot but no longer on disk. |
|
|
161
|
+
| `- new file: path` | The file exists on disk and is not in the snapshot. |
|
|
162
|
+
| `- part: part-001.md (missing from snapshot/parts)` | The part file was deleted or renamed. |
|
|
163
|
+
| `- part: … (size mismatch …)` | The part was edited by hand. |
|
|
164
|
+
| `- config: …` | A setting differs from the one recorded in the manifest. |
|
|
165
|
+
| `- counts: …` | The manifest's own bookkeeping disagrees with its contents. |
|
|
166
|
+
|
|
167
|
+
**Fix** — re-run `generate`. If it persists, the snapshot directory is being modified by
|
|
168
|
+
something else.
|
|
169
|
+
|
|
170
|
+
### `report` exits 1
|
|
171
|
+
|
|
172
|
+
- `Manifest not found at … Run generate first.` — nothing has been generated yet.
|
|
173
|
+
- `… is not a snapshot manifest: missing \`counts\`` — the file parsed as JSON but is not a
|
|
174
|
+
manifest this tool wrote. Wrong `--out-dir`, or a foreign file named `manifest.json`.
|
|
175
|
+
|
|
176
|
+
### `diff` exits 1
|
|
177
|
+
|
|
178
|
+
- `No snapshot found at X: the path does not exist.`
|
|
179
|
+
- `Could not read a manifest at X.`
|
|
180
|
+
- `… is not a snapshot manifest (no "counts" object).`
|
|
181
|
+
|
|
182
|
+
Point it at a snapshot directory or a `manifest.json` written by this tool.
|
|
183
|
+
|
|
184
|
+
## A file is missing from the snapshot
|
|
185
|
+
|
|
186
|
+
Run `explain` on it — it names the exact reason and the rule responsible:
|
|
187
|
+
|
|
188
|
+
```bash
|
|
189
|
+
npx codebase-snapshot explain src/generated/schema.ts
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
`manifest.json` records the same for every file in `skipped[]`:
|
|
193
|
+
|
|
194
|
+
| `reason` | Meaning | Fix |
|
|
195
|
+
| :--- | :--- | :--- |
|
|
196
|
+
| `sensitive-file` | `.env`, `*.pem`, `.npmrc`, `.ssh/`, `.tfstate`, … | `--include-sensitive-files` if you really want it. |
|
|
197
|
+
| `sensitive-path` | The path itself matched a secret rule, so the file is skipped and its path is masked in every artifact. | Rename the file; a path that looks like a key is treated as one. |
|
|
198
|
+
| `binary` | Not text. | Nothing to do. |
|
|
199
|
+
| `default-ignore` | A built-in rule, the preset's ecosystem ignores (`node_modules`, `__pycache__`, `target`, `vendor`, …), or the output directory. | A preset's ignores are not configurable; a custom `excludePatterns` can only remove more. |
|
|
200
|
+
| `excluded` | Your own `excludePatterns`, or a path outside a non-empty `include` allow-list. | Remove the pattern, or widen `include`. |
|
|
201
|
+
| `symlink` | Links are not followed (a directory link names its target in `detail`). | Snapshot the target. |
|
|
202
|
+
| `outside-root` | A link whose target resolves outside the scanned root. | Keep the target inside the repository, or snapshot it directly. |
|
|
203
|
+
| `gitignore` | A `.gitignore` excluded it, in a scan that is not reading git's index. | Remove the entry, or add the path to `include`. |
|
|
204
|
+
| `read-error` | Unreadable file. | Check permissions. |
|
|
205
|
+
| `not-file` | A directory, socket, FIFO. | Expected. |
|
|
206
|
+
|
|
207
|
+
Inside a git repository the candidate list comes from git, which applies `.gitignore` before
|
|
208
|
+
the scanner runs; those ignored paths are listed separately and recorded too, so a `.gitignore`d
|
|
209
|
+
file or directory appears here with reason `gitignore` in either mode.
|
|
210
|
+
|
|
211
|
+
`explain` can report two more, which never appear in `skipped[]` because they are about the
|
|
212
|
+
path rather than about a candidate file:
|
|
213
|
+
|
|
214
|
+
| `reason` | Meaning | Fix |
|
|
215
|
+
| :--- | :--- | :--- |
|
|
216
|
+
| `missing` | `no such file or directory, relative to the configured cwd` — nothing is at that path. | Check the path and `--cwd`. |
|
|
217
|
+
| `not-discovered` | `exists but is not tracked or is otherwise not a candidate` — the file is there but the scanner never offered it, because it sits inside a directory the traversal skips, such as `node_modules`. | Copy it into the repository if you really need it in the snapshot; `include` cannot rescue a skipped directory. |
|
|
218
|
+
|
|
219
|
+
Also check `include`: if it is non-empty it acts as an allow-list, and everything else is
|
|
220
|
+
excluded.
|
|
221
|
+
|
|
222
|
+
## The snapshot is too big
|
|
223
|
+
|
|
224
|
+
- Lower the budget: `--max-part-bytes 120k`.
|
|
225
|
+
- Exclude whole trees: `excludePatterns: ["vendor/**", "**/*.min.js"]` in the config.
|
|
226
|
+
- Per-layer budgets: `budgets: { default: "120k", byLayer: { docs: 40000 } }`.
|
|
227
|
+
- Skip artifacts you do not read: `--skip-artifacts navigation,projectTree,audit`.
|
|
228
|
+
- Large files are already previewed rather than inlined; tune with `--large-file-bytes`.
|
|
229
|
+
|
|
230
|
+
## Warnings that are working as intended
|
|
231
|
+
|
|
232
|
+
These come from `generate`. They are recorded in `manifest.warnings` and repeated on stderr
|
|
233
|
+
under a `- Warnings: N` line in the summary, and none of them stops a run:
|
|
234
|
+
|
|
235
|
+
- `manifest.json is disabled: \`validate\` and \`report\` cannot inspect this snapshot.` — you
|
|
236
|
+
used `--skip-artifacts manifest`.
|
|
237
|
+
- `parts are disabled but navigation.md is enabled: its links point at part files that were not written.`
|
|
238
|
+
- `every artifact is disabled: only the .codebase-snapshot ownership marker will be written.`
|
|
239
|
+
- A `hooks.afterGenerate` error is downgraded to a warning: the snapshot it was called for is
|
|
240
|
+
already written and is not lost.
|
|
241
|
+
|
|
242
|
+
`validate` produces its own warnings, printed with a `⚠ ` prefix and never written to the
|
|
243
|
+
manifest, because they describe the state of the repository rather than the snapshot:
|
|
244
|
+
|
|
245
|
+
- `⚠ Working tree has uncommitted changes.`
|
|
246
|
+
- `⚠ Snapshot was generated on branch "zeta" but the configured branch is "main".` — the
|
|
247
|
+
branch moved since the snapshot was written.
|
|
248
|
+
|
|
249
|
+
## Detached HEAD
|
|
250
|
+
|
|
251
|
+
On a detached HEAD (normal in CI) `manifest.git.branch` records the configured branch —
|
|
252
|
+
`main` by default — because a detached HEAD cannot name one. Set `branch` in the config if
|
|
253
|
+
your CI convention differs. This is not a warning condition.
|
|
254
|
+
|
|
255
|
+
## Not a git repository
|
|
256
|
+
|
|
257
|
+
Outside a repository the tool does not fail; it records what it can:
|
|
258
|
+
|
|
259
|
+
```json
|
|
260
|
+
{ "branch": "main", "commit": "unknown", "isDirty": false }
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
`branch` is the configured branch, `commit` is `"unknown"`, and `isDirty` is `false` because
|
|
264
|
+
there is no tree to compare — not because the tree is clean. Read `commit` when you need to
|
|
265
|
+
tell "no repository" from "clean repository", and do not treat `isDirty: false` alone as
|
|
266
|
+
evidence that the snapshot was taken from committed state.
|
|
267
|
+
|
|
268
|
+
## Still stuck
|
|
269
|
+
|
|
270
|
+
```bash
|
|
271
|
+
npx @ankurhalder/codebase-snapshot describe --format json > contract.json
|
|
272
|
+
npx @ankurhalder/codebase-snapshot generate --dry-run --format json > dry-run.json
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
The first is the machine-readable contract, including a troubleshooting table. The second
|
|
276
|
+
computes a full snapshot without writing anything, so you can inspect
|
|
277
|
+
`config`, `counts`, `skipped` and `warnings` before committing to a run.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ankurhalder/codebase-snapshot",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.0",
|
|
4
4
|
"description": "Production-grade LLM codebase snapshot generator, auditor, and AST partitioner",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"codebase",
|
|
@@ -32,7 +32,8 @@
|
|
|
32
32
|
"types": "./dist/index.d.ts",
|
|
33
33
|
"sideEffects": false,
|
|
34
34
|
"bin": {
|
|
35
|
-
"codebase-snapshot": "./dist/bin.js"
|
|
35
|
+
"codebase-snapshot": "./dist/bin.js",
|
|
36
|
+
"snap": "./dist/bin.js"
|
|
36
37
|
},
|
|
37
38
|
"exports": {
|
|
38
39
|
".": {
|
|
@@ -75,9 +76,11 @@
|
|
|
75
76
|
"pretest": "npm run build",
|
|
76
77
|
"test": "node --test tests/*.test.js",
|
|
77
78
|
"test:coverage": "node --test --experimental-test-coverage tests/*.test.js",
|
|
78
|
-
"prepare": "npm run build",
|
|
79
79
|
"prepublishOnly": "npm run build",
|
|
80
|
-
"publish:create": "npm publish packages/create --access public"
|
|
80
|
+
"publish:create": "npm publish packages/create --access public",
|
|
81
|
+
"prepack": "npm run build",
|
|
82
|
+
"pack-check": "node scripts/pack-check.mjs",
|
|
83
|
+
"verify": "npm run check && npm run pack-check"
|
|
81
84
|
},
|
|
82
85
|
"dependencies": {
|
|
83
86
|
"typescript": "^5.0.0"
|