agentel 0.2.5 → 0.2.8

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.
@@ -77,6 +77,13 @@ without a specific archived model group as `claude-unknown`, because the model
77
77
  family is still known. Favorite-model stats still use known archived model
78
78
  metadata.
79
79
 
80
+ SDK source types (`codex-sdk-history` and `claude-sdk-history`) are excluded from
81
+ the primary stats totals, daily activity, streaks, folder rankings, and
82
+ provider/model/company charts by default. The stats payload still exposes their
83
+ own SDK aggregate fields plus `split_stats.sdk`, and the web view renders an SDK
84
+ jobs card and heatmap. This keeps high-volume batch automation searchable and
85
+ auditable without letting it swamp interactive usage stats.
86
+
80
87
  Cursor sessions that still lack provider-reported usage get a separate
81
88
  `estimatedUsage` metadata field instead of synthetic `usage`. The estimate uses
82
89
  empirical per-assistant-turn Cursor rates by model family, with visible
@@ -88,15 +95,20 @@ split as non-assistant input, assistant output, and Claude thinking output, not
88
95
  reconstructed billing context windows.
89
96
 
90
97
  ```sh
91
- agentlog update --yes --since all
98
+ agentlog update --yes
92
99
  ```
93
100
 
94
101
  `agentlog update` preserves config preferences, redaction settings, web account
95
- labels, source histories, and recall integrations. It removes derived local
96
- archive/import/index state and reimports configured local sources. Manual web
97
- exports still need to be imported again from the original export file when those
98
- archives need to be rebuilt. `agentlog reset` is the heavier path: it removes
99
- agentlog state and archive objects, including config, while still leaving source
102
+ labels, manually imported ChatGPT/Claude.ai archive objects, source histories,
103
+ and recall integrations. It removes derived local agent archive/import/index
104
+ state and reimports configured local sources. The default rebuild window is
105
+ `imports.updateSince`, saved from the initial backfill or explicit all-source
106
+ imports, falling back to `all` for legacy configs. The watcher's rolling
107
+ `imports.defaultSinceDays` is not used by `agentlog update`; `--since` still
108
+ overrides it for one run. Manual web exports only need to be
109
+ imported again from the original export file when those chat archives themselves
110
+ need to be rebuilt. `agentlog reset` is the heavier path: it removes agentlog
111
+ state and archive objects, including config, while still leaving source
100
112
  application histories such as Cursor, Codex, Claude, Gemini, or Devin logs
101
113
  untouched.
102
114
 
@@ -130,7 +142,7 @@ agentlog does not blindly copy entire source directories.
130
142
  ## Canonical Events
131
143
 
132
144
  `events.jsonl` is the provider-independent archive/search substrate. It uses
133
- schema version `agentlog.events.v1` and these event kinds:
145
+ schema version `agentlog.events.v2` and these event kinds:
134
146
 
135
147
  - `session.started`
136
148
  - `prompt.submitted`
@@ -150,9 +162,14 @@ events add viewer-facing display metadata:
150
162
  - `metadata.toolCalls[]`: `id`, `name`, `displayName`, `category`, `title`,
151
163
  `status`, `argument`, `rawInputSummary`, `inputPreview`, `target`, `icon`,
152
164
  `categoryLabel`, and `provider`.
153
- - `metadata.toolResult`: `provider`, `kind`, `title`, `summary`, `output`,
154
- `lineCount`, `collapsed`, `category`, `categoryLabel`, `icon`, and optional
155
- `status`.
165
+ - `metadata.toolResult`: `id`, `name`, `provider`, `kind`, `title`, `summary`,
166
+ `output`, `lineCount`, `collapsed`, `category`, `categoryLabel`, `icon`, and
167
+ optional `status`.
168
+
169
+ `tool.completed.parentEventId` links to the matching `tool.called` event when a
170
+ provider exposes stable ids or matching tool names. When those are absent,
171
+ canonical event derivation falls back to the next unmatched tool call so streams
172
+ such as Devin CLI still preserve the call/result relationship.
156
173
 
157
174
  The viewer reads canonical events or normalized metadata first. Text patterns
158
175
  such as `Grep(...)` are legacy fallback only.
@@ -183,35 +200,36 @@ package-prefixed scheme.
183
200
 
