@liuyoumi/codex-history 0.4.0 → 0.5.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/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.5.0 - 2026-05-29
4
+
5
+ ### Changed
6
+
7
+ - Narrow `--grep` matching to conversation text fields and let `--cwd` match working-directory path fragments.
8
+
3
9
  ## 0.4.0 - 2026-05-29
4
10
 
5
11
  ### Added
package/README.en.md CHANGED
@@ -77,10 +77,10 @@ Type 019e6885 to confirm:
77
77
  | --- | --- |
78
78
  | `codex-history doctor` | Check whether the local Codex data layout is supported. |
79
79
  | `codex-history list` | List local conversations. |
80
- | `codex-history list --grep <keyword>` | Filter conversations by title, id, or cwd. |
80
+ | `codex-history list --grep <keyword>` | Filter conversations by title, first user message, or preview. |
81
81
  | `codex-history purge <id...>` | Remove one or more resolved local conversations after confirmation. |
82
- | `codex-history purge --cwd <path>` | Remove local conversations matching a working directory after confirmation. |
83
- | `codex-history purge --grep <keyword>` | Remove local conversations matching title, id, or cwd after confirmation. |
82
+ | `codex-history purge --cwd <path>` | Remove local conversations whose working directory contains the path fragment after confirmation. |
83
+ | `codex-history purge --grep <keyword>` | Remove local conversations matching title, first user message, or preview after confirmation. |
84
84
  | `codex-history purge-orphans` | Remove orphaned local data after confirmation. |
85
85
 
86
86
  ### `doctor`
@@ -112,7 +112,13 @@ Default output is one line per conversation:
112
112
  019e6874 Review Astro blog visual plan
113
113
  ```
114
114
 
115
- `--grep` filters by displayed title, thread id, and cwd. It does not search or print prompt bodies.
115
+ `--grep` filters by displayed title, first user message, and preview. It does not match thread ids or cwd values, and it does not search or print full transcript bodies.
116
+
117
+ `--cwd` filters by a working-directory path fragment, so you can provide either a full path or a project name / partial path:
118
+
119
+ ```bash
120
+ codex-history list --cwd codex-history
121
+ ```
116
122
 
117
123
  Use the short id shown by `list`, or paste a full thread id, when running `purge`.
118
124
 
@@ -152,7 +158,7 @@ codex-history purge --archived
152
158
  codex-history purge --cwd /Users/me/Projects/example --grep "Astro"
153
159
  ```
154
160
 
155
- `--cwd`, `--grep`, and `--archived` can be combined. Combined filters delete only conversations that match every provided condition. By default, filter mode matches non-archived conversations only; use `--archived` to target archived conversations. Filtered purge prints a batch plan and requires typing `purge-selected`. Filters cannot be combined with explicit ids.
161
+ `--cwd`, `--grep`, and `--archived` can be combined. Combined filters delete only conversations that match every provided condition. `--cwd` matches working-directory path fragments, while `--grep` matches only title, first user message, and preview. By default, filter mode matches non-archived conversations only; use `--archived` to target archived conversations. Filtered purge prints a batch plan and matched cwd values, then requires typing `purge-selected`. Filters cannot be combined with explicit ids.
156
162
 
157
163
  For scripts or non-interactive shells, use `--force`:
158
164
 
package/README.md CHANGED
@@ -77,10 +77,10 @@ Type 019e6885 to confirm:
77
77
  | --- | --- |
78
78
  | `codex-history doctor` | 检查当前本地 Codex 数据结构是否受支持。 |
79
79
  | `codex-history list` | 列出本地对话。 |
80
- | `codex-history list --grep <keyword>` | 按标题、id 或 cwd 过滤对话。 |
80
+ | `codex-history list --grep <keyword>` | 按标题、首条用户消息或预览过滤对话。 |
81
81
  | `codex-history purge <id...>` | 确认后删除一条或多条解析到的本地对话。 |
