@claudemini/ses-cli 1.4.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/README.md ADDED
@@ -0,0 +1,465 @@
1
+ [![Typing SVG](https://readme-typing-svg.herokuapp.com?font=Fira+Code&weight=600&size=32&pause=1000&color=4EA7F7&width=435&lines=Session+Event+Sanpshot;Remember+what+your+AI+did)](https://git.io/typing-svg)
2
+
3
+
4
+ A memory system for human-AI coding sessions. Tracks what happened, classifies intent and risk, and provides structured data for code review automation.
5
+
6
+ Supports **Claude Code**, **Gemini CLI**, **Cursor**, and **OpenCode**.
7
+
8
+ ## Quick Start
9
+
10
+ ```bash
11
+ npm install -g @claudemini/ses-cli
12
+
13
+ cd /path/to/your/project
14
+ ses enable # Setup hooks + .ses-logs
15
+ # ... use Claude Code normally ...
16
+ ses list # See sessions
17
+ ses status # Check current session
18
+ ```
19
+
20
+ ## Installation
21
+
22
+ ```bash
23
+ npm install -g @claudemini/ses-cli
24
+ ```
25
+
26
+ Or use directly without installing:
27
+
28
+ ```bash
29
+ npx @claudemini/ses-cli <command>
30
+ ```
31
+
32
+ ## Commands
33
+
34
+ ### Setup
35
+
36
+ ```bash
37
+ ses enable # Enable for Claude Code (default)
38
+ ses enable gemini-cli # Enable for Gemini CLI
39
+ ses enable --all # Enable for all supported agents
40
+ ses enable --checkpoint # Also create checkpoints on git commit
41
+ ses disable # Remove hooks (keep data)
42
+ ses disable --clean # Remove hooks and all data
43
+ ses init # Low-level: register hooks in .claude/settings.json
44
+ ```
45
+
46
+ ### Session Tracking
47
+
48
+ ```bash
49
+ ses status # Show current session + git info
50
+ ses list # List all sessions with type, risk, intent
51
+ ses view <session-id> # View semantic session report
52
+ ses view <session-id> --json # Include raw JSON data
53
+ ses review [session-id] # Run structured code review from session data
54
+ ses review --json # Machine-readable findings (structured schema)
55
+ ses review # goatchain Agent-driven review
56
+ ses review --recent=3 --md # Aggregated Markdown report for PR comments
57
+ ses review --strict --fail-on=medium # CI gate by severity threshold
58
+ ses explain <session-id> # Human-friendly explanation of a session
59
+ ses explain <commit-sha> # Explain a commit via its checkpoint
60
+ ```
61
+
62
+ `ses review` options:
63
+ - `--recent=<n>` review latest `n` sessions (default `1`)
64
+ - `--all` review all sessions in `.ses-logs`
65
+ - `--min-severity=<info|low|medium|high|critical>` filter findings
66
+ - `--fail-on=<info|low|medium|high|critical>` strict-mode failure threshold (default `high`)
67
+ - `--agent-timeout-ms=<ms>` total timeout for the review agent (default: 60s base + 30s per session)
68
+ - `--allow-worktree-diff` allow worktree fallback diff when checkpoint commits are unavailable
69
+ - `--agent-auto-approve=<bool>` auto approve agent tool calls (default `true`)
70
+ - `--no-agent-auto-approve` disable auto approval for agent tool calls
71
+ - `--agent` deprecated alias (accepted but ignored)
72
+ - `--engine=<name>` deprecated alias (accepted but ignored)
73
+ - `--strict` exit code `1` when findings reach `--fail-on`
74
+ - `--json` output structured JSON
75
+ - `--markdown` / `--md` output Markdown
76
+
77
+ ### Cross-Session Queries
78
+
79
+ ```bash
80
+ ses query --recent=5 # Recent 5 sessions
81
+ ses query --file=src/auth/auth.service.ts # Sessions that modified this file
82
+ ses query --type=bugfix # All bugfix sessions
83
+ ses query --risk=high # High-risk sessions
84
+ ses query --type=feature --json # JSON output for bot consumption
85
+ ```
86
+
87
+ ### Checkpoints & Recovery
88
+
89
+ ```bash
90
+ ses checkpoints # List all checkpoints
91
+ ses commit # Manually create checkpoint for current HEAD
92
+ ses rewind <checkpoint> # Rollback to a checkpoint (git reset --hard)
93
+ ses rewind --interactive # Choose from available checkpoints
94
+ ses resume <checkpoint> # Restore session data from a checkpoint
95
+ ses reset --force # Delete checkpoint for current HEAD
96
+ ```
97
+
98
+ ### Maintenance
99
+
100
+ ```bash
101
+ ses doctor # Diagnose issues (corrupted state, stuck sessions)
102
+ ses doctor --fix # Auto-fix detected issues
103
+ ses shadow # List shadow branches
104
+ ses shadow info <branch> # Show branch details
105
+ ses clean --days=7 --dry-run # Preview cleanup
106
+ ses clean --days=7 # Delete sessions older than 7 days
107
+ ses summarize <session-id> # Generate AI summary (requires API key)
108
+ ```
109
+
110
+ ## Command Reference
111
+
112
+ | Command | Description |
113
+ |---------|-------------|
114
+ | `enable` | Enable ses-cli in repository (multi-agent support) |
115
+ | `disable` | Remove hooks, optionally clean data |
116
+ | `status` | Show current session and git info |
117
+ | `init` | Register hooks in .claude/settings.json |
118
+ | `log <type>` | Log a hook event from stdin (called by hooks) |
119
+ | `list` | List all sessions with type, intent, risk |
120
+ | `view <id>` | View semantic session report |
121
+ | `review [id]` | Run agent-driven code review (goatchain, single or multi-session) |
122
+ | `query` | Query session memory across sessions |
123
+ | `explain <id>` | Human-friendly explanation of a session or commit |
124
+ | `commit` | Create checkpoint on git commit |
125
+ | `checkpoints` | List all checkpoints |
126
+ | `rewind <cp>` | Rollback to a checkpoint |
127
+ | `resume <cp>` | Resume session from a checkpoint |
128
+ | `reset` | Delete checkpoint for current HEAD |
129
+ | `summarize <id>` | Generate AI summary for a session |
130
+ | `doctor` | Diagnose and fix issues |
131
+ | `shadow` | List/inspect shadow branches |
132
+ | `clean` | Clean old sessions |
133
+ | `webhook` | Show/test webhook configuration |
134
+
135
+ ## How It Works
136
+
137
+ ```
138
+ Human <-> AI Agent (Claude Code, Gemini CLI, ...)
139
+ | (hooks)
140
+ Event Ingestion (log.js)
141
+ |
142
+ Semantic Extraction (extract.js)
143
+ |
144
+ Session State (session.js) + Reports (report.js)
145
+ |
146
+ Memory System (.ses-logs/ + index.json)
147
+ |
148
+ Agent Review (goatchain) / Human Queries
149
+ ```
150
+
151
+ 1. **Ingestion** - Hooks fire on every agent event (tool use, prompts, session start/end). Events are appended to `events.jsonl`.
152
+ 2. **Extraction** - Each event updates incremental state. Intent, change categories, and risk are computed using rule-based pattern matching (zero latency, zero cost, fully offline).
153
+ 3. **Reports** - `summary.json` (bot-readable), `summary.txt` (human-readable), `context.md`, `metadata.json`, and `prompts.txt` are regenerated on every event.
154
+ 4. **Checkpoints** - On session end or git commit, session data is committed to an orphan git branch using plumbing commands (no working tree impact).
155
+
156
+ ## Configuration
157
+
158
+ All configuration lives in `.ses-logs/config.json`. Environment variables override file config.
159
+
160
+ ### Full Template
161
+
162
+ ```json
163
+ {
164
+ "provider": "openai",
165
+ "api_key": "sk-...",
166
+ "model": "gpt-4o-mini",
167
+ "openai_base_url": "https://api.openai.com/v1",
168
+ "openai_endpoint": "",
169
+ "max_tokens": 1000,
170
+ "temperature": 0.7,
171
+
172
+ "webhooks": {
173
+ "url": "https://example.com/hook",
174
+ "events": ["session.ended", "review.completed"],
175
+ "secret": "",
176
+ "auth_token": "",
177
+ "headers": {},
178
+ "timeout_ms": 5000,
179
+ "retry": 1
180
+ },
181
+
182
+ "env": {
183
+ "SES_WEBHOOK_URL": "",
184
+ "SES_WEBHOOK_SECRET": "",
185
+ "SES_WEBHOOK_EVENTS": ""
186
+ }
187
+ }
188
+ ```
189
+
190
+ ### Fields
191
+
192
+ | Field | Description | Default |
193
+ |-------|-------------|---------|
194
+ | `provider` | `"openai"` or `"anthropic"` | `"openai"` |
195
+ | `api_key` | API key for the provider | — |
196
+ | `model` | Model ID for summarize / review | `"gpt-4o-mini"` |
197
+ | `openai_base_url` | OpenAI-compatible base URL | `"https://api.openai.com/v1"` |
198
+ | `openai_endpoint` | Full endpoint URL (overrides `openai_base_url`) | — |
199
+ | `max_tokens` | Max tokens for AI summary | `1000` |
200
+ | `temperature` | Temperature for AI summary | `0.7` |
201
+ | `webhooks` | Webhook configuration object (see [Webhook](#webhook)) | — |
202
+ | `env` | Environment variable overrides (lower priority than real env vars) | — |
203
+
204
+ ### Minimal Examples
205
+
206
+ **OpenAI-compatible provider** (e.g. MiniMax, DeepSeek, Together):
207
+
208
+ ```json
209
+ {
210
+ "provider": "openai",
211
+ "api_key": "sk-...",
212
+ "model": "your-model-id",
213
+ "openai_base_url": "https://api.your-provider.com/v1"
214
+ }
215
+ ```
216
+
217
+ **Anthropic**:
218
+
219
+ ```json
220
+ {
221
+ "provider": "anthropic",
222
+ "api_key": "sk-ant-...",
223
+ "model": "claude-3-haiku-20240307"
224
+ }
225
+ ```
226
+
227
+ **With webhook**:
228
+
229
+ ```json
230
+ {
231
+ "provider": "openai",
232
+ "api_key": "sk-...",
233
+ "model": "gpt-4o-mini",
234
+ "webhooks": {
235
+ "url": "https://hooks.slack.com/services/xxx",
236
+ "events": ["session.ended", "review.completed"]
237
+ }
238
+ }
239
+ ```
240
+
241
+ ## Data Model
242
+
243
+ ### Session Directory
244
+
245
+ ```
246
+ .ses-logs/
247
+ ├── index.json # Cross-session index
248
+ └── <session-id>/
249
+ ├── events.jsonl # Raw hook events
250
+ ├── state.json # Incremental processing state
251
+ ├── summary.json # Bot data interface (v2)
252
+ ├── summary.txt # Human-readable report
253
+ ├── context.md # Session context (Entire-style)
254
+ ├── prompts.txt # User prompts with timestamps
255
+ ├── metadata.json # Lightweight session metadata
256
+ └── ai-summary.md # AI-generated summary (optional)
257
+ ```
258
+
259
+ ### summary.json v2
260
+
261
+ ```json
262
+ {
263
+ "version": "2.0",
264
+ "session": {
265
+ "id": "f608c31e...",
266
+ "start": "2026-02-27T10:00:00Z",
267
+ "end": "2026-02-27T10:45:00Z",
268
+ "duration_minutes": 45,
269
+ "type": "bugfix",
270
+ "intent": "Fix authentication timeout issue",
271
+ "risk": "medium",
272
+ "summary": "Fixed: Fix authentication timeout issue"
273
+ },
274
+ "changes": {
275
+ "files": [{ "path": "src/auth.ts", "category": "source", "operations": ["edit"] }],
276
+ "summary": { "source": 3, "test": 1 }
277
+ },
278
+ "activity": {
279
+ "tools": { "Read": 15, "Edit": 3, "Bash": 5 },
280
+ "commands": { "test": ["npm run test"], "git": ["git status"] },
281
+ "errors": []
282
+ },
283
+ "review_hints": {
284
+ "tests_run": true,
285
+ "build_verified": false,
286
+ "files_without_tests": ["src/auth.ts"],
287
+ "large_change": false,
288
+ "config_changed": false,
289
+ "migration_added": false
290
+ },
291
+ "prompts": [{ "time": "...", "text": "Fix the auth timeout bug" }],
292
+ "scope": ["auth"]
293
+ }
294
+ ```
295
+
296
+ ## Session Types
297
+
298
+ | Type | Description |
299
+ |------|-------------|
300
+ | `bugfix` | Bug fixes |
301
+ | `feature` | New features |
302
+ | `refactor` | Code restructuring |
303
+ | `debug` | Investigation/debugging |
304
+ | `test` | Test writing/updates |
305
+ | `docs` | Documentation |
306
+ | `devops` | CI/CD, deployment |
307
+ | `upgrade` | Dependency updates |
308
+ | `config` | Configuration changes |
309
+ | `style` | Formatting, UI |
310
+ | `security` | Security-related |
311
+ | `perf` | Performance optimization |
312
+
313
+ ## Risk Levels
314
+
315
+ - **low** - Few files, no config/migration changes, tests run
316
+ - **medium** - Multiple files, some config changes
317
+ - **high** - Many files (>10), migration changes, infra changes without tests
318
+
319
+ ## Bot Integration
320
+
321
+ ```javascript
322
+ import { readFileSync } from 'fs';
323
+
324
+ // Read session data
325
+ const summary = JSON.parse(readFileSync('.ses-logs/<id>/summary.json', 'utf-8'));
326
+
327
+ // Check review hints
328
+ if (!summary.review_hints.tests_run && summary.changes.files.length > 0) {
329
+ review.warn('Files modified but no tests run');
330
+ }
331
+ if (summary.review_hints.migration_added) {
332
+ review.flag('Database migration requires careful review');
333
+ }
334
+
335
+ // Query file history via index
336
+ const index = JSON.parse(readFileSync('.ses-logs/index.json', 'utf-8'));
337
+ const history = index.file_history['src/auth/auth.service.ts'];
338
+ if (history && history.length > 3) {
339
+ review.note('This file has been modified frequently');
340
+ }
341
+ ```
342
+
343
+ ## Webhook
344
+
345
+ ses-cli can send webhook notifications to external systems (Slack, Lark, CI, custom platforms) when key events occur.
346
+
347
+ ### Events
348
+
349
+ | Event | Trigger | Payload |
350
+ |-------|---------|---------|
351
+ | `session.ended` | Session ends (hook `session-end` / `stop`) | `summary.json` content |
352
+ | `review.completed` | `ses review` finishes | Review report |
353
+
354
+ ### Configuration
355
+
356
+ Webhook supports three configuration sources (highest priority first):
357
+
358
+ **1. Environment variables** (highest priority):
359
+
360
+ ```bash
361
+ export SES_WEBHOOK_URL=https://example.com/hook
362
+ export SES_WEBHOOK_SECRET=my-secret # HMAC-SHA256 signing
363
+ export SES_WEBHOOK_AUTH_TOKEN=bearer-token # Bearer auth (alternative to secret)
364
+ export SES_WEBHOOK_EVENTS=session.ended,review.completed
365
+ ```
366
+
367
+ **2. `.ses-logs/config.json` `env` field**:
368
+
369
+ ```json
370
+ {
371
+ "env": {
372
+ "SES_WEBHOOK_URL": "https://example.com/hook",
373
+ "SES_WEBHOOK_SECRET": "my-secret",
374
+ "SES_WEBHOOK_EVENTS": "session.ended,review.completed"
375
+ }
376
+ }
377
+ ```
378
+
379
+ **3. `.ses-logs/config.json` `webhooks` field** (lowest priority):
380
+
381
+ ```json
382
+ {
383
+ "webhooks": {
384
+ "url": "https://example.com/hook",
385
+ "events": ["session.ended", "review.completed"],
386
+ "secret": "hmac-secret-key",
387
+ "headers": { "X-Custom": "value" },
388
+ "timeout_ms": 5000,
389
+ "retry": 1
390
+ }
391
+ }
392
+ ```
393
+
394
+ ### Authentication
395
+
396
+ - **HMAC-SHA256** — Set `secret` or `SES_WEBHOOK_SECRET`. Adds `X-Signature-256: sha256=<hex>` header (GitHub-compatible format).
397
+ - **Bearer token** — Set `auth_token` or `SES_WEBHOOK_AUTH_TOKEN`. Adds `Authorization: Bearer <token>` header.
398
+ - If neither is set, requests are sent without authentication.
399
+
400
+ ### Payload Format
401
+
402
+ ```json
403
+ {
404
+ "event": "session.ended",
405
+ "timestamp": "2026-03-03T12:00:00.000Z",
406
+ "payload": { ... }
407
+ }
408
+ ```
409
+
410
+ ### Commands
411
+
412
+ ```bash
413
+ ses webhook # Show current webhook configuration
414
+ ses webhook --test # Send a test ping to the configured URL
415
+ ```
416
+
417
+ ## AI Summary
418
+
419
+ Set one of these environment variables to enable AI-powered session summaries:
420
+
421
+ ```bash
422
+ export OPENAI_API_KEY=sk-... # Uses gpt-4o-mini by default
423
+ export OPENAI_BASE_URL=https://api.openai.com/v1 # Optional: OpenAI-compatible base URL
424
+ export AI_MODEL=gpt-5-mini # Optional: universal model override (all providers)
425
+ export ANTHROPIC_API_KEY=sk-... # Uses claude-3-haiku by default
426
+ ```
427
+
428
+ Then run:
429
+ ```bash
430
+ ses summarize <session-id>
431
+ ```
432
+
433
+ ## Environment Variables
434
+
435
+ | Variable | Description |
436
+ |----------|-------------|
437
+ | `SES_LOG_DIR` | Custom log directory (default: `.ses-logs` in project root) |
438
+ | `OPENAI_API_KEY` | Enable AI summaries via OpenAI |
439
+ | `OPENAI_BASE_URL` | OpenAI-compatible base URL for summaries (default: `https://api.openai.com/v1`) |
440
+ | `OPENAI_ENDPOINT` | Full OpenAI-compatible endpoint (overrides `OPENAI_BASE_URL`) |
441
+ | `AI_MODEL` | Universal model override for summaries (applies to all providers) |
442
+ | `OPENAI_MODEL` | OpenAI-only model override (takes precedence over `AI_MODEL` for OpenAI) |
443
+ | `ANTHROPIC_API_KEY` | Enable AI summaries via Anthropic |
444
+ | `ANTHROPIC_MODEL` | Anthropic-only model override (takes precedence over `AI_MODEL` for Anthropic) |
445
+ | `SES_REVIEW_AGENT_TIMEOUT_MS` | Agent review timeout in milliseconds (default: 60s base + 30s per session) |
446
+ | `SES_REVIEW_AUTO_APPROVE` | Auto approve agent tool calls (`true`/`false`, default: `true`) |
447
+ | `SES_WEBHOOK_URL` | Webhook endpoint URL |
448
+ | `SES_WEBHOOK_SECRET` | HMAC-SHA256 signing secret for webhooks |
449
+ | `SES_WEBHOOK_AUTH_TOKEN` | Bearer token for webhook authentication |
450
+ | `SES_WEBHOOK_EVENTS` | Comma-separated list of webhook events to subscribe to |
451
+
452
+ `ses summarize` also accepts OpenAI-compatible responses where completion text is returned via `reasoning_content` instead of `content`.
453
+
454
+ ## Security
455
+
456
+ - Session logs are stored locally in `.ses-logs/` (added to `.gitignore` automatically)
457
+ - Secrets (API keys, tokens, passwords) are automatically redacted when writing to shadow branches
458
+ - Checkpoint data uses git plumbing commands — no impact on your working tree
459
+
460
+ ## Acknowledgements
461
+
462
+ Special thanks to [goatchain](https://www.npmjs.com/package/goatchain) for powering the agent-driven review workflow in `ses review`.
463
+
464
+ ## License
465
+
package/bin/ses.js ADDED
@@ -0,0 +1,85 @@
1
+ #!/usr/bin/env node
2
+
3
+ const args = process.argv.slice(2);
4
+ const command = args[0];
5
+
6
+ const commands = {
7
+ enable: 'Enable ses-cli in repository',
8
+ disable: 'Remove ses-cli hooks',
9
+ status: 'Show current session status',
10
+ init: 'Initialize hooks in .claude/settings.json',
11
+ log: 'Log a hook event (called by hooks)',
12
+ commit: 'Create checkpoint on git commit (hook)',
13
+ list: 'List all sessions',
14
+ checkpoints: 'List all checkpoints',
15
+ view: 'View session details',
16
+ review: 'Run structured code review for a session',
17
+ query: 'Query session memory (cross-session)',
18
+ explain: 'Explain a session or commit',
19
+ summarize: 'Generate AI summary for a session',
20
+ rewind: 'Rollback to previous checkpoint',
21
+ resume: 'Resume session from checkpoint',
22
+ reset: 'Delete checkpoint for current HEAD',
23
+ doctor: 'Fix or clean stuck sessions',
24
+ shadow: 'List shadow branches',
25
+ clean: 'Clean old sessions',
26
+ webhook: 'Manage webhook configuration',
27
+ help: 'Show help',
28
+ };
29
+
30
+ function showHelp() {
31
+ console.log('ses-cli - Session Hook Intelligence Tracker\n');
32
+ console.log('Usage: ses <command> [options]\n');
33
+ console.log('Commands:');
34
+ Object.entries(commands).forEach(([cmd, desc]) => {
35
+ console.log(` ${cmd.padEnd(10)} ${desc}`);
36
+ });
37
+ console.log('\nExamples:');
38
+ console.log(' ses enable # Enable ses-cli in repo');
39
+ console.log(' ses status # Show current session');
40
+ console.log(' ses list # List sessions');
41
+ console.log(' ses view <session-id> # View session');
42
+ console.log(' ses review [session-id] # Structured code review');
43
+ console.log(' ses review --recent=3 --md # Markdown review for latest 3 sessions');
44
+ console.log(' ses rewind <checkpoint> # Rollback to checkpoint');
45
+ console.log(' ses resume <checkpoint> # Resume from checkpoint');
46
+ console.log(' ses doctor --fix # Fix stuck sessions');
47
+ console.log(' ses query --recent=5 # Recent 5 sessions');
48
+ console.log(' ses query --file=src/app.ts # Sessions that touched file');
49
+ console.log(' ses shadow # List shadow branches');
50
+ console.log(' ses disable --clean # Remove ses-cli and data');
51
+ }
52
+
53
+ if (!command || command === 'help' || command === '--help') {
54
+ showHelp();
55
+ process.exit(0);
56
+ }
57
+
58
+ if (command === '--version' || command === '-v') {
59
+ const { readFileSync } = await import('fs');
60
+ const { fileURLToPath } = await import('url');
61
+ const { dirname, join } = await import('path');
62
+ const __dirname = dirname(fileURLToPath(import.meta.url));
63
+ const pkg = JSON.parse(readFileSync(join(__dirname, '..', 'package.json'), 'utf-8'));
64
+ console.log(`ses-cli v${pkg.version}`);
65
+ process.exit(0);
66
+ }
67
+
68
+ if (!Object.prototype.hasOwnProperty.call(commands, command)) {
69
+ console.error(`Unknown command: ${command}`);
70
+ process.exit(1);
71
+ }
72
+
73
+ try {
74
+ const mod = await import(`../lib/${command}.js`);
75
+ if (typeof mod.default !== 'function') {
76
+ throw new Error(`Command module "${command}" has no default function export`);
77
+ }
78
+ const exitCode = await mod.default(args.slice(1));
79
+ if (Number.isInteger(exitCode) && exitCode !== 0) {
80
+ process.exitCode = exitCode;
81
+ }
82
+ } catch (error) {
83
+ console.error(`Failed to run command "${command}": ${error.message}`);
84
+ process.exit(1);
85
+ }