whatileaked 0.5.1 → 0.5.3

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 (3) hide show
  1. package/README.md +6 -2
  2. package/dist/cli.js +24 -7
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -114,7 +114,9 @@ fingerprint — so it is the part you can paste or screenshot anywhere:
114
114
  whatileaked: 3 credentials sent to a model provider, across 561 transcripts.
115
115
  ```
116
116
 
117
- A clean scan ends the same way, with `no credentials`.
117
+ A clean scan ends the same way, with `no credentials`. If some of it could not
118
+ be scanned, the line says how much, still in counts only — `(7 messages and 1
119
+ file not scanned)` — so a pasted partial scan never reads as a clean one.
118
120
 
119
121
  ---
120
122
 
@@ -206,7 +208,7 @@ npx whatileaked scan || echo "found something"
206
208
  | Agent | Folder |
207
209
  | --- | --- |
208
210
  | Claude Code | `~/.claude/projects/` · `~/.claude/history.jsonl` · `~/.claude/paste-cache/` · `~/.claude/CLAUDE.md` |
209
- | Codex | `~/.codex/sessions/` · `~/.codex/archived_sessions/` · `~/.codex/history.jsonl` · `~/.codex/AGENTS.md` |
211
+ | Codex | `~/.codex/sessions/` · `~/.codex/archived_sessions/` · `~/.codex/history.jsonl` · `~/.codex/AGENTS.md` · `~/.codex/AGENTS.override.md` |
210
212
  | Cursor | `~/.cursor/projects/*/agent-transcripts/` |
211
213
  | opencode | `~/.local/share/opencode/opencode.db` |
212
214
 
@@ -220,6 +222,8 @@ opencode, and rotate.
220
222
  Cursor keeps its older Ask-mode chats in SQLite as well, and those are not
221
223
  scanned yet. Agent transcripts are covered; Ask history is not.
222
224
 
225
+ Claude Code transcripts it set aside (`*.jsonl.superseded-*`) are scanned too.
226
+
223
227
  Transcripts record credentials that were already sent. So does prompt history,
224
228
  which keeps every prompt you typed and every long paste after the session itself
225
229
  has been cleaned up. Instruction and memory files are worse: they are read again
package/dist/cli.js CHANGED
@@ -220,13 +220,19 @@ var TerminalReporter = class {
220
220
  * and stays that way. It is last so a screenshot can crop to it, unstyled so
221
221
  * a copy carries nothing but the words, and it repeats the headline's
222
222
  * transmitted-only count for the same reason the headline keeps memory files
223
- * out of it.
223
+ * out of it. A partial scan says so here in counts, because this is the line
224
+ * that gets cropped to: without it a pasted "no credentials" overclaims.
224
225
  */
225
226
  #share(sent, stats) {
226
227
  const credentials = sent === 0 ? "no credentials" : plural(sent, "credential");
228
+ const missed = [
229
+ ...stats.unscannable > 0 ? [plural(stats.unscannable, "message")] : [],
230
+ ...stats.unread.length > 0 ? [plural(stats.unread.length, "file")] : []
231
+ ];
232
+ const partial = missed.length === 0 ? "" : ` (${missed.join(" and ")} not scanned)`;
227
233
  this.#write("");
228
234
  this.#write(
229
- `whatileaked: ${credentials} sent to a model provider, across ${plural(stats.transcripts, "transcript")}.`
235
+ `whatileaked: ${credentials} sent to a model provider, across ${plural(stats.transcripts, "transcript")}${partial}.`
230
236
  );
231
237
  }
232
238
  };
@@ -2431,7 +2437,16 @@ var FileExtension = {
2431
2437
  database: ".db"
2432
2438
  };
2433
2439
  function isJsonl(path) {
2434
- return path.endsWith(FileExtension.jsonl);
2440
+ return path.endsWith(FileExtension.jsonl) || supersededJsonl.test(path);
2441
+ }
2442
+ var supersededJsonl = /\.jsonl\.superseded-[^/\\]+$/;
2443
+ async function listJsonl(dir) {
2444
+ try {
2445
+ const entries = await readdir(dir, { withFileTypes: true });
2446
+ return entries.filter((entry) => entry.isFile() && isJsonl(entry.name)).map((entry) => entry.name);
2447
+ } catch {
2448
+ return [];
2449
+ }
2435
2450
  }
2436
2451
  async function listFiles(dir, extension) {
2437
2452
  try {
@@ -2638,7 +2653,7 @@ var ClaudeCodeSource = class {
2638
2653
  const dir = join2(root, slug);
2639
2654
  let project = slug;
2640
2655
  for (const nested of await walkDirectories(dir)) {
2641
- for (const file of await listFiles(nested, FileExtension.jsonl)) {
2656
+ for (const file of await listJsonl(nested)) {
2642
2657
  const path = join2(nested, file);
2643
2658
  const cwd = await firstCwd(path);
2644
2659
  if (cwd !== null) project = basename(cwd);
@@ -2682,9 +2697,11 @@ var CodexSource = class {
2682
2697
  this.#home = home2;
2683
2698
  }
2684
2699
  async *discover() {
2685
- const instructions = await resolveFile(join3(this.#home, ".codex", "AGENTS.md"));
2686
- if (instructions !== null) {
2687
- yield { source: this.name, kind: FileKind.memory, path: instructions, project: this.name };
2700
+ for (const name of ["AGENTS.override.md", "AGENTS.md"]) {
2701
+ const instructions = await resolveFile(join3(this.#home, ".codex", name));
2702
+ if (instructions !== null) {
2703
+ yield { source: this.name, kind: FileKind.memory, path: instructions, project: this.name };
2704
+ }
2688
2705
  }
2689
2706
  const history = await resolveFile(join3(this.#home, ".codex", "history.jsonl"));
2690
2707
  if (history !== null) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "whatileaked",
3
- "version": "0.5.1",
3
+ "version": "0.5.3",
4
4
  "description": "Scan your local Claude Code, Codex, Cursor and opencode transcripts for credentials you already sent to a model provider.",
5
5
  "type": "module",
6
6
  "imports": {