ai-cli-log 1.0.5 → 1.0.9

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 (49) hide show
  1. package/README.md +50 -85
  2. package/dist/index.js +46 -30
  3. package/package.json +3 -1
  4. package/src/index.ts +48 -38
  5. package/.ai-cli-log/0001.txt +0 -360
  6. package/.ai-cli-log/0002.txt +0 -1791
  7. package/.ai-cli-log/0003.txt +0 -338
  8. package/.ai-cli-log/0004.txt +0 -116
  9. package/.ai-cli-log/0005.txt +0 -105
  10. package/.ai-cli-log/config.json +0 -32
  11. package/.ai-cli-log/gemini-2025-07-13T13-33-13-a-quick-gemini-test.txt +0 -174
  12. package/.ai-cli-log/gemini-2025-07-13T13-37-00-typescript-check-pass.txt +0 -105
  13. package/.ai-cli-log/gemini-2025-07-13T13-44-15-rename-ai-cli-logs-to-log.txt +0 -164
  14. package/.ai-cli-log/gemini-20250705-154601.txt +0 -1320
  15. package/.ai-cli-log/gemini-20250705-155547.txt +0 -726
  16. package/.ai-cli-log/gemini-20250705-165038.txt +0 -66
  17. package/.ai-cli-log/gemini-20250705-171429.txt +0 -216
  18. package/.ai-cli-log/gemini-20250705-191202.txt +0 -448
  19. package/.ai-cli-log/gemini-20250705-193741.txt +0 -901
  20. package/.ai-cli-log/gemini-20250705-194435.txt +0 -110
  21. package/.ai-cli-log/gemini-20250705-195926.txt +0 -415
  22. package/.ai-cli-log/gemini-20250705-201738.txt +0 -246
  23. package/.ai-cli-log/gemini-20250713-204921.txt +0 -3036
  24. package/.ai-cli-log/gemini-20250713-215941-update-ai-cli-log-documentation.txt +0 -400
  25. package/.ai-cli-log/gemini-20250713-220544-removed-debug-logs-successfully.txt +0 -258
  26. package/.ai-cli-log/gemini-20250713-221128-sessionsummarytxt.txt +0 -112
  27. package/.ai-cli-log/gemini-20250714-084659.txt +0 -86
  28. package/.ai-cli-log/gemini-20250714-085847-update-prompt-configuration.txt +0 -189
  29. package/.ai-cli-log/gemini-20250714-090905-add-sgpt-custom-summarizer.txt +0 -284
  30. package/.ai-cli-log/gemini-20250714-092329.txt +0 -110
  31. package/.ai-cli-log/gemini-20250714-092935.txt +0 -183
  32. package/.ai-cli-log/gemini-20250714-093205-heres-a-concise-summary-of-the-terminal-session-fix-sgpt-option-error-this-captures-1-the-action-fix-2-the-tool-involved-sgpt-3-the-issue-option-error-4-follows-the-requested-lowercase-hyphenated-format.txt +0 -140
  33. package/.ai-cli-log/gemini-20250714-094141-heres-the-concise-summary-build-check-clean-this-captures-1.txt +0 -111
  34. package/.ai-cli-log/gemini-20250714-094405-heres-the-concise-summary-clean-build-check-this-captures-1.txt +0 -111
  35. package/.ai-cli-log/gemini-20250714-094816-json-summary-format.txt +0 -132
  36. package/.ai-cli-log/gemini-20250714-094833-optimize-summary-logic.txt +0 -342
  37. package/.ai-cli-log/gemini-20250714-133202-refactor-config-initialization.txt +0 -1729
  38. package/.ai-cli-log/gemini-20250714-134138-update-summary-logic.txt +0 -153
  39. package/.ai-cli-log/gemini-20250714-134749-json-summary-format.txt +0 -214
  40. package/.ai-cli-log/gemini-20250714-140527.txt +0 -715
  41. package/.ai-cli-log/gemini-20250714-142018.txt +0 -86
  42. package/.ai-cli-log/gemini-20250714-142027-update-summary-format.txt +0 -86
  43. package/.ai-cli-log/gemini-20250714-142100-session-complete.txt +0 -86
  44. package/.ai-cli-log/gemini-20250714-142129-refactor-readme-structure.txt +0 -584
  45. package/.ai-cli-log/gemini-20250714-213153.txt +0 -1195
  46. package/.ai-cli-log/session-20250705-150655.txt +0 -174
  47. package/.ai-cli-log/session-20250705-151726.txt +0 -313
  48. package/.github/workflows/node.js.yml +0 -30
  49. package/GEMINI.md +0 -54
