ai-cli-log 1.0.5 → 1.0.6
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/.ai-cli-log/config.json +4 -4
- package/.ai-cli-log/gemini-20250714-222508-refactor-command-parser.txt +2110 -0
- package/README.md +25 -26
- package/dist/index.js +39 -30
- package/package.json +3 -1
- package/src/index.ts +43 -38
package/README.md
CHANGED
|
@@ -10,27 +10,27 @@ 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 `-s` or `--with-summary` option must come **before** the `run` command.
|
|
28
28
|
```bash
|
|
29
|
-
ai-cli-log -s <command> [args...]
|
|
30
|
-
# or
|
|
31
|
-
ai-cli-log --with-summary <command> [args...]
|
|
29
|
+
ai-cli-log -s run <command> [args...]
|
|
30
|
+
# or specify a summarizer
|
|
31
|
+
ai-cli-log --with-summary=gemini-pro run <command> [args...]
|
|
32
32
|
```
|
|
33
|
-
This will use your default summarizer to generate a descriptive filename like `gemini-20250713-153000-fix-database-connection-error.md`.
|
|
33
|
+
This will use your default (or specified) summarizer to generate a descriptive filename like `gemini-20250713-153000-fix-database-connection-error.md`.
|
|
34
34
|
|
|
35
35
|
## Configuration
|
|
36
36
|
|
|
@@ -42,19 +42,19 @@ ai-cli-log <command> [args...]
|
|
|
42
42
|
|
|
43
43
|
You can create these files manually or by using the interactive setup command.
|
|
44
44
|
|
|
45
|
-
### Interactive Setup (
|
|
45
|
+
### Interactive Setup (`init`)
|
|
46
46
|
|
|
47
|
-
The
|
|
47
|
+
The `init` command helps you create a configuration file.
|
|
48
48
|
|
|
49
49
|
* **To create a global configuration:**
|
|
50
50
|
```bash
|
|
51
|
-
ai-cli-log
|
|
51
|
+
ai-cli-log init
|
|
52
52
|
```
|
|
53
53
|
This saves the configuration to `~/.config/ai-cli-log/config.json`.
|
|
54
54
|
|
|
55
55
|
* **To create a local (project-specific) configuration:**
|
|
56
56
|
```bash
|
|
57
|
-
ai-cli-log
|
|
57
|
+
ai-cli-log init --local
|
|
58
58
|
```
|
|
59
59
|
This saves the configuration to `.ai-cli-log/config.json` in the current directory.
|
|
60
60
|
|
|
@@ -118,7 +118,6 @@ Special thanks to Gemini for its invaluable help in the development of this tool
|
|
|
118
118
|
|
|
119
119
|
## TODO
|
|
120
120
|
|
|
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
121
|
* **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
122
|
|
|
124
123
|
---
|
|
@@ -135,27 +134,27 @@ npm install -g ai-cli-log
|
|
|
135
134
|
|
|
136
135
|
## 使用方法
|
|
137
136
|
|
|
138
|
-
使用 `ai-cli-log`
|
|
137
|
+
使用 `ai-cli-log` 命令来包装任何您想记录的命令。核心结构是:
|
|
139
138
|
|
|
140
139
|
```bash
|
|
141
|
-
ai-cli-log
|
|
140
|
+
ai-cli-log [全局选项] run <要记录的命令> [参数...]
|
|
142
141
|
```
|
|
143
142
|
|
|
144
143
|
**示例:**
|
|
145
144
|
|
|
146
145
|
- **基本日志记录:** 记录与 Google Gemini CLI 的会话。
|
|
147
146
|
```bash
|
|
148
|
-
ai-cli-log gemini
|
|
147
|
+
ai-cli-log run gemini
|
|
149
148
|
```
|
|
150
149
|
*日志将保存到 `.ai-cli-log/` 目录中。*
|
|
151
150
|
|
|
152
|
-
- **AI 驱动的文件名:** 使用 AI
|
|
151
|
+
- **AI 驱动的文件名:** 使用 AI 摘要作为日志文件名。`-s` 或 `--with-summary` 选项必须在 `run` 命令**之前**。
|
|
153
152
|
```bash
|
|
154
|
-
ai-cli-log -s <命令> [参数...]
|
|
155
|
-
#
|
|
156
|
-
ai-cli-log --with-summary <命令> [参数...]
|
|
153
|
+
ai-cli-log -s run <命令> [参数...]
|
|
154
|
+
# 或指定一个摘要器
|
|
155
|
+
ai-cli-log --with-summary=gemini-pro run <命令> [参数...]
|
|
157
156
|
```
|
|
158
|
-
|
|
157
|
+
这将使用您默认(或指定)的摘要器生成一个描述性的文件名,例如 `gemini-20250713-153000-fix-database-connection-error.md`。
|
|
159
158
|
|
|
160
159
|
## 配置
|
|
161
160
|
|
|
@@ -167,19 +166,19 @@ ai-cli-log <command> [args...]
|
|
|
167
166
|
|
|
168
167
|
您可以通过手动或使用交互式设置命令来创建这些文件。
|
|
169
168
|
|
|
170
|
-
### 交互式设置 (
|
|
169
|
+
### 交互式设置 (`init`)
|
|
171
170
|
|
|
172
|
-
|
|
171
|
+
`init` 命令可以帮助您创建配置文件。
|
|
173
172
|
|
|
174
173
|
* **创建全局配置文件:**
|
|
175
174
|
```bash
|
|
176
|
-
ai-cli-log
|
|
175
|
+
ai-cli-log init
|
|
177
176
|
```
|
|
178
|
-
|
|
177
|
+
This saves the configuration to `~/.config/ai-cli-log/config.json`.
|
|
179
178
|
|
|
180
179
|
* **创建本地(项目特定)配置文件:**
|
|
181
180
|
```bash
|
|
182
|
-
ai-cli-log
|
|
181
|
+
ai-cli-log init --local
|
|
183
182
|
```
|
|
184
183
|
这会将配置保存到当前目录的 `.ai-cli-log/config.json` 中。
|
|
185
184
|
|
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
|
|
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
|
-
|
|
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,39 @@ function runLoggingSession(command, commandArgs, summaryArg) {
|
|
|
382
386
|
}
|
|
383
387
|
// --- 3. MAIN ENTRY POINT & ARGUMENT PARSER ---
|
|
384
388
|
function main() {
|
|
385
|
-
const
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
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 [summarizer]', 'Enable AI summary for the session. Optionally specify a summarizer.');
|
|
397
|
+
program
|
|
398
|
+
.command('init')
|
|
399
|
+
.description('Initialize or update the configuration file.')
|
|
400
|
+
.option('--local', 'Create the configuration file in the current directory\'s .ai-cli-log folder.', false)
|
|
401
|
+
.action((options) => {
|
|
402
|
+
handleInitCommand(options.local);
|
|
403
|
+
});
|
|
404
|
+
program
|
|
405
|
+
.command('run')
|
|
406
|
+
.usage('<command> [args...]')
|
|
407
|
+
.description("Run a command and log the session. Any options for ai-cli-log itself (like -s) must come before the 'run' command.")
|
|
408
|
+
.argument('<command>', 'The command to execute and log.')
|
|
409
|
+
.argument('[args...]', 'Arguments for the command.')
|
|
410
|
+
.allowUnknownOption()
|
|
411
|
+
.action((command, args) => {
|
|
412
|
+
const options = program.opts();
|
|
413
|
+
let summaryArg = false;
|
|
414
|
+
if (options.withSummary) {
|
|
415
|
+
summaryArg = typeof options.withSummary === 'string' ? options.withSummary : true;
|
|
416
|
+
}
|
|
417
|
+
runLoggingSession(command, args, summaryArg);
|
|
418
|
+
});
|
|
419
|
+
program.parse(process.argv);
|
|
420
|
+
if (!process.argv.slice(2).length) {
|
|
421
|
+
program.help();
|
|
412
422
|
}
|
|
413
|
-
runLoggingSession(command, commandArgs, summaryArg);
|
|
414
423
|
}
|
|
415
424
|
main();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ai-cli-log",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.6",
|
|
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
|
|
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
|
-
|
|
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,45 @@ function runLoggingSession(command: string, commandArgs: string[], summaryArg?:
|
|
|
399
404
|
// --- 3. MAIN ENTRY POINT & ARGUMENT PARSER ---
|
|
400
405
|
|
|
401
406
|
function main() {
|
|
402
|
-
const
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
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 [summarizer]', 'Enable AI summary for the session. Optionally specify a summarizer.');
|
|
416
|
+
|
|
417
|
+
program
|
|
418
|
+
.command('init')
|
|
419
|
+
.description('Initialize or update the configuration file.')
|
|
420
|
+
.option('--local', 'Create the configuration file in the current directory\'s .ai-cli-log folder.', false)
|
|
421
|
+
.action((options) => {
|
|
422
|
+
handleInitCommand(options.local);
|
|
423
|
+
});
|
|
410
424
|
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
425
|
+
program
|
|
426
|
+
.command('run')
|
|
427
|
+
.usage('<command> [args...]')
|
|
428
|
+
.description("Run a command and log the session. Any options for ai-cli-log itself (like -s) must come before the 'run' command.")
|
|
429
|
+
.argument('<command>', 'The command to execute and log.')
|
|
430
|
+
.argument('[args...]', 'Arguments for the command.')
|
|
431
|
+
.allowUnknownOption()
|
|
432
|
+
.action((command, args) => {
|
|
433
|
+
const options = program.opts();
|
|
434
|
+
let summaryArg: string | boolean = false;
|
|
435
|
+
if (options.withSummary) {
|
|
436
|
+
summaryArg = typeof options.withSummary === 'string' ? options.withSummary : true;
|
|
437
|
+
}
|
|
438
|
+
runLoggingSession(command, args, summaryArg);
|
|
439
|
+
});
|
|
416
440
|
|
|
417
|
-
|
|
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
|
-
}
|
|
441
|
+
program.parse(process.argv);
|
|
434
442
|
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
summaryArg = summaryArgRaw.includes('=') ? summaryArgRaw.split('=')[1] : true;
|
|
443
|
+
if (!process.argv.slice(2).length) {
|
|
444
|
+
program.help();
|
|
438
445
|
}
|
|
439
|
-
|
|
440
|
-
runLoggingSession(command, commandArgs, summaryArg);
|
|
441
446
|
}
|
|
442
447
|
|
|
443
|
-
main();
|
|
448
|
+
main();
|