@liuyoumi/codex-history 0.1.2 → 0.1.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.
package/CHANGELOG.md CHANGED
@@ -1,12 +1,24 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.3 - 2026-05-29
4
+
5
+ ### Changed
6
+
7
+ - Remove purge backup creation and document `purge` as a permanent local deletion flow.
8
+ - Report the CLI version from `package.json` instead of a stale hard-coded value.
9
+
10
+ ### Documentation
11
+
12
+ - Refresh the README cover image to show only the terminal window.
13
+ - Add agent workflow guidance for future implementation work.
14
+ - Clarify the boundary between `AGENTS.md` and `docs/agent-workflow.md`.
15
+
3
16
  ## 0.1.2 - 2026-05-28
4
17
 
5
18
  ### Documentation
6
19
 
7
20
  - Use Chinese as the default README language.
8
21
  - Add an English README translation.
9
- - Refresh the README cover image to focus on a single guarded `purge` command flow.
10
22
  - Add README badges and clearer macOS, Windows, and Linux support notes.
11
23
 
12
24
  ## 0.1.1 - 2026-05-28
@@ -28,7 +40,7 @@ Initial release candidate.
28
40
  - `purge <id>` execution by full id or unique short id prefix.
29
41
  - Interactive purge confirmation by typing the standard short id.
30
42
  - `purge <id> --force` for non-interactive execution.
31
- - Guarded purge execution with mandatory backups.
43
+ - Guarded purge execution with explicit confirmation.
32
44
  - SQLite cleanup for supported Codex stores.
33
45
  - JSON and JSONL state cleanup for supported Codex files.
34
46
  - Rollout jsonl and shell snapshot deletion.
package/README.en.md CHANGED
@@ -4,7 +4,7 @@
4
4
  <img alt="npm" src="https://img.shields.io/npm/v/@liuyoumi/codex-history?style=flat-square&color=cb9b27" />
5
5
  <img alt="platform" src="https://img.shields.io/badge/platform-macOS%20%7C%20Windows%20%7C%20Linux-2ea043?style=flat-square" />
6
6
  <img alt="local only" src="https://img.shields.io/badge/local%20data-only-6e7681?style=flat-square" />
7
- <img alt="backup" src="https://img.shields.io/badge/backup-before%20purge-0969da?style=flat-square" />
7
+ <img alt="confirm" src="https://img.shields.io/badge/confirm-before%20purge-0969da?style=flat-square" />
8
8
  <img alt="license" src="https://img.shields.io/npm/l/@liuyoumi/codex-history?style=flat-square" />
9
9
  </p>
10
10
 
@@ -34,7 +34,7 @@ npx @liuyoumi/codex-history doctor
34
34
 
35
35
  ## Supported Platforms
36
36
 
37
- `codex-history` has been checked on macOS, Windows, and Linux for install, `doctor`, `list` / `--grep`, and guarded `purge` workflows with confirmation and backups.
37
+ `codex-history` has been checked on macOS, Windows, and Linux for install, `doctor`, `list` / `--grep`, and guarded `purge` workflows with confirmation.
38
38
 
39
39
  | Platform | Status |
40
40
  | --- | --- |
@@ -63,7 +63,7 @@ id: 019e6885-b5ae-7ae0-a50d-ce5f75b0ac08
63
63
  cwd: /Users/me/Projects/example
64
64
  updated: 2026-05-28T03:16:01.959Z
65
65
 
66
- A backup will be created before deletion.
66
+ This cannot be undone.
67
67
  Type 019e6885 to confirm:
68
68
  ```
69
69
 
@@ -139,7 +139,7 @@ For scripts or non-interactive shells, use `--force`:
139
139
  codex-history purge 019e6885 --force
140
140
  ```
141
141
 
142
- `--force` skips only the interactive short-id confirmation. It still keeps schema validation, mandatory backup, active-thread protection, and post-purge verification.
142
+ `--force` skips only the interactive short-id confirmation. It still keeps schema validation, active-thread protection, and post-purge verification.
143
143
 
144
144
  ## Options
145
145
 
@@ -160,7 +160,6 @@ Before deleting, `codex-history`:
160
160
  - validates the supported Codex data model
161
161
  - resolves the target to exactly one conversation