package/README.md CHANGED
@@ -10,27 +10,33 @@ npm install -g ai-cli-log
10
10
 
11
11
  ## Usage
12
12
 
13
- Wrap any command with `ai-cli-log` to start a logging session.
13
+ Wrap any command with `ai-cli-log` to start a logging session. The core structure is:
14
14
 
15
15
  ```bash
16
- ai-cli-log <command> [args...]
16
+ ai-cli-log [global-options] run <command-to-log> [args...]
17
17
  ```
18
18
 
19
19
  **Examples:**
20
20
 
21
21
  - **Basic Logging:** Record a session with Google's Gemini CLI.
22
22
  ```bash
23
- ai-cli-log gemini
23
+ ai-cli-log run gemini
24
24
  ```
25
25
  *Logs are saved to the `.ai-cli-log/` directory.*
26
26
 
27
- - **AI-Powered Filenames:** Use an AI summary for the log's filename.
27
+ - **AI-Powered Filenames:** Use an AI summary for the log's filename. The options must come **before** the `run` command.
28
28
  ```bash
29
- ai-cli-log -s <command> [args...]
29
+ # Enable summary with the default summarizer
30
+ ai-cli-log -s run gemini
30
31
  # or
31
- ai-cli-log --with-summary <command> [args...]
32
+ ai-cli-log --with-summary run gemini
33
+
34
+ # Enable summary and specify a summarizer
35
+ ai-cli-log --by gemini-pro run gemini
36
+ # or
37
+ ai-cli-log --summarizer gemini-pro run gemini
32
38
  ```
33
- This will use your default summarizer to generate a descriptive filename like `gemini-20250713-153000-fix-database-connection-error.md`. You can also specify a summarizer: `ai-cli-log -s=my-ollama-summarizer ...`.
39
+ This will use your default (or specified) summarizer to generate a descriptive filename like `gemini-20250713-153000-fix-database-connection-error.txt`.
34
40
 
35
41
  ## Configuration
36
42
 
@@ -42,19 +48,19 @@ ai-cli-log <command> [args...]
42
48
 
43
49
  You can create these files manually or by using the interactive setup command.
44
50
 
45
- ### Interactive Setup (`--init`)
51
+ ### Interactive Setup (`init`)
46
52
 
47
- The `--init` command helps you create a configuration file.
53
+ The `init` command helps you create a configuration file. It will scan for available AI tools, guide you through creating summarizer profiles, and set a default.
48
54
 
49
55
  * **To create a global configuration:**
50
56
  ```bash
51
- ai-cli-log --init
57
+ ai-cli-log init
52
58
  ```
53
59
  This saves the configuration to `~/.config/ai-cli-log/config.json`.
54
60
 
55
61
  * **To create a local (project-specific) configuration:**
56
62
  ```bash
57
- ai-cli-log --init --local
63
+ ai-cli-log init --local
58
64
  ```
59
65
  This saves the configuration to `.ai-cli-log/config.json` in the current directory.
60
66
 