184
201
  | Source type | Version |
185
202
  | --- | --- |
186
- | `codex-cli-history` | `0.2.5.0` |
187
- | `codex-desktop-history` | `0.2.5.0` |
188
- | `cli-history` | `0.2.5.0` |
189
- | `claude-sdk-history` | `0.2.5.0` |
190
- | `claude-code-desktop-metadata` | `0.2.5.0` |
191
- | `claude-workspace-desktop` | `0.2.5.0` |
192
- | `cursor-workspace-sqlite` | `0.2.5.0` |
193
- | `cursor-global-sqlite` | `0.2.5.0` |
194
- | `cursor-raw-sqlite-salvage` | `0.2.5.0` |
195
- | `cursor-agent-transcripts` | `0.2.5.0` |
196
- | `devin-cli-history` | `0.2.5.0` |
197
- | `gemini-cli-history` | `0.2.5.0` |
198
- | `cline-task-history` | `0.2.5.0` |
199
- | `opencode-cli-history` | `0.2.5.0` |
200
- | `opencode-cli-sqlite-history` | `0.2.5.0` |
201
- | `opencode-desktop-history` | `0.2.5.0` |
202
- | `opencode-desktop-sqlite-history` | `0.2.5.0` |
203
- | `opencode-web-sqlite-history` | `0.2.5.0` |
204
- | `opencode-history` | `0.2.5.0` |
205
- | `opencode-sqlite-history` | `0.2.5.0` |
206
- | `aider-chat-history` | `0.2.5.0` |
207
- | `antigravity-history` | `0.2.5.0` |
208
- | `antigravity-trajectory-summary` | `0.2.5.0` |
209
- | `windsurf-trajectory-export` | `0.2.5.0` |
210
- | `web-chat-export` | `0.2.5.0` |
211
- | `chatgpt-export` | `0.2.5.0` |
212
- | `claude-web-export` | `0.2.5.0` |
213
- | `claude-web-memory` | `0.2.5.0` |
214
- | `import` | `0.2.5.0` |
203
+ | `codex-cli-history` | `0.2.8.0` |
204
+ | `codex-desktop-history` | `0.2.8.0` |
205
+ | `codex-sdk-history` | `0.2.8.0` |
206
+ | `cli-history` | `0.2.8.0` |
207
+ | `claude-sdk-history` | `0.2.8.0` |
208
+ | `claude-code-desktop-metadata` | `0.2.8.0` |
209
+ | `claude-workspace-desktop` | `0.2.8.0` |
210
+ | `cursor-workspace-sqlite` | `0.2.8.0` |
211
+ | `cursor-global-sqlite` | `0.2.8.0` |
212
+ | `cursor-raw-sqlite-salvage` | `0.2.8.0` |
213
+ | `cursor-agent-transcripts` | `0.2.8.0` |
214
+ | `devin-cli-history` | `0.2.8.0` |
215
+ | `gemini-cli-history` | `0.2.8.0` |
216
+ | `cline-task-history` | `0.2.8.0` |
217
+ | `opencode-cli-history` | `0.2.8.0` |
218
+ | `opencode-cli-sqlite-history` | `0.2.8.0` |
219
+ | `opencode-desktop-history` | `0.2.8.0` |
220
+ | `opencode-desktop-sqlite-history` | `0.2.8.0` |
221
+ | `opencode-web-sqlite-history` | `0.2.8.0` |
222
+ | `opencode-history` | `0.2.8.0` |
223
+ | `opencode-sqlite-history` | `0.2.8.0` |
224
+ | `aider-chat-history` | `0.2.8.0` |
225
+ | `antigravity-history` | `0.2.8.0` |
226
+ | `antigravity-trajectory-summary` | `0.2.8.0` |
227
+ | `windsurf-trajectory-export` | `0.2.8.0` |
228
+ | `web-chat-export` | `0.2.8.0` |
229
+ | `chatgpt-export` | `0.2.8.0` |
230
+ | `claude-web-export` | `0.2.8.0` |
231
+ | `claude-web-memory` | `0.2.8.0` |
232
+ | `import` | `0.2.8.0` |
215
233
 
216
234
  `cursor-sqlite-history` and `antigravity-brain` are compatibility aliases for
217
235
  older labels. Fingerprints include the parser version prefix, so changing the