162
162
  - refuses the currently active thread when detectable
163
- - creates a mandatory backup under `~/.codex-history/backups`
164
163
  - removes known references from supported local Codex stores
165
164
  - verifies supported stores after mutation
166
165
 
@@ -174,13 +173,9 @@ If Codex Desktop is already showing the conversation you purge, quit or restart
174
173
 
175
174
  No. It only modifies supported local files on your machine.
176
175
 
177
- ### Where are backups stored?
178
-
179
- Backups are written under `~/.codex-history/backups`.
180
-
181
176
  ### Can I recover a purged conversation?
182
177
 
183
- The tool creates a backup before deletion, but v0.1 does not include an automatic restore command. Treat `purge` as destructive.
178
+ Not with this tool. Treat `purge` as destructive.
184
179
 
185
180
  ### Do I need to restart Codex after purging?
186
181
 
package/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
  <img alt="npm" src="https://img.shields.io/npm/v/@liuyoumi/codex-history?style=flat-square&color=cb9b27" />
5
5
  <img alt="platform" src="https://img.shields.io/badge/platform-macOS%20%7C%20Windows%20%7C%20Linux-2ea043?style=flat-square" />
6
6
  <img alt="local only" src="https://img.shields.io/badge/local%20data-only-6e7681?style=flat-square" />
7
- <img alt="backup" src="https://img.shields.io/badge/backup-before%20purge-0969da?style=flat-square" />
7
+ <img alt="confirm" src="https://img.shields.io/badge/confirm-before%20purge-0969da?style=flat-square" />
8
8
  <img alt="license" src="https://img.shields.io/npm/l/@liuyoumi/codex-history?style=flat-square" />
9
9
  </p>
10
10
 
@@ -34,7 +34,7 @@ npx @liuyoumi/codex-history doctor
34
34
 
35
35
  ## 支持平台
36
36
 
37
- `codex-history` 已在 macOS、Windows、Linux 上完成基础流程验证,包括安装、`doctor`、`list` / `--grep`,以及带确认和备份保护的 `purge`。
37
+ `codex-history` 已在 macOS、Windows、Linux 上完成基础流程验证,包括安装、`doctor`、`list` / `--grep`,以及带确认保护的 `purge`。
38
38
 
39
39
  | 平台 | 状态 |
40
40
  | --- | --- |
@@ -63,7 +63,7 @@ id: 019e6885-b5ae-7ae0-a50d-ce5f75b0ac08
63
63
  cwd: /Users/me/Projects/example
64
64
  updated: 2026-05-28T03:16:01.959Z
65
65
 
66
- A backup will be created before deletion.
66
+ This cannot be undone.
67
67
  Type 019e6885 to confirm:
68
68
  ```
69
69
 
@@ -139,7 +139,7 @@ codex-history purge 019e6885
139
139
  codex-history purge 019e6885 --force
140
140
  ```
141
141
 
142
- `--force` 只跳过交互式短 id 确认,不会跳过数据结构校验、强制备份、active thread 保护和删除后的验证。
142
+ `--force` 只跳过交互式短 id 确认,不会跳过数据结构校验、active thread 保护和删除后的验证。
143
143
 
144
144
  ## 选项
145
145
 
@@ -160,7 +160,6 @@ codex-history --json purge 019e6885 --force
160
160
  - 校验当前 Codex 本地数据结构是否受支持
161
161
  - 将目标解析到唯一一条对话
162
162
  - 在可检测时拒绝删除当前 active thread
163
- - 在 `~/.codex-history/backups` 下创建强制备份
164
163
  - 从受支持的本地 Codex 数据中移除已知引用
165
164
  - 删除后扫描受支持的数据存储,确认目标引用已经移除
166
165
 
@@ -174,13 +173,9 @@ codex-history --json purge 019e6885 --force
174
173
 
175
174
  不会。它只修改你机器上受支持的本地文件。
176
175
 
177
- ### 备份在哪里?
178
-
179
- 备份会写入 `~/.codex-history/backups`。
180
-
181
176
  ### 删除后还能恢复吗?
182
177
 
183
- 工具会在删除前创建备份,但 v0.1 还没有自动恢复命令。请把 `purge` 当作破坏性操作对待。
178
+ 不能通过这个工具恢复。请把 `purge` 当作破坏性操作对待。
184
179
 