@@ -83,23 +89,14 @@ Here is an example of a manual `config.json`:
83
89
  {
84
90
  "name": "sgpt",
85
91
  "tool": "custom",
86
- "command": ["sgpt", "--chat", "session-summary", "\"{{prompt}}\""]
87
- },
88
-
89
- * **To create a global configuration file (at `~/.config/ai-cli-log/config.json`):**
90
- ```bash
91
- ai-cli-log --init
92
- ```
93
-
94
- * **To create a local, project-specific configuration file (at `.ai-cli-log/config.json`):**
95
- ```bash
96
- ai-cli-log --init --local
97
- ```
98
-
99
- This command will:
100
- 1. Scan for available AI tools on your system (like `gemini`, `sgpt`, or `ollama`).
101
- 2. Guide you through creating summarizer profiles for them.
102
- 3. Set a default summarizer.
92
+ "prompt": "You are a log summarizer. Your response MUST be a valid JSON object with one key: \"summary\" (a 3-5 word, lowercase, filename-friendly phrase). Example: {\"summary\": \"refactor-database-schema\"}. The session content is:",
93
+ "command": ["sgpt", "--chat", "session-summary", "\"{{prompt}}\""],
94
+ "maxLines": 50
95
+ }
96
+ ]
97
+ }
98
+ }
99
+ ```
103
100
 
104
101
  ## Features
105
102
 
@@ -108,7 +105,7 @@ This command will:
108
105
  * **Accurate Rendering:** Uses `@xterm/headless` to interpret ANSI escape codes, ensuring the log accurately reflects the final terminal state (spinners, progress bars, etc.).
109
106
  * **Configurable:** Supports different AI backends (`gemini`, `sgpt`, `ollama`, etc.) for generating summaries.
110
107
  * **Performance-Aware:** When summarizing long sessions, it intelligently samples the beginning and end of the output to ensure fast and cost-effective summary generation.
111
- * **Markdown Output:** Saves sessions as clean Markdown files.
108
+ * **Plain Text Output:** Saves sessions as clean plain text files.
112
109
 
113
110
  ## Development Notes
114
111
 
@@ -118,7 +115,6 @@ Special thanks to Gemini for its invaluable help in the development of this tool
118
115
 
119
116
  ## TODO
120
117
 
121
- * **Argument Parsing:** Refactor the manual argument parsing to use a robust library like `yargs` or `commander` to improve maintainability and provide standard features like `--help`.
122
118
  * **Markdown Support:** Investigate and potentially implement saving logs in Markdown format, which could include session metadata (e.g., command, timestamp, summary) in a frontmatter block.
123
119
 
124
120
  ---
@@ -135,27 +131,33 @@ npm install -g ai-cli-log
135
131
 
136
132
  ## 使用方法
137
133
 
138
- 使用 `ai-cli-log` 命令来包装任何您想记录的命令。
134
+ 使用 `ai-cli-log` 命令来包装任何您想记录的命令。核心结构是:
139
135
 
140
136
  ```bash
141
- ai-cli-log <command> [args...]
137
+ ai-cli-log [全局选项] run <要记录的命令> [参数...]
142
138
  ```
143
139
 
144
140
  **示例:**
145
141
 
146
142
  - **基本日志记录:** 记录与 Google Gemini CLI 的会话。
147
143
  ```bash
148
- ai-cli-log gemini
144
+ ai-cli-log run gemini
149
145
  ```
150
146
  *日志将保存到 `.ai-cli-log/` 目录中。*
151
147
 
152
- - **AI 驱动的文件名:** 使用 AI 摘要作为日志文件名。
148
+ - **AI 驱动的文件名:** 使用 AI 摘要作为日志文件名。选项必须在 `run` 命令**之前**。
153
149
  ```bash
154
- ai-cli-log -s <命令> [参数...]
150
+ # 使用默认摘要器启用摘要
151
+ ai-cli-log -s run gemini
155
152
  # 或