@@ -249,7 +267,7 @@ real-world query should reliably find a representative archived session.
249
267
 
250
268
  The setup UI, import defaults, and history source filters use this grouped order:
251
269
 
252
- 1. OpenAI: Codex CLI, Codex Desktop, ChatGPT
270
+ 1. OpenAI: Codex CLI, Codex Desktop, Codex SDK jobs, ChatGPT
253
271
  2. Anthropic: Claude Code CLI, Claude Code Desktop, Claude Workspace,
254
272
  Claude.ai, Claude SDK jobs
255
273
  3. Google: Gemini CLI, Antigravity
@@ -260,10 +278,10 @@ The setup UI, import defaults, and history source filters use this grouped order
260
278
  `src/sources.js`: `codex-cli`, `codex-desktop`, `claude`,
261
279
  `claude-code-desktop`, `claude-workspace`, `gemini-cli`, `antigravity`,
262
280
  `devin-cli`, `cursor`, `cline`, `opencode-cli`, `opencode-desktop`,
263
- `opencode-web`, `aider`. Claude SDK jobs are
264
- intentionally opt-in. Windsurf local cache scanning is disabled for now because
265
- current Cascade transcripts are encrypted binary stores, but downloaded
266
- trajectory Markdown exports are importable with an explicit path.
281
+ `opencode-web`, `aider`. Codex SDK jobs and Claude SDK jobs are intentionally
282
+ opt-in. Windsurf local cache scanning is disabled for now because current
283
+ Cascade transcripts are encrypted binary stores, but downloaded trajectory
284
+ Markdown exports are importable with an explicit path.
267
285
 
268
286
  The background watcher polls the watcher source list selected near the end of
269
287
  `agentlog init`. New configs still support `imports.autoDiscoverSources=true`,
@@ -327,6 +345,7 @@ stable local command for the archived source.
327
345
  | --- | --- | --- |
328
346
  | Codex CLI | `codex resume <session-id>` | Uses the Codex thread id from `~/.codex/state_5.sqlite`. |
329
347
  | Codex Desktop | `codex resume <session-id>` | Uses the same Codex thread id. Codex decides whether the resumed session opens in the terminal flow. |
348
+ | Codex SDK jobs | No interactive resume command. | These are Codex `exec`/SDK-style batch runs. |
330
349
  | Claude Code CLI | `claude -r <session-id>` | Uses the Claude Code JSONL session id. |
331
350
  | Devin CLI | `devin -r <session-id>` | agentlog archives these as `devin-<session-id>` and strips that prefix for the resume command, for example `devin -r selective-lotus`. |
332
351
  | Claude Code Desktop | No stable local resume command known. | Use Claude's own desktop/history surface or `agentlog show <session-id>`. |
@@ -346,29 +365,72 @@ stable local command for the archived source.
346
365
  - Import selector: `codex-cli`
347
366
  - Provider: `codex`
348
367
  - Source type: `codex-cli-history`
349
- - Primary store: `~/.codex/state_5.sqlite`
368
+ - Primary stores: `~/.codex/state_5.sqlite` and
369
+ `~/.codex/session_index.jsonl`
350
370
  - Session files: rollout paths referenced by the `threads` table, plus
351
371
  unindexed `rollout-*.jsonl` files under `sessions` and `archived_sessions`
352
372
  - Source split: `threads.source = "cli"`
353
373
  - Overrides:
354
374
  - `CODEX_STATE_DB` overrides the state database path.
375
+ - `CODEX_SESSION_INDEX` overrides the session index path.
355
376
  - `CODEX_HOME` is used for the fallback sessions root.
356
377
 
357
378
  The importer reads `id`, `rollout_path`, `created_at`, `updated_at`, `source`,