185
180
  ### 删除后需要重启 Codex 吗?
186
181
 
package/dist/cli.js CHANGED
@@ -3,11 +3,11 @@
3
3
  // src/cli.ts
4
4
  import { Command } from "commander";
5
5
  import { spawnSync } from "child_process";
6
+ import { readFileSync as readFileSync5 } from "fs";
6
7
  import { createInterface } from "readline/promises";
7
8
 
8
9
  // src/core/schema.ts
9
- import { mkdirSync, readFileSync } from "fs";
10
- import { dirname } from "path";
10
+ import { readFileSync } from "fs";
11
11
 
12
12
  // src/core/paths.ts
13
13
  import { existsSync } from "fs";
@@ -22,13 +22,10 @@ function expandHome(input) {
22
22
  }
23
23
  return input;
24
24
  }
25
- function resolvePaths(codexHomeInput, toolHomeInput) {
25
+ function resolvePaths(codexHomeInput) {
26
26
  const codexHome = path.resolve(expandHome(codexHomeInput ?? "~/.codex"));
27
- const toolHome = path.resolve(expandHome(toolHomeInput ?? process.env.CODEX_HISTORY_HOME ?? "~/.codex-history"));
28
27
  return {
29
28
  codexHome,
30
- toolHome,
31
- backupHome: path.join(toolHome, "backups"),
32
29
  stateDb: path.join(codexHome, "state_5.sqlite"),
33
30
  logsDb: path.join(codexHome, "logs_2.sqlite"),
34
31
  goalsDb: path.join(codexHome, "goals_1.sqlite"),
@@ -122,18 +119,15 @@ function runDoctor(paths) {
122
119
  checks.push(checkJsonFile(paths.globalState, "global_state"));
123
120
  checks.push(checkJsonFile(paths.globalStateBackup, "global_state_backup"));
124
121
  checks.push(checkJsonlFile(paths.sessionIndex, "session_index"));
125
- checks.push(checkBackupHome(paths.backupHome));
126
122
  return {
127
123
  supported: !checks.some((check) => check.status === "error"),
128
124
  codexHome: paths.codexHome,
129
125
  checks
130
126
  };
131
127
  }
132
- function validateSupportedDataModel(paths, options = {}) {
128
+ function validateSupportedDataModel(paths) {
133
129
  const report = runDoctor(paths);
134
- const errors = report.checks.filter(
135
- (check) => check.status === "error" && (options.requireBackupHome || check.name !== "backup_home")
136
- );
130
+ const errors = report.checks.filter((check) => check.status === "error");
137
131
  if (errors.length > 0) {
138
132
  const details = errors.map((check) => `${check.name}: ${check.detail}`).join("; ");
139
133
  throw new Error(`Unsupported Codex data model: ${details}`);
@@ -255,23 +249,6 @@ function checkJsonlFile(filePath, name) {
255
249
  };
256
250
  }
257
251
  }
258
- function checkBackupHome(backupHome) {
259
- try {
260
- mkdirSync(dirname(backupHome), { recursive: true });
261
- mkdirSync(backupHome, { recursive: true });
262
- return {
263
- name: "backup_home",
264
- status: "ok",
265
- detail: backupHome
266
- };
267
- } catch (error) {
268
- return {
269
- name: "backup_home",
270
- status: "error",
271
- detail: error instanceof Error ? error.message : String(error)
272
- };
273
- }
274
- }
275
252
 
276
253
  // src/commands/doctor.ts
277
254
  function doctorCommand(paths) {
@@ -393,7 +370,7 @@ function listCommand(paths, options = {}) {
393
370
  }
394
371
 
395
372
  // src/core/executor.ts
396
- import { existsSync as existsSync9 } from "fs";
373
+ import { existsSync as existsSync8 } from "fs";
397
374
 
398
375
  // src/safety/active-thread.ts
399
376
  import { existsSync as existsSync4, statSync } from "fs";
@@ -450,71 +427,8 @@ function assertThreadIsNotActive(target) {
450
427
  return checks;
451
428
  }
452
429
 
453
- // src/safety/backup.ts
454
- import { copyFileSync, existsSync as existsSync5, mkdirSync as mkdirSync2, statSync as statSync2, writeFileSync } from "fs";
455
- import path2 from "path";
456
- function createBackup(paths, plan) {
457
- const timestamp = (/* @__PURE__ */ new Date()).toISOString().replaceAll(/[:.]/g, "-");
458
- const backupDir = path2.join(paths.backupHome, `${timestamp}-${plan.target.id}`);
459
- mkdirSync2(backupDir, { recursive: true });
460
- const candidates = /* @__PURE__ */ new Set();
461
- candidates.add(paths.stateDb);
462
- addIfPresent(candidates, `${paths.stateDb}-wal`);
463
- addIfPresent(candidates, `${paths.stateDb}-shm`);
464
- addIfPresent(candidates, paths.logsDb);
465
- addIfPresent(candidates, `${paths.logsDb}-wal`);
466
- addIfPresent(candidates, `${paths.logsDb}-shm`);
467
- addIfPresent(candidates, paths.goalsDb);
468
- addIfPresent(candidates, `${paths.goalsDb}-wal`);
469
- addIfPresent(candidates, `${paths.goalsDb}-shm`);
470
- addIfPresent(candidates, paths.sessionIndex);
471
- addIfPresent(candidates, paths.globalState);
472
- addIfPresent(candidates, paths.globalStateBackup);
473
- addIfPresent(candidates, plan.target.rolloutPath);
474
- for (const store of plan.stores) {
475
- if (store.store === "shell_snapshot") {
476
- addIfPresent(candidates, store.path);
477
- }
478
- }
479
- const entries = [];
480
- for (const originalPath of candidates) {
481
- if (!existsSync5(originalPath)) {
482
- continue;
483
- }
484
- const backupPath = uniqueBackupPath(backupDir, originalPath);
485
- mkdirSync2(path2.dirname(backupPath), { recursive: true });
486
- copyFileSync(originalPath, backupPath);
487
- const stats = statSync2(originalPath);
488
- entries.push({
489
- originalPath,
490
- backupPath,
491
- size: stats.size,
492
- mtimeMs: stats.mtimeMs
493
- });
494
- }
495
- const manifest = {
496
- threadId: plan.target.id,
497
- createdAt: (/* @__PURE__ */ new Date()).toISOString(),
498
- backupDir,
499
- entries
500
- };
501
- writeFileSync(path2.join(backupDir, "manifest.json"), JSON.stringify(manifest, null, 2) + "\n");
502
- return manifest;
503
- }
504
- function addIfPresent(paths, filePath) {
505
- if (existsSync5(filePath)) {
506
- paths.add(filePath);
507
- }
508
- }
509
- function uniqueBackupPath(backupDir, originalPath) {
510
- const parsed = path2.parse(originalPath);
511
- const safeBase = `${parsed.name}${parsed.ext}`.replaceAll(/[^a-zA-Z0-9._-]/g, "_");
512
- const hash = Buffer.from(originalPath).toString("base64url").slice(0, 12);
513
- return path2.join(backupDir, `${hash}-${safeBase}`);
514
- }
515
-
516
430
  // src/safety/verify.ts
517
- import { existsSync as existsSync6, readFileSync as readFileSync3 } from "fs";
431
+ import { existsSync as existsSync5, readFileSync as readFileSync3 } from "fs";
518
432
  function verifyPurge(paths, plan) {
519
433
  const remainingReferences = [];
520
434
  const threadId = plan.target.id;
@@ -524,7 +438,7 @@ function verifyPurge(paths, plan) {
524
438
  checkTextFile(paths.sessionIndex, "session_index", threadId, remainingReferences);
525
439
  checkTextFile(paths.globalState, "global_state", threadId, remainingReferences);
526
440
  checkTextFile(paths.globalStateBackup, "global_state_backup", threadId, remainingReferences);
527
- if (existsSync6(plan.target.rolloutPath)) {
441
+ if (existsSync5(plan.target.rolloutPath)) {
528
442
  remainingReferences.push({
529
443
  store: "rollout_jsonl",
530
444
  path: plan.target.rolloutPath,
@@ -532,7 +446,7 @@ function verifyPurge(paths, plan) {
532
446
  });
533
447
  }
534
448
  for (const store of plan.stores) {
535
- if (store.store === "shell_snapshot" && existsSync6(store.path)) {
449
+ if (store.store === "shell_snapshot" && existsSync5(store.path)) {
536
450
  remainingReferences.push({
537
451
  store: "shell_snapshot",
538
452
  path: store.path,
@@ -546,7 +460,7 @@ function verifyPurge(paths, plan) {
546
460
  };
547
461
  }
548
462
  function checkSqlite(filePath, store, threadId, remainingReferences) {
549
- if (!existsSync6(filePath)) {
463
+ if (!existsSync5(filePath)) {
550
464
  return;
551
465
  }
552
466
  const db = openReadonlyDatabase(filePath);
@@ -578,7 +492,7 @@ function checkSqlite(filePath, store, threadId, remainingReferences) {
578
492
  }
579
493
  }
580
494
  function checkTextFile(filePath, store, threadId, remainingReferences) {
581
- if (!existsSync6(filePath)) {
495
+ if (!existsSync5(filePath)) {
582
496
  return;
583
497
  }
584
498
  const content = readFileSync3(filePath, "utf8");
@@ -592,9 +506,9 @@ function checkTextFile(filePath, store, threadId, remainingReferences) {
592
506
  }
593
507
 
594
508
  // src/stores/files.ts
595
- import { existsSync as existsSync7, unlinkSync } from "fs";
509
+ import { existsSync as existsSync6, unlinkSync } from "fs";
596
510
  function deleteFileIfExists(filePath) {
597
- if (!existsSync7(filePath)) {
511
+ if (!existsSync6(filePath)) {
598
512
  return {
599
513
  path: filePath,
600
514
  deleted: false
@@ -608,9 +522,9 @@ function deleteFileIfExists(filePath) {
608
522
  }
609
523
 
610
524
  // src/stores/json-state.ts
611
- import { existsSync as existsSync8, readFileSync as readFileSync4, writeFileSync as writeFileSync2 } from "fs";
525
+ import { existsSync as existsSync7, readFileSync as readFileSync4, writeFileSync } from "fs";
612
526
  function removeThreadFromSessionIndex(filePath, threadId) {
613
- if (!existsSync8(filePath)) {
527
+ if (!existsSync7(filePath)) {
614
528
  return { path: filePath, changed: false };
615
529
  }
616
530
  const original = readFileSync4(filePath, "utf8");
@@ -626,12 +540,12 @@ function removeThreadFromSessionIndex(filePath, threadId) {
626
540
  ` : "";
627
541
  const changed = next !== original;
628
542
  if (changed) {
629
- writeFileSync2(filePath, next);
543
+ writeFileSync(filePath, next);
630
544
  }
631
545
  return { path: filePath, changed };
632
546
  }
633
547
  function removeThreadFromGlobalState(filePath, threadId) {
634
- if (!existsSync8(filePath)) {
548
+ if (!existsSync7(filePath)) {
635
549
  return { path: filePath, changed: false };
636
550
  }
637
551
  const original = readFileSync4(filePath, "utf8");
@@ -639,7 +553,7 @@ function removeThreadFromGlobalState(filePath, threadId) {
639
553
  const nextValue = removeThreadReferences(parsed, threadId);
640
554
  const next = JSON.stringify(nextValue.value, null, 2) + "\n";
641
555
  if (nextValue.changed) {
642
- writeFileSync2(filePath, next);
556
+ writeFileSync(filePath, next);
643
557
  }
644
558
  return {
645
559
  path: filePath,
@@ -681,7 +595,6 @@ function removeThreadReferences(value, threadId) {
681
595
  // src/core/executor.ts
682
596
  function executePurge(paths, plan) {
683
597
  const activeThreadChecks = assertThreadIsNotActive(plan.target);
684
- const backup = createBackup(paths, plan);
685
598
  const sqlite = purgeSqlite(paths, plan.target.id);
686
599
  const json = [
687
600
  removeThreadFromSessionIndex(paths.sessionIndex, plan.target.id),
@@ -697,7 +610,6 @@ function executePurge(paths, plan) {
697
610
  mode: "executed",
698
611
  plan,
699
612
  activeThreadChecks,
700
- backup,
701
613
  sqlite,
702
614
  json,
703
615
  files,
@@ -706,7 +618,7 @@ function executePurge(paths, plan) {
706
618
  }
707
619
  function purgeSqlite(paths, threadId) {
708
620
  const results = [];
709
- if (existsSync9(paths.stateDb)) {
621
+ if (existsSync8(paths.stateDb)) {
710
622
  const db = openWritableDatabase(paths.stateDb);
711
623
  try {
712
624
  const transaction = db.transaction(() => {
@@ -727,7 +639,7 @@ function purgeSqlite(paths, threadId) {
727
639
  db.close();
728
640
  }
729
641
  }
730
- if (existsSync9(paths.logsDb)) {
642
+ if (existsSync8(paths.logsDb)) {
731
643
  const db = openWritableDatabase(paths.logsDb);
732
644
  try {
733
645
  const transaction = db.transaction(() => {
@@ -738,7 +650,7 @@ function purgeSqlite(paths, threadId) {
738
650
  db.close();
739
651
  }
740
652
  }
741
- if (existsSync9(paths.goalsDb)) {
653
+ if (existsSync8(paths.goalsDb)) {
742
654
  const db = openWritableDatabase(paths.goalsDb);
743
655
  try {
744
656
  const transaction = db.transaction(() => {
@@ -773,8 +685,8 @@ function purgeFiles(plan) {
773
685
  }
774
686
 
775
687
  // src/core/planner.ts
776
- import { existsSync as existsSync10, readdirSync, statSync as statSync3 } from "fs";
777
- import path3 from "path";
688
+ import { existsSync as existsSync9, readdirSync, statSync as statSync2 } from "fs";
689
+ import path2 from "path";
778
690
  function resolvePurgeTarget(paths, threadId) {
779
691
  if (!threadId.trim()) {
780
692
  throw new UsageError("Provide a thread id or unique short id prefix.");
@@ -801,7 +713,7 @@ function buildPurgePlan(paths, target) {
801
713
  for (const snapshot of findShellSnapshots(paths.shellSnapshotsDir, target.id)) {
802
714
  stores.push(planDeleteFile(snapshot, "shell_snapshot"));
803
715
  }
804
- if (!existsSync10(target.rolloutPath)) {
716
+ if (!existsSync9(target.rolloutPath)) {
805
717
  warnings.push(`rollout file is missing: ${target.rolloutPath}`);
806
718
  }
807
719
  return {
@@ -812,7 +724,7 @@ function buildPurgePlan(paths, target) {
812
724
  };
813
725
  }
814
726
  function planStateDb(filePath, threadId) {
815
- if (!existsSync10(filePath)) {
727
+ if (!existsSync9(filePath)) {
816
728
  return [missingStore("state_db", filePath)];
817
729
  }
818
730
  const db = openReadonlyDatabase(filePath);
@@ -845,7 +757,7 @@ function planStateDb(filePath, threadId) {
845
757
  }
846
758
  }
847
759
  function planLogsDb(filePath, threadId) {
848
- if (!existsSync10(filePath)) {
760
+ if (!existsSync9(filePath)) {
849
761
  return [missingStore("logs_db", filePath)];
850
762
  }
851
763
  const db = openReadonlyDatabase(filePath);
@@ -856,7 +768,7 @@ function planLogsDb(filePath, threadId) {
856
768
  }
857
769
  }
858
770
  function planGoalsDb(filePath, threadId) {
859
- if (!existsSync10(filePath)) {
771
+ if (!existsSync9(filePath)) {
860
772
  return [missingStore("goals_db", filePath)];
861
773
  }
862
774
  const db = openReadonlyDatabase(filePath);
@@ -874,7 +786,7 @@ function countTable(db, filePath, tableName, columnName, threadId, storeName) {
874
786
  path: filePath,
875
787
  action: "inspect",
876
788
  detail: `table or column unavailable: ${tableName}.${columnName}`,
877
- exists: existsSync10(filePath)
789
+ exists: existsSync9(filePath)
878
790
  };
879
791
  }
880
792
  return countPlan(storeName ?? `state_db.${tableName}`, filePath, count, "delete matching rows");
@@ -895,7 +807,7 @@ function planRewrite(filePath, store, detail) {
895
807
  path: filePath,
896
808
  action: "rewrite",
897
809
  detail,
898
- exists: existsSync10(filePath)
810
+ exists: existsSync9(filePath)
899
811
  };
900
812
  }
901
813
  function planDeleteFile(filePath, store) {
@@ -904,8 +816,8 @@ function planDeleteFile(filePath, store) {
904
816
  path: filePath,
905
817
  action: "delete_file",
906
818
  detail: "delete file",
907
- exists: existsSync10(filePath),
908
- count: existsSync10(filePath) ? statSync3(filePath).size : 0
819
+ exists: existsSync9(filePath),
820
+ count: existsSync9(filePath) ? statSync2(filePath).size : 0
909
821
  };
910
822
  }
911
823
  function missingStore(store, filePath) {
@@ -918,10 +830,10 @@ function missingStore(store, filePath) {
918
830
  };
919
831
  }
920
832
  function findShellSnapshots(shellSnapshotsDir, threadId) {
921
- if (!existsSync10(shellSnapshotsDir)) {
833
+ if (!existsSync9(shellSnapshotsDir)) {
922
834
  return [];
923
835
  }
924
- return readdirSync(shellSnapshotsDir).filter((entry) => entry.startsWith(`${threadId}.`) && entry.endsWith(".sh")).map((entry) => path3.join(shellSnapshotsDir, entry));
836
+ return readdirSync(shellSnapshotsDir).filter((entry) => entry.startsWith(`${threadId}.`) && entry.endsWith(".sh")).map((entry) => path2.join(shellSnapshotsDir, entry));
925
837
  }
926
838
 
927
839
  // src/commands/purge.ts
@@ -931,7 +843,7 @@ function planPurgeCommand(paths, threadId) {
931
843
  return buildPurgePlan(paths, target);
932
844
  }
933
845
  function executePurgePlanCommand(paths, plan) {
934
- validateSupportedDataModel(paths, { requireBackupHome: true });
846
+ validateSupportedDataModel(paths);
935
847
  return executePurge(paths, plan);
936
848
  }
937
849
 
@@ -962,8 +874,9 @@ function shortId(id) {
962
874
 
963
875
  // src/cli.ts
964
876
  var TITLE_MAX_LENGTH = 80;
877
+ var packageVersion = JSON.parse(readFileSync5(new URL("../package.json", import.meta.url), "utf8")).version;
965
878
  var program = new Command();
966
- program.name("codex-history").description("Inspect and safely purge local Codex conversation history.").version("0.1.0").option("--codex-home <path>", "Path to Codex home directory", "~/.codex").option("--json", "Print machine-readable JSON output");
879
+ program.name("codex-history").description("Inspect and safely purge local Codex conversation history.").version(packageVersion).option("--codex-home <path>", "Path to Codex home directory", "~/.codex").option("--json", "Print machine-readable JSON output");
967
880
  program.command("doctor").description("Check whether the local Codex data model is supported.").action(
968
881
  () => runCommand(() => {
969
882
  const report = doctorCommand(currentPaths());
@@ -1132,7 +1045,6 @@ function formatPurgeResult(result) {
1132
1045
  "",
1133
1046
  `Target: ${displayTitle(result.plan.target.title)}`,
1134
1047
  `Thread id: ${result.plan.target.id}`,
1135
- `Backup: ${colorize("dim", result.backup.backupDir)}`,
1136
1048
  "",
1137
1049
  "SQLite changes:",
1138
1050
  ...result.sqlite.map((change) => `- ${change.store}: ${change.changedRows} row(s)`),
@@ -1166,7 +1078,7 @@ function formatPurgeConfirmation(plan) {
1166
1078
  `cwd: ${colorize("dim", plan.target.cwd)}`,
1167
1079
  `updated: ${formatDate(plan.target.updatedAtMs)}`,
1168
1080
  "",
1169
- colorize("dim", "A backup will be created before deletion."),
1081
+ colorize("dim", "This cannot be undone."),
1170
1082
  ""
1171
1083
  ].join("\n");
1172
1084
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@liuyoumi/codex-history",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "CLI for listing and safely purging local Codex conversation history",
5
5
  "type": "module",
6
6
  "bin": {