156
- ai-cli-log --with-summary <命令> [参数...]
153
+ ai-cli-log --with-summary run gemini
154
+
155
+ # 启用摘要并指定一个摘要器
156
+ ai-cli-log --by gemini-pro run gemini
157
+ # 或
158
+ ai-cli-log --summarizer gemini-pro run gemini
157
159
  ```
158
- 这将使用您的默认摘要器生成一个描述性的文件名,例如 `gemini-20250713-153000-fix-database-connection-error.md`。您也可以指定一个摘要器:`ai-cli-log -s=my-ollama-summarizer ...`。
160
+ 这将使用您默认(或指定)的摘要器生成一个描述性的文件名,例如 `gemini-20250713-153000-fix-database-connection-error.txt`。
159
161
 
160
162
  ## 配置
161
163
 
@@ -167,19 +169,19 @@ ai-cli-log <command> [args...]
167
169
 
168
170
  您可以通过手动或使用交互式设置命令来创建这些文件。
169
171
 
170
- ### 交互式设置 (`--init`)
172
+ ### 交互式设置 (`init`)
171
173
 
172
- `--init` 命令可以帮助您创建配置文件。
174
+ `init` 命令可以帮助您创建配置文件。它会扫描可用的 AI 工具,引导您完成摘要器配置的创建,并设置一个默认值。
173
175
 
174
176
  * **创建全局配置文件:**
175
177
  ```bash
176
- ai-cli-log --init
178
+ ai-cli-log init
177
179
  ```
178
180
  这会将配置保存到 `~/.config/ai-cli-log/config.json`。
179
181
 
180
182
  * **创建本地(项目特定)配置文件:**
181
183
  ```bash
182
- ai-cli-log --init --local
184
+ ai-cli-log init --local
183
185
  ```
184
186
  这会将配置保存到当前目录的 `.ai-cli-log/config.json` 中。
185
187
 
@@ -195,22 +197,22 @@ ai-cli-log <command> [args...]
195
197
  {
196
198
  "name": "gemini-pro",
197
199
  "tool": "gemini",
198
- "prompt": "你是一个日志摘要器。你的响应必须是一个有效的 JSON 对象,其中包含一个键:"summary"(一个 3-5 个单词的、小写的、文件名友好的短语)。示例:{"summary": "refactor-database-schema"}。会话内容是:",
200
+ "prompt": "你是一个日志摘要器。你的响应必须是一个有效的 JSON 对象,其中包含一个键:\"summary\"(一个 3-5 个单词的、小写的、文件名友好的短语)。示例:{\"summary\": \"refactor-database-schema\"}。会话内容是:",
199
201
  "maxLines": 100
200
202
  },
201
203
  {
202
204
  "name": "ollama",
203
205
  "tool": "ollama",
204
206
  "model": "llama3",
205
- "prompt": "你是一个日志摘要器。你的响应必须是一个有效的 JSON 对象,其中包含一个键:"summary"(一个 3-5 个单词的、小写的、文件名友好的短语)。示例:{"summary": "refactor-database-schema"}。会话内容是:",
207
+ "prompt": "你是一个日志摘要器。你的响应必须是一个有效的 JSON 对象,其中包含一个键:\"summary\"(一个 3-5 个单词的、小写的、文件名友好的短语)。示例:{\"summary\": \"refactor-database-schema\"}。会话内容是:",
206
208
  "maxLines": 50
207
209
  },
208
210
  {
209
211
  "name": "sgpt",
210
212
  "tool": "custom",
211
- "command": ["sgpt", "--chat", "session-summary", ""{{prompt}}""],
212
- "prompt": "你是一个日志摘要器。你的响应必须是一个有效的 JSON 对象,其中包含一个键:"summary"(一个 3-5 个单词的、小写的、文件名友好的短语)。示例:{"summary": "refactor-database-schema"}。会话内容是:",
213
- "maxLines": 100
213
+ "command": ["sgpt", "--chat", "session-summary", "\"{{prompt}}\""],
214
+ "prompt": "你是一个日志摘要器。你的响应必须是一个有效的 JSON 对象,其中包含一个键\"summary\"(一个 3-5 个单词的、小写的、文件名友好的短语)。示例:{\"summary\": \"refactor-database-schema\"}。会话内容是:",
215
+ "maxLines": 50
214
216
  },
215
217
  {
216
218
  "name": "my-custom-summarizer",
@@ -238,40 +240,7 @@ ai-cli-log <command> [args...]
238
240
  * **`prompt`**: 传递给摘要器命令的提示。会话内容将作为标准输入传递。
239
241
  * **`maxLines`** (可选): 限制传递给摘要器的会话内容行数。如果会话内容超过此限制,将只采样开头和结尾的行。
240
242
  * **`command`** (可选): 对于 `custom` 工具,指定要执行的命令数组。会话内容会通过管道传递给该命令的 `stdin`。`{{prompt}}` 占位符将被实际的提示字符串替换。例如: `["my-summarizer-script", "--prompt", "{{prompt}}"]`。
241
- * **重要**: 摘要器的输出**必须**是一个有效的 JSON 对象,其中包含一个名为 `summary` 的键(例如,`{"summary": "你的摘要短语"}`)。
242
- ```
243
-
244
- **Field Descriptions:**
245
-
246
- * `summarizer.default` (optional): The name of the default summarizer configuration to use.
247
- * `summarizer.summarizers`: An array of different summarizer configurations.
248
- * **`name`**: A unique name you give to the summarizer configuration (e.g., `gemini-pro`, `ollama`, `claude-opus`, `my-custom-summarizer`).
249
- * **`tool`**: The type of tool the summarizer uses.
250
- * `gemini`: Uses the `gemini` CLI tool.
251
- * `ollama`: Uses the `ollama` CLI tool.
252
- * `claude`: Uses the `claude` CLI tool.
253
- * `custom`: Uses a custom command.
254
- * **`model`** (optional): For the `ollama` tool, specifies the model name to use (e.g., `llama3`).
255
- * **`prompt`**: The prompt passed to the summarizer command. The session content will be passed as standard input.
256
- * **`maxLines`** (optional): Limits the number of session content lines passed to the summarizer. If the session exceeds this limit, only the beginning and end lines will be sampled.
257
- * **`command`** (optional): For the `custom` tool, specifies the command array to execute. The session content is piped to this command's `stdin`. The `{{prompt}}` placeholder will be replaced with the actual prompt string. Example: `["my-summarizer-script", "--prompt", "{{prompt}}"]`.
258
- * **Important**: The output from the summarizer **MUST** be a valid JSON object containing a key named `summary` (e.g., `{"summary": "your-summary-phrase"}`).
259
-
260
- ### 交互式设置 (`--init`)
261
-
262
- 运行交互式设置来创建配置文件。
263
-
264
- * **创建全局配置文件 (位于 `~/.config/ai-cli-log/config.json`):**
265
- ```bash
266
- ai-cli-log --init
267
- ```
268
-
269
- * **创建本地、项目特定的配置文件 (位于 `.ai-cli-log/config.json`):**
270
- ```bash
271
- ai-cli-log --init --local
272
- ```
273
-
274
- 该命令将引导您完成配置过程,包括扫描可用的 AI 工具、创建摘要器配置和设置默认摘要器。
243
+ * **重要**: 摘要器的输出**必须**是一个有效的 JSON 对象,其中包含一个名为 `summary` 的键(例如,`{"summary": "fix-login-bug"}`)。
275
244
 