82
- | `codex-history purge --cwd <path>` | 确认后删除匹配工作目录的本地对话。 |
83
- | `codex-history purge --grep <keyword>` | 确认后删除匹配标题、id 或 cwd 的本地对话。 |
82
+ | `codex-history purge --cwd <path>` | 确认后删除工作目录路径包含该片段的本地对话。 |
83
+ | `codex-history purge --grep <keyword>` | 确认后删除匹配标题、首条用户消息或预览的本地对话。 |
84
84
  | `codex-history purge-orphans` | 确认后清理本地孤儿数据。 |
85
85
 
86
86
  ### `doctor`
@@ -112,7 +112,13 @@ codex-history list --pretty=full
112
112
  019e6874 评审 Astro 博客视觉方案
113
113
  ```
114
114
 
115
- `--grep` 会按显示标题、线程 idcwd 过滤。它不会搜索或输出对话正文。
115
+ `--grep` 会按显示标题、首条用户消息和预览过滤。它不会匹配线程 idcwd,也不会搜索或输出完整对话正文。
116
+
117
+ `--cwd` 会按工作目录路径片段过滤,既可以输入完整路径,也可以输入项目名或部分路径:
118
+
119
+ ```bash
120
+ codex-history list --cwd codex-history
121
+ ```
116
122
 
117
123
  执行 `purge` 时,可以使用 `list` 里显示的短 id,也可以粘贴完整 thread id。
118
124
 
@@ -152,7 +158,7 @@ codex-history purge --archived
152
158
  codex-history purge --cwd /Users/me/Projects/example --grep "Astro"
153
159
  ```
154
160
 
155
- `--cwd`、`--grep`、`--archived` 可以组合,组合后只删除同时满足全部条件的对话。默认只匹配未归档对话;如果要删除已归档对话,请使用 `--archived`。过滤式删除会展示批量计划,并要求输入 `purge-selected` 确认。过滤条件不能和 id 同时使用。
161
+ `--cwd`、`--grep`、`--archived` 可以组合,组合后只删除同时满足全部条件的对话。`--cwd` 会匹配工作目录路径片段,`--grep` 只匹配标题、首条用户消息和预览。默认只匹配未归档对话;如果要删除已归档对话,请使用 `--archived`。过滤式删除会展示批量计划和匹配到的 cwd,并要求输入 `purge-selected` 确认。过滤条件不能和 id 同时使用。
156
162
 
157
163
  脚本或非交互环境可以使用 `--force`:
158
164
 
package/dist/cli.js CHANGED
@@ -290,8 +290,8 @@ function listThreads(paths, options = {}) {
290
290
  params.push(1);
291
291
  }
292
292
  if (options.cwd) {
293
- where.push(`${quoteIdentifier("cwd")} = ?`);
294
- params.push(options.cwd);
293
+ where.push(`lower(${quoteIdentifier("cwd")}) like lower(?) escape '\\'`);
294
+ params.push(`%${escapeLike(options.cwd)}%`);
295
295
  }
296
296
  const whereClause = where.length > 0 ? `where ${where.join(" and ")}` : "";
297
297
  const hasLimit = typeof limit === "number" && Number.isFinite(limit) && limit > 0;
@@ -321,9 +321,10 @@ function filterThreads(threads, keyword) {
321
321
  const normalizedKeyword = keyword.toLocaleLowerCase();
322
322
  return threads.filter((thread) => {
323
323
  const haystack = [
324
- thread.id,
325
324
  thread.title,
326
- thread.cwd
325
+ thread.sourceTitle,
326
+ thread.firstUserMessage,
327
+ thread.preview
327
328
  ].join("\n").toLocaleLowerCase();
328
329
  return haystack.includes(normalizedKeyword);
329
330
  });
@@ -1139,7 +1140,7 @@ program.command("doctor").description("Check whether the local Codex data model
1139
1140
  return formatDoctor(report);
1140
1141
  })
1141
1142
  );