358
- `cwd`, and `title` from the Codex state database using `sqlite3`. When the
359
- database has the newer `stage1_outputs` table, agentlog also reads
379
+ `cwd`, `title`, and available subagent metadata columns from the Codex state
380
+ database using `sqlite3`. It also reads `thread_spawn_edges` when present. It then
381
+ prefers `~/.codex/session_index.jsonl` when a matching `thread_name` entry is
382
+ present, because Codex Desktop can now keep the sidebar title there while
383
+ leaving `threads.title` as the full first prompt. If the index has no title for
384
+ a session, the parser falls back to the rollout `thread_name_updated` event
385
+ when Codex emits one, then to non-prompt-shaped state titles and finally to
386
+ first-user-message inference. When a prompt starts with `$agentlog-recall` and
387
+ then continues with a separate task paragraph, fallback title inference skips
388
+ the recall lookup line and titles the session from the task body. If existing
389
+ Codex archives show long context titles, recall-query titles, or stale first
390
+ prompts instead of the Codex sidebar title, reimport them with
391
+ `agentlog import --source codex-desktop --since all` or
392
+ `agentlog import --source codex-cli --since all`. When the database has the
393
+ newer `stage1_outputs` table, agentlog also reads
360
394
  `rollout_summary` and `raw_memory` as supplementary Codex summary documents and
361
395
  adds them to the archived transcript. The importer also scans
362
396
  `~/.codex/sessions` and `~/.codex/archived_sessions` for `rollout-*.jsonl` and
363
397
  `rollout-*.jsonl.zst` files that are not referenced by the state database, so
364
398
  older archived rollouts still get backed up.
365
399
 
400
+ Codex subagents are stored as ordinary rollout threads whose `threads.source`
401
+ can be a JSON `subagent.thread_spawn` object, with parent/child relationships in
402
+ `thread_spawn_edges` and optional `agent_nickname`, `agent_role`, and
403
+ `agent_path` columns. Agentlog resolves those rows back to the parent's source
404
+ split (`codex-cli-history`, `codex-desktop-history`, or `codex-sdk-history`),
405
+ imports each child as `conversationKind = "codex_subagent"` with
406
+ `parentComposerId` set to the parent thread id, and attaches compact run
407
+ metadata to the parent as `metadata.sessionSummary.codexSubagentRuns`. The web
408
+ viewer renders those runs inline and opens the child transcript in the same
409
+ subagent modal used for Claude Code. Existing Codex archives need a full
410
+ reimport, for example `agentlog import --source codex-desktop --since all`, to
411
+ gain the child-session links.
412
+
366
413
  The rollout JSONL parser captures readable `response_item` reasoning summaries,
367
414
  Codex `event_msg` assistant/user messages, task and compaction markers, local
368
415
  shell calls, web search calls, custom tool calls such as `apply_patch`, tool
369
416
  outputs, and token-count usage deltas. Shell calls that run `apply_patch`
370
417
  through a heredoc are promoted to edit tool calls with `patch`, `diff`, and
371
- target path metadata. The working directory comes from the parsed transcript
418
+ target path metadata. Codex token totals are normalized
419
+ from `event_msg.token_count.info.total_token_usage`: `input_tokens` is split
420
+ into fresh input and `cached_input_tokens`, output tokens are preserved, and
421
+ `reasoning_output_tokens` is stored as a visible sub-count that is already
422
+ included in Codex output totals. When the Codex state database exposes
423
+ `threads.tokens_used`, agentlog stores it as the session-level provider total so
424
+ the stats page can reconcile rollout splits with Codex's own thread counter.
425
+ Because these fields are import-time metadata, changing Codex token semantics
426
+ requires a full reimport, for example:
427
+
428
+ ```bash
429
+ agentlog import --source codex-desktop --since all
430
+ agentlog import --source codex-cli --since all
431
+ ```
432
+
433
+ The working directory comes from the parsed transcript
372
434
  first, then the `threads.cwd` column. If neither is available, the session is
373
435
  archived under `codex/uncategorized` instead of inheriting the supervisor's
374
436
  current directory. Repo attribution is computed from the resolved directory.
@@ -379,35 +441,85 @@ Reading `.zst` sessions requires `zstd` or `unzstd`.
379
441
  - Import selector: `codex-desktop`
380
442
  - Provider: `codex`
381
443
  - Source type: `codex-desktop-history`
382
- - Primary store: `~/.codex/state_5.sqlite`
444
+ - Primary stores: `~/.codex/state_5.sqlite` and
445
+ `~/.codex/session_index.jsonl`
383
446
  - Session files: rollout paths referenced by the `threads` table
384
447
  - Source split: `threads.source = "vscode"`
385
448
  - Overrides: same as Codex CLI
386
449
 