276
245
  ## 功能特性
277
246
 
@@ -290,8 +259,4 @@ ai-cli-log <command> [args...]
290
259
 
291
260
  ## 待办事项 (TODO)
292
261
 
293
- * **内容处理:**
294
- * 当会话输出为空时,避免保存空的日志文件。
295
- * 尾随空格和空行现在已从输出中删除,以解决内容不足导致大片空白区域的问题。
296
- * **文件名约定:** 当前基于时间戳的文件名虽然功能上可行,但可能过于单调。评估其他更具描述性的文件名方案,同时仔细考虑如果使用 AI 摘要进行命名可能导致的信息泄露问题。
297
-
262
+ * **Markdown 支持:** 探寻并实现将日志保存为 Markdown 格式的可能性,可在文件的 frontmatter 中包含会话元数据(如:命令、时间戳、摘要等)。
package/dist/index.js CHANGED
@@ -44,6 +44,7 @@ const os = __importStar(require("os"));
44
44
  const child_process_1 = require("child_process");
45
45
  const headless_1 = require("@xterm/headless");
46
46
  const readline_1 = __importDefault(require("readline"));
47
+ const commander_1 = require("commander");
47
48
  // --- 1. CONFIGURATION & TYPE DEFINITIONS ---
48
49
  const GLOBAL_CONFIG_DIR = path.join(os.homedir(), '.config', 'ai-cli-log');
