@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 +465 -0
- package/bin/ses.js +85 -0
- package/lib/agent-review.js +722 -0
- package/lib/checkpoint.js +320 -0
- package/lib/checkpoints.js +54 -0
- package/lib/clean.js +45 -0
- package/lib/commit.js +60 -0
- package/lib/config.js +28 -0
- package/lib/disable.js +152 -0
- package/lib/doctor.js +307 -0
- package/lib/enable.js +294 -0
- package/lib/explain.js +212 -0
- package/lib/extract.js +265 -0
- package/lib/git-shadow.js +136 -0
- package/lib/init.js +83 -0
- package/lib/list.js +62 -0
- package/lib/log.js +77 -0
- package/lib/prompts.js +125 -0
- package/lib/query.js +110 -0
- package/lib/redact.js +170 -0
- package/lib/report.js +296 -0
- package/lib/reset.js +122 -0
- package/lib/resume.js +224 -0
- package/lib/review-common.js +100 -0
- package/lib/review.js +652 -0
- package/lib/rewind.js +198 -0
- package/lib/session.js +225 -0
- package/lib/shadow.js +51 -0
- package/lib/status.js +198 -0
- package/lib/summarize.js +315 -0
- package/lib/view.js +50 -0
- package/lib/webhook.js +224 -0
- package/package.json +41 -0
package/README.md
ADDED
|
@@ -0,0 +1,465 @@
|
|
|
1
|
+
[](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
|
+
}
|