1142
- program.command("list").description("List local Codex conversations.").option("--limit <number>", "Maximum rows to show", parseInteger).option("--all", "Include archived and non-archived threads").option("--archived", "Show archived threads").option("--cwd <path>", "Filter by exact working directory").option("--grep <keyword>", "Filter by title, id, or cwd keyword").option("--pretty <format>", "Output format: oneline, medium, full", parsePretty, "oneline").action(
1143
+ program.command("list").description("List local Codex conversations.").option("--limit <number>", "Maximum rows to show", parseInteger).option("--all", "Include archived and non-archived threads").option("--archived", "Show archived threads").option("--cwd <path>", "Filter by working directory path fragment").option("--grep <keyword>", "Filter by title, first user message, or preview keyword").option("--pretty <format>", "Output format: oneline, medium, full", parsePretty, "oneline").action(
1143
1144
  (options) => runCommand(
1144
1145
  () => formatThreads(
1145
1146
  listCommand(currentPaths(), {
@@ -1154,7 +1155,7 @@ program.command("list").description("List local Codex conversations.").option("-
1154
1155
  )
1155
1156
  )
1156
1157
  );
1157
- program.command("purge").argument("[threadIds...]", "Codex thread id(s) or unique short id prefix(es) to purge").option("--force", "Skip interactive confirmation").option("--cwd <path>", "Filter conversations by exact working directory").option("--grep <keyword>", "Filter conversations by title, id, or cwd keyword").option("--archived", "Filter archived conversations").description("Purge local Codex conversation(s) after target confirmation.").action(
1158
+ program.command("purge").argument("[threadIds...]", "Codex thread id(s) or unique short id prefix(es) to purge").option("--force", "Skip interactive confirmation").option("--cwd <path>", "Filter conversations by working directory path fragment").option("--grep <keyword>", "Filter conversations by title, first user message, or preview keyword").option("--archived", "Filter archived conversations").description("Purge local Codex conversation(s) after target confirmation.").action(
1158
1159
  (threadIds, options) => runCommand(async () => {
1159
1160
  const paths = currentPaths();
1160
1161
  const requestedThreadIds = threadIds ?? [];
@@ -1472,6 +1473,7 @@ function formatBatchPurgeConfirmation(plan) {
1472
1473
  "SQLite row changes:",
1473
1474
  ...formatSqliteRows(summarizePlannedSqliteRows(plan.plans)),
1474
1475
  "",
1476
+ ...formatMatchedCwdValues(plan),
1475
1477
  ...formatBatchPurgeExamples(plan),
1476
1478
  colorize("dim", "This cannot be undone."),
1477
1479
  ""
@@ -1486,16 +1488,28 @@ function formatBatchPurgeSelection(plan) {
1486
1488
  function formatPurgeFilters(filters) {
1487
1489
  const parts = [];
1488
1490
  if (filters.cwd) {
1489
- parts.push(`cwd=${filters.cwd}`);
1491
+ parts.push(`cwd contains "${filters.cwd}"`);
1490
1492
  }
1491
1493
  if (filters.grep) {
1492
- parts.push(`grep=${filters.grep}`);
1494
+ parts.push(`grep="${filters.grep}"`);
1493
1495
  }
1494
1496
  if (filters.archived) {
1495
1497
  parts.push("archived=true");
1496
1498
  }
1497
1499
  return parts.length > 0 ? parts.join(", ") : "filtered conversations";
1498
1500
  }
1501
+ function formatMatchedCwdValues(plan) {
1502
+ if (plan.source !== "filtered" || !plan.filters?.cwd || plan.plans.length === 0) {
1503
+ return [];
1504
+ }
1505
+ const cwdValues = [...new Set(plan.plans.map((item) => item.target.cwd))].sort();
1506
+ const shown = cwdValues.slice(0, 5);
1507
+ const lines = ["Matched cwd values:", ...shown.map((cwd) => `- ${colorize("dim", cwd)}`), ""];
1508
+ if (cwdValues.length > shown.length) {
1509
+ lines.push(`Showing ${shown.length} of ${cwdValues.length} cwd value(s).`, "");
1510
+ }
1511
+ return lines;
1512
+ }
1499
1513
  function formatPurgeOrphansConfirmation(plan) {
1500
1514
  return [
1501
1515
  "About to purge orphaned local Codex data:",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@liuyoumi/codex-history",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "description": "CLI for listing and safely purging local Codex conversation history",
5
5
  "type": "module",
6
6
  "bin": {