49
50
  const GLOBAL_CONFIG_PATH = path.join(GLOBAL_CONFIG_DIR, 'config.json');
@@ -125,7 +126,7 @@ async function handleInitCommand(isLocal) {
125
126
  }
126
127
  const config = readConfig();
127
128
  const summarizersToUpdate = [];
128
- const newPrompt = 'You are a log summarizer. Your response MUST be a valid JSON object with one key: "summary" (a 3-5 word, lowercase, filename-friendly phrase). Example: {"summary": "refactor-database-schema"}. The session content is:';
129
+ const newPrompt = 'You are a log summarizer. Your response MUST be a raw, valid JSON object and nothing else. Do not wrap it in markdown blocks like ```json. The JSON object must have a single key "summary" which is a 3-5 word, lowercase, filename-friendly phrase. Example: {"summary": "refactor-database-schema"}. The session content is:';
129
130
  if (availableTools.includes('gemini')) {
130
131
  const add = await ask('\n> Found Gemini. Add/update the \'gemini-pro\' summarizer? (Y/n): ');
131
132
  if (add.toLowerCase() !== 'n') {
@@ -345,7 +346,10 @@ function runLoggingSession(command, commandArgs, summaryArg) {
345
346
  const config = readConfig();
346
347
  const summarizerName = (typeof summaryArg === 'string' ? summaryArg : config.summarizer.default) || 'default';
347
348
  try {
348
- const summaryData = JSON.parse(rawSummaryJson);
349
+ // Pre-process the raw summary to extract JSON from markdown blocks if present
350
+ const jsonMatch = rawSummaryJson.match(/\{.*\}/s);
351
+ const cleanJson = jsonMatch ? jsonMatch[0] : rawSummaryJson;
352
+ const summaryData = JSON.parse(cleanJson);
349
353
  const slug = summaryData.summary;
350
354
  if (typeof slug !== 'string') {
351
355
  throw new Error('Invalid JSON structure from summarizer: "summary" key is missing or not a string.');
@@ -382,34 +386,46 @@ function runLoggingSession(command, commandArgs, summaryArg) {
382
386
  }
383
387
  // --- 3. MAIN ENTRY POINT & ARGUMENT PARSER ---
384
388
  function main() {
385
- const args = process.argv.slice(2);
386
- if (args.includes('--version') || args.includes('-v')) {
387
- // eslint-disable-next-line @typescript-eslint/no-var-requires
388
- const pkg = require('../package.json');
389
- console.log(pkg.version);
390
- return;
391
- }
392
- if (args.includes('--init')) {
393
- const isLocal = args.includes('--local');
394
- handleInitCommand(isLocal);
395
- return;
396
- }
397
- const summaryArgRaw = args.find(arg => arg.startsWith('--with-summary') || arg.startsWith('-s'));
398
- const otherArgs = args.filter(arg => !arg.startsWith('--with-summary') &&
399
- !arg.startsWith('-s') &&
400
- arg !== '--init' &&
401
- arg !== '--local');
402
- const command = otherArgs[0];
403
- const commandArgs = otherArgs.slice(1);
404
- if (!command) {
405
- console.error('Usage: ai-cli-log [-s[=<summarizer>]] <command> [args...]');
406
- console.error(' ai-cli-log --init [--local]');
407
- process.exit(1);
408
- }
409
- let summaryArg = false;
410
- if (summaryArgRaw) {
411
- summaryArg = summaryArgRaw.includes('=') ? summaryArgRaw.split('=')[1] : true;
389
+ const program = new commander_1.Command();
390
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
391
+ const pkg = require('../package.json');
392
+ program
393
+ .name('ai-cli-log')
394
+ .description('A CLI tool to seamlessly log terminal sessions with AI models.')
395
+ .version(pkg.version, '-v, --version', 'Output the current version')
396
+ .option('-s, --with-summary', 'Enable AI summary for the session using the default summarizer.')
397
+ .option('--by <name>, --summarizer <name>', 'Specify a summarizer to use. Implies --with-summary.');
398
+ program
399
+ .command('init')
400
+ .description('Initialize or update the configuration file.')
401
+ .option('--local', 'Create the configuration file in the current directory\'s .ai-cli-log folder.', false)
402
+ .action((options) => {
403
+ handleInitCommand(options.local);
404
+ });
405
+ program
406
+ .command('run')
407
+ .usage('<command> [args...]')
408
+ .description("Run a command and log the session. Any options for ai-cli-log itself (like -s) must come before the 'run' command.")
409
+ .argument('<command>', 'The command to execute and log.')
410
+ .argument('[args...]', 'Arguments for the command.')
411
+ .allowUnknownOption()
412
+ .action((command, args) => {
413
+ const options = program.opts();
414
+ let summaryArg = false;
415
+ if (options.by) {
416
+ summaryArg = options.by;
417
+ }
418
+ else if (options.summarizer) {
419
+ summaryArg = options.summarizer;
420
+ }
421
+ else if (options.withSummary) {
422
+ summaryArg = true;
423
+ }
424
+ runLoggingSession(command, args, summaryArg);
425
+ });
426
+ program.parse(process.argv);
427
+ if (!process.argv.slice(2).length) {
428
+ program.help();
412
429
  }
413
- runLoggingSession(command, commandArgs, summaryArg);
414
430
  }
415
431
  main();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-cli-log",
3
- "version": "1.0.5",
3
+ "version": "1.0.9",
4
4
  "description": "Seamlessly log your AI-powered coding conversations. This command-line interface (CLI) tool captures your terminal interactions with AI models like Gemini and Claude, saving entire sessions as clean plain text documents for easy review and documentation.",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -23,12 +23,14 @@
23
23
  },
24
24
  "homepage": "https://github.com/alingse/ai-cli-log#readme",
25
25
  "devDependencies": {
26
+ "@types/commander": "^2.12.0",
26
27
  "@types/node": "^24.0.10",
27
28
  "ts-node": "^10.9.2",
28
29
  "typescript": "^5.8.3"
29
30
  },
30
31
  "dependencies": {
31
32
  "@xterm/headless": "^5.5.0",
33
+ "commander": "^14.0.0",
32
34
  "node-pty": "^1.0.0"
33
35
  }
34
36
  }
package/src/index.ts CHANGED
@@ -7,6 +7,7 @@ import * as os from 'os';
7
7
  import { spawn } from 'child_process';
8
8
  import { Terminal } from '@xterm/headless';
9
9
  import readline from 'readline';
10
+ import { Command } from 'commander';
10
11
 
11
12
  // --- 1. CONFIGURATION & TYPE DEFINITIONS ---
12
13
 
@@ -110,7 +111,7 @@ async function handleInitCommand(isLocal: boolean) {
110
111
 
111
112
  const config = readConfig();
112
113
  const summarizersToUpdate: Summarizer[] = [];
113
- const newPrompt = 'You are a log summarizer. Your response MUST be a valid JSON object with one key: "summary" (a 3-5 word, lowercase, filename-friendly phrase). Example: {"summary": "refactor-database-schema"}. The session content is:';
114
+ const newPrompt = 'You are a log summarizer. Your response MUST be a raw, valid JSON object and nothing else. Do not wrap it in markdown blocks like ```json. The JSON object must have a single key "summary" which is a 3-5 word, lowercase, filename-friendly phrase. Example: {"summary": "refactor-database-schema"}. The session content is:';
114
115
 
115
116
  if (availableTools.includes('gemini')) {
116
117
  const add = await ask('\n> Found Gemini. Add/update the \'gemini-pro\' summarizer? (Y/n): ');
@@ -357,7 +358,11 @@ function runLoggingSession(command: string, commandArgs: string[], summaryArg?:
357
358
  const summarizerName = (typeof summaryArg === 'string' ? summaryArg : config.summarizer.default) || 'default';
358
359
 
359
360
  try {
360
- const summaryData = JSON.parse(rawSummaryJson);
361
+ // Pre-process the raw summary to extract JSON from markdown blocks if present
362
+ const jsonMatch = rawSummaryJson.match(/\{.*\}/s);
363
+ const cleanJson = jsonMatch ? jsonMatch[0] : rawSummaryJson;
364
+
365
+ const summaryData = JSON.parse(cleanJson);
361
366
  const slug = summaryData.summary;
362
367
 
363
368
  if (typeof slug !== 'string') {
@@ -399,45 +404,50 @@ function runLoggingSession(command: string, commandArgs: string[], summaryArg?:
399
404
  // --- 3. MAIN ENTRY POINT & ARGUMENT PARSER ---
400
405
 
401
406
  function main() {
402
- const args = process.argv.slice(2);
403
-
404
- if (args.includes('--version') || args.includes('-v')) {
405
- // eslint-disable-next-line @typescript-eslint/no-var-requires
406
- const pkg = require('../package.json');
407
- console.log(pkg.version);
408
- return;
409
- }
407
+ const program = new Command();
408
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
409
+ const pkg = require('../package.json');
410
+
411
+ program
412
+ .name('ai-cli-log')
413
+ .description('A CLI tool to seamlessly log terminal sessions with AI models.')
414
+ .version(pkg.version, '-v, --version', 'Output the current version')
415
+ .option('-s, --with-summary', 'Enable AI summary for the session using the default summarizer.')
416
+ .option('--by <name>, --summarizer <name>', 'Specify a summarizer to use. Implies --with-summary.');
417
+
418
+ program
419
+ .command('init')
420
+ .description('Initialize or update the configuration file.')
421
+ .option('--local', 'Create the configuration file in the current directory\'s .ai-cli-log folder.', false)
422
+ .action((options) => {
423
+ handleInitCommand(options.local);
424
+ });
410
425
 
411
- if (args.includes('--init')) {
412
- const isLocal = args.includes('--local');
413
- handleInitCommand(isLocal);
414
- return;
415
- }
426
+ program
427
+ .command('run')
428
+ .usage('<command> [args...]')
429
+ .description("Run a command and log the session. Any options for ai-cli-log itself (like -s) must come before the 'run' command.")
430
+ .argument('<command>', 'The command to execute and log.')
431
+ .argument('[args...]', 'Arguments for the command.')
432
+ .allowUnknownOption()
433
+ .action((command, args) => {
434
+ const options = program.opts();
435
+ let summaryArg: string | boolean = false;
436
+ if (options.by) {
437
+ summaryArg = options.by;
438
+ } else if (options.summarizer) {
439
+ summaryArg = options.summarizer;
440
+ } else if (options.withSummary) {
441
+ summaryArg = true;
442
+ }
443
+ runLoggingSession(command, args, summaryArg);
444
+ });
416
445
 
417
- const summaryArgRaw = args.find(arg => arg.startsWith('--with-summary') || arg.startsWith('-s'));
418
-
419
- const otherArgs = args.filter(arg =>
420
- !arg.startsWith('--with-summary') &&
421
- !arg.startsWith('-s') &&
422
- arg !== '--init' &&
423
- arg !== '--local'
424
- );
425
-
426
- const command = otherArgs[0];
427
- const commandArgs = otherArgs.slice(1);
428
-
429
- if (!command) {
430
- console.error('Usage: ai-cli-log [-s[=<summarizer>]] <command> [args...]');
431
- console.error(' ai-cli-log --init [--local]');
432
- process.exit(1);
433
- }
446
+ program.parse(process.argv);
434
447
 
435
- let summaryArg: string | boolean = false;
436
- if (summaryArgRaw) {
437
- summaryArg = summaryArgRaw.includes('=') ? summaryArgRaw.split('=')[1] : true;
448
+ if (!process.argv.slice(2).length) {
449
+ program.help();
438
450
  }
439
-
440
- runLoggingSession(command, commandArgs, summaryArg);
441
451
  }
442
452
 
443
- main();
453
+ main();