387
- Codex Desktop uses the same state database, summary-document handling, and
388
- rollout parser as Codex CLI. The only distinction is the `threads.source` value.
389
- This is why the web source dropdown can split Codex CLI and Codex Desktop even
390
- though both archive under the same `codex` provider.
450
+ Codex Desktop uses the same state database, session-index title handling,
451
+ summary-document handling, and rollout parser as Codex CLI. The only distinction
452
+ is the `threads.source` value. This is why the web source dropdown can split
453
+ Codex CLI and Codex Desktop even though both archive under the same `codex`
454
+ provider.
455
+
456
+ ## Codex SDK Jobs
457
+
458
+ - Import selector: `codex-sdk`
459
+ - Provider: `codex`
460
+ - Source type: `codex-sdk-history`
461
+ - Primary store: `~/.codex/state_5.sqlite`
462
+ - Session files: rollout paths referenced by the `threads` table
463
+ - Source split: `threads.source = "exec"`
464
+ - Overrides: same as Codex CLI
465
+
466
+ Codex SDK jobs use the same rollout parser as Codex CLI/Desktop, but they are
467
+ shown as a separate opt-in source because `codex exec` batch traffic can produce
468
+ hundreds or thousands of short prompt/response sessions. They are useful for
469
+ programmatic jobs such as Siftly bookmark enrichment and Polymarket vote
470
+ labeling, but should not be silently mixed into the default interactive import.
471
+ When imported, these sessions remain searchable, but the stats view keeps them
472
+ in the separate SDK jobs aggregate instead of primary interactive totals.
391
473
 
392
474
  ## ChatGPT Export
393
475
 
394
- - Import command: `agentlog import chatgpt --file <path> [--scope local|team]`
476
+ - Instructions command: `agentlog import chatgpt`
477
+ - Import command: `agentlog import chatgpt <path> [--scope local|team]`
395
478
  - Provider: `chatgpt`
396
479
  - Source type: `chatgpt-export`
397
- - Source file: ChatGPT JSON export or ZIP containing a JSON export
480
+ - Source file: ChatGPT JSON export, OpenAI export ZIP, extracted
481
+ `OpenAI-export`, or `User Online Activity` folder
398
482
  - Default archive scope: `chatgpt`
399
483
 
400
- ChatGPT is not scanned automatically from a desktop app. The user provides an
401
- official export file. ZIP imports prefer `conversations.json`, then another JSON
402
- file with `chat` in the name, then the first JSON file in the ZIP.
484
+ ChatGPT is not scanned automatically from a desktop app. In a terminal, the
485
+ import command without a path starts a walkthrough that asks for the export path
486
+ or paths, account username/email, and display name.
487
+ Use `agentlog import chatgpt --instructions` for static Privacy Portal and
488
+ ChatGPT Data Controls instructions. Older ChatGPT exports usually contain a
489
+ single `conversations.json`. Newer OpenAI privacy exports can arrive as
490
+ `OpenAI-export/User Online Activity` with conversation data split across ZIPs or
491
+ folders such as
492
+ `Conversations__<account-hash>-chatgpt-0001-part-0001` and
493
+ `...part-0002`. Import the parent `User Online Activity` folder when possible.
494
+ The walkthrough also accepts each split `Conversations__...chatgpt...part`
495
+ folder one at a time, ending on a blank line, so agentlog sees all split JSON
496
+ files, manifests, `chat.html`, conversation ZIPs, and attached files together. Very large outer
497
+ `OpenAI-export.zip` files should be unzipped first because Node and unzip tooling
498
+ can hit multi-gigabyte file limits.
499
+
500
+ ChatGPT attachment files are preserved in the shared raw export archive and are
501
+ shown from normalized message metadata in the readable transcript. Fresh imports
502
+ render image/file attachment cards instead of folding `[Attachment: ...]`
503
+ placeholders into message text. Reimport ChatGPT exports after upgrading to
504
+ populate the attachment metadata and viewer URLs.
505
+ File cards are only linked when the exported raw archive actually contains the
506
+ file bytes; ChatGPT privacy exports may list some uploaded PDFs or documents in
507
+ conversation metadata without including the original file. ChatGPT tool calls
508
+ such as `web.run` are normalized into tool-call cards, uploaded-file parsing
509
+ messages are normalized as file tool results, and private-use citation markers
510
+ including file citations render as citation labels instead of unsupported glyph
511
+ boxes.
403
512
 
404
513
  For OpenAI export mappings, agentlog reads each node message, normalizes
405
- `author.role`, extracts `content.parts`, and uses `create_time` or `update_time`
406
- as the timestamp. Web imports are scope-based by default because they generally
407
- do not have a reliable local working directory. Since official exports do not
408
- usually include usage, the importer archives estimated per-message
409
- `metadata.usage` from native message content and marks the resulting session
410
- usage as estimated.
514
+ `author.role`, extracts `content.parts`, records attachment and asset-pointer
515
+ metadata, and uses `create_time` or `update_time` as the timestamp. Non-chat JSON
516
+ such as `user_settings.json` is available for account metadata but is not counted
517
+ as a conversation. Extensionless binary attachment files are preserved as raw
518
+ files rather than parsed as JSON. Web imports are scope-based by default because
519
+ they generally do not have a reliable local working directory. Since official
520
+ exports do not usually include usage, the importer archives estimated
521
+ per-message `metadata.usage` from native message content and marks the resulting
522
+ session usage as estimated.
411
523
 
412
524
  ## Claude Code CLI
413
525
 
@@ -419,15 +531,60 @@ usage as estimated.
419
531
  Claude Code CLI files are discovered under `~/.claude/projects`. Each JSONL file
420
532
  is classified before import. A file is treated as an interactive conversation
421
533
  when the initial records include `type = "user"` or `type = "assistant"` with a
422
- `message` object and no `entrypoint = "sdk-cli"`.
534
+ `message` object and no `entrypoint = "sdk-cli"`. Remote Control transcripts
535
+ also use `entrypoint = "sdk-cli"`, but include a deferred tool delta with
536
+ Remote Control tool names such as `RemoteTrigger`, `TaskOutput`, `TaskStop`,
537
+ `PushNotification`, `AskUserQuestion`, task tools, cron tools, or monitor tools;
538
+ those are imported as interactive Claude Code conversations rather than SDK
539
+ jobs.
423
540
 
424
541
  The Claude-specific JSONL parser extracts session ids, titles, cwd fields,
425
542
  message roles, text content, timestamps, assistant thinking summaries,
426
543
  `tool_use` calls, `tool_result` outputs, model, request id, stop status, and
427
- token usage. Tool calls and results are normalized into the shared
544
+ token usage. It also preserves Claude JSONL lineage fields (`uuid`,
545
+ `parentUuid`, `logicalParentUuid`, `leafUuid`, `promptId`,
546
+ `sourceToolAssistantUUID`, `sourceToolUseID`, `parentToolUseID`, `toolUseID`,
547
+ `agentId`, `slug`, `isSidechain`), execution metadata (`entrypoint`,
548
+ `userType`, Claude Code version, git branch, permission mode), attribution skill,
549
+ MCP structured-content metadata, API error metadata, Remote Control
550
+ queue/tool-surface summaries, and richer usage extras such as service tier,
551
+ speed, server-tool usage, and cache creation detail.
552
+ Tool calls and results are normalized into the shared
428
553
  `metadata.toolCalls[]`, `metadata.toolResult`, and `metadata.usage` shapes.
429
554
  Bash or shell tool calls that invoke `apply_patch` are reclassified as edit
430
555
  calls and retain the patch text under `arguments.diff`.
556
+ Tool results are matched back to prior `tool_use` ids when possible so result
557
+ cards inherit the tool name instead of displaying only the raw tool-use id.
558
+ Remote Control lifecycle records are also converted into provider-generated
559
+ system/context messages for queue operations, deferred tool catalog changes,
560
+ MCP instruction updates, skill listings, nested memories, queued commands,
561
+ command permissions, edited text files, date changes, max-turn notices,
562
+ file-history snapshots, hook progress, and stop-hook summaries. These messages
563
+ carry compact metadata and previews rather than copying large attachment bodies;
564
+ the byte-perfect source records remain in the raw archive. Session summaries
565
+ also include Remote Control attachment counts/details, available tool names,
566
+ MCP server names, queue timing/content, agent ids, slugs, API error counts, and
567
+ MCP structured-content counts.
568
+
569
+ For each Claude Code session with a working directory, agentlog also snapshots
570
+ Claude subagent definitions from the user-level `~/.claude/agents` directory and
571
+ the nearest project `.claude/agents` directory. It parses the Markdown
572
+ frontmatter fields that Claude uses for subagents (`name`, `description`,
573
+ `tools`, and `model`), records the effective project-over-user definition set in
574
+ `metadata.sessionSummary.claudeSubagents`, and preserves the source `.md` files
575
+ in the session raw manifest. The transcript is not padded with full subagent
576
+ instructions; use the raw archive when the complete definition body is needed.
577
+
578
+ Claude Code subagent run transcripts stored under
579
+ `~/.claude/projects/<project>/<parent-session-id>/subagents/*.jsonl` are also
580
+ attached to the parent session as `metadata.sessionSummary.claudeSubagentRuns`
581
+ and imported as child sessions with `conversationKind = "claude_subagent"` and
582
+ `parentComposerId` set to the parent Claude Code session id. The parent summary
583
+ keeps compact run metadata, prompts, result previews, model names, usage totals,
584
+ and tool counts; the child session carries the full normalized transcript and
585
+ preserves both the JSONL and any sibling `.meta.json` file in raw storage. The
586
+ web viewer renders run summaries inline at their transcript timestamps and links
587
+ to the child session instead of dumping every subagent run at the top.
431
588
 
432
589
  When the Claude desktop app has a matching
433
590
  `~/Library/Application Support/Claude/claude-code-sessions/**/local_*.json`
@@ -436,7 +593,8 @@ record with `cliSessionId`, the CLI importer uses that sidecar's generated
436
593
  archive storage. This is the source of Claude's readable auto names such as
437
594
  "Fix cursor import paths handling"; the transcript JSONL itself may only contain
438
595
  the user prompt ("Can you fix these?"). Without a sidecar title, the importer
439
- falls back to the first real user prompt. Repo attribution uses sidecar
596
+ uses Claude JSONL `ai-title` events when present, then falls back to the first
597
+ real user prompt. Repo attribution uses sidecar
440
598
  `originCwd` when available, otherwise the parsed `cwd`; Claude-created
441
599
  `.claude/worktrees/<name>` directories are attributed to their parent project
442
600
  when that project still exists, even if the temporary worktree has been deleted.
@@ -468,7 +626,8 @@ sessions. agentlog separates them by scanning the initial JSONL records for
468
626
  batch runs can be much higher volume than interactive sessions.
469
627
 
470
628
  When imported, SDK jobs use the same Claude-specific JSONL parser as Claude Code
471
- CLI but archive under `claude_sdk`.
629
+ CLI but archive under `claude_sdk`. Stats keep them in the separate SDK jobs
630
+ aggregate instead of primary interactive totals.
472
631
 
473
632
  ## Claude Code Desktop
474
633
 
@@ -520,16 +679,18 @@ uncategorized.
520
679
 
521
680
  ## Claude.ai Export
522
681
 
523
- - Import command: `agentlog import claude-web --file <path> [--scope local|team]`
682
+ - Instructions command: `agentlog import claude-web`
683
+ - Import command: `agentlog import claude-web <path> [--scope local|team]`
524
684
  - Provider: `claude_web`
525
685
  - Source types: `claude-web-export`, `claude-web-memory`
526
686
  - Source file: Claude.ai JSON export or ZIP containing a JSON export
527
687
  - Default archive scope: `claude_web`
528
688
 
529
- Claude.ai is not scanned automatically from the desktop app. The user provides
530
- an official export file. agentlog reads `chat_messages`, `messages`, or
531
- `children`, normalizes sender/role fields, extracts text content, and uses
532
- `created_at`, `updated_at`, or `timestamp`.
689
+ Claude.ai is not scanned automatically from the desktop app. The import command
690
+ without a path prints official export instructions for Claude Settings >
691
+ Privacy. The user then provides the downloaded official export file. agentlog
692
+ reads `chat_messages`, `messages`, or `children`, normalizes sender/role fields,
693
+ extracts text content, and uses `created_at`, `updated_at`, or `timestamp`.
533
694
  For official `conversations.json` exports, the top-level conversation `summary`
534
695
  is archived as both `sessionSummary.summary` and a supplementary transcript row.
535
696
  Assistant messages prefer structured `content[]` parts over the legacy top-level
@@ -555,7 +716,7 @@ are marked `recovered-time-unknown` in history views instead of being displayed
555
716
  as if they happened at import time. This keeps project folders from implying
556
717
  that account-level conversations were reliably tagged to Claude projects when
557
718
  the export did not preserve that relationship. Re-run
558
- `agentlog import claude-web --file <path>` after importing an export that
719
+ `agentlog import claude-web <path>` after importing an export that
559
720
  contains conversation project ids or after Claude web parser semantics change.
560
721
 
561
722
  Like ChatGPT export imports, Claude.ai imports are scope-based by default because
@@ -821,8 +982,8 @@ per-message timestamp exists, it uses the source file's mtime with stable
821
982
  millisecond offsets so imports do not get stamped with the time of import.
822
983
 
823
984
  Cursor project slugs are decoded back to local paths when possible. For example,
824
- `Users-bzhou-Documents-GitHub-spring-next` resolves to
825
- `/Users/bzhou/Documents/GitHub/spring-next` if that directory exists. If no
985
+ `Users-alex-Documents-GitHub-spring-next` resolves to
986
+ `/Users/alex/Documents/GitHub/spring-next` if that directory exists. If no
826
987
  working directory can be resolved for a newer transcript, it archives under
827
988
  `cursor/uncategorized` instead of assigning the session to the current repo.
828
989
 
@@ -905,14 +1066,18 @@ created by Desktop, CLI, and Web clients, so agentlog classifies each SQLite
905
1066
  session row individually. Desktop sessions are identified by session ids in
906
1067
  OpenCode Desktop sidecar state such as `ai.opencode.desktop/*.dat`; sub-sessions
907
1068
  inherit Desktop classification from a Desktop parent. CLI sessions are
908
- identified by session-level `agent` or `model` metadata. Remaining non-`local`
909
- shared core rows are labeled as Web sessions. Rows without reliable client
910
- evidence stay on the legacy `opencode-sqlite-history` source type. The
1069
+ identified by session-level `agent` or `model` metadata, or by CLI evidence in
1070
+ the sanitized message metadata when session rows omit those fields. Remaining
1071
+ non-`local` shared core rows are labeled as Web sessions. Rows without reliable
1072
+ client evidence stay on the legacy `opencode-sqlite-history` source type. The
911
1073
  `session`, `message`, `part`, and `project` tables provide session
912
1074
  metadata, working directory, user/assistant messages, reasoning text, tool
913
- calls, tool outputs, model/provider ids, cost, and token usage. Because the
914
- database is a multi-session source, raw preservation stores it as a shared raw
915
- source instead of duplicating the same file into every session archive.
1075
+ calls, tool outputs, model/provider ids, cost, and token usage. During SQLite
1076
+ reads, agentlog removes the bulky `message.data.summary` object before JSON
1077
+ transport; canonical transcript text still comes from the `part` table, and raw
1078
+ preservation keeps the original database byte-for-byte. Because the database is a
1079
+ multi-session source, raw preservation stores it as a shared raw source instead
1080
+ of duplicating the same file into every session archive.
916
1081
 
917
1082
  agentlog also reads OpenCode's JSON session store directly. Sessions provide the
918
1083
  archive id and project id; message and part files provide role text, reasoning
package/docs/release.md CHANGED
@@ -64,5 +64,5 @@ After tagging and pushing the release, sanity-check both public install forms:
64
64
 
65
65
  ```sh
66
66
  npm install -g agentel
67
- npm install -g brianlzhou/agentlog#v0.2.5
67
+ npm install -g brianlzhou/agentlog#v0.2.8
68
68
  ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentel",
3
- "version": "0.2.5",
3
+ "version": "0.2.8",
4
4
  "description": "Local-first archive and recall layer for agent coding sessions.",
5
5
  "type": "commonjs",
6
6
  "license": "MIT",
@@ -53,5 +53,8 @@
53
53
  "engines": {
54
54
  "node": ">=20"
55
55
  },
56
- "packageManager": "npm@11.5.1"
56
+ "packageManager": "npm@11.5.1",
57
+ "dependencies": {
58
+ "better-sqlite3": "^12.9.0"
59
+ }
57
60
  }