agentel 0.2.6 → 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.
package/README.md CHANGED
@@ -41,7 +41,7 @@ ref for repeatable installs:
41
41
  ```sh
42
42
  npm install -g brianlzhou/agentlog
43
43
  # or
44
- npm install -g brianlzhou/agentlog#v0.2.6
44
+ npm install -g brianlzhou/agentlog#v0.2.8
45
45
  agentlog init
46
46
  ```
47
47
 
@@ -80,6 +80,7 @@ AGENTLOG_HOME=/tmp/agentlog-demo node ./bin/agentlog.js import --source codex-de
80
80
  AGENTLOG_HOME=/tmp/agentlog-demo node ./bin/agentlog.js import chatgpt
81
81
  AGENTLOG_HOME=/tmp/agentlog-demo node ./bin/agentlog.js import claude-web
82
82
  AGENTLOG_HOME=/tmp/agentlog-demo node ./bin/agentlog.js import chatgpt ~/Downloads/chatgpt-export.zip --username you@example.com
83
+ AGENTLOG_HOME=/tmp/agentlog-demo node ./bin/agentlog.js import chatgpt "~/Downloads/OpenAI-export/User Online Activity" --username you@example.com
83
84
  AGENTLOG_HOME=/tmp/agentlog-demo node ./bin/agentlog.js import claude-web ~/Downloads/claude-export --username you --display-name "Personal Claude"
84
85
  AGENTLOG_HOME=/tmp/agentlog-demo node ./bin/agentlog.js import --source claude --since 30d
85
86
  AGENTLOG_HOME=/tmp/agentlog-demo node ./bin/agentlog.js import --source claude-code-desktop --since all
@@ -364,6 +365,9 @@ alongside it:
364
365
  For large multi-session stores such as Cursor SQLite, the per-session raw
365
366
  manifest may reference one shared copy under `raw-sources/` instead of copying
366
367
  the same database into every session folder.
368
+ Web chat imports may also reference a shared raw export archive; ChatGPT
369
+ attachments remain preserved there and fresh imports render image/file cards in
370
+ the readable transcript when the export includes the file bytes.
367
371
 
368
372
  `events.jsonl` uses the local `agentlog.events.v2` canonical event shape:
369
373
  `session.started`, `prompt.submitted`, `response.generated`, `tool.called`, and
@@ -382,7 +386,12 @@ search.
382
386
 
383
387
  Stats are import-time metadata, not viewer-time transcript repair. Archive
384
388
  metadata stores message counts, user-message counts, token usage, and models for
385
- each session, and the web stats view reads those fields directly. Codex SDK and
389
+ each session, and the web stats view reads those fields directly. Token totals
390
+ include cache-read/cache-write tokens when providers report them, while the
391
+ stats payload and UI also keep input, output, cache, and reasoning sub-counts
392
+ separately when available. Codex imports preserve `threads.tokens_used` as the
393
+ provider total and split rollout `token_count` events into fresh input, cache
394
+ read, output, and reasoning metadata. Codex SDK and
386
395
  Claude SDK batch jobs are kept out of primary activity totals, streaks, folder
387
396
  rankings, and provider/model charts; the stats payload and web view expose them
388
397
  as a separate SDK jobs section so high-volume automation does not drown out
@@ -406,13 +415,24 @@ as `[chatgpt]conversations/<account-id>` and
406
415
  metadata in `~/.agentlog/state/web-accounts.json`; use
407
416
  `agentlog import accounts list` to inspect mappings and
408
417
  `agentlog import accounts rename <provider> <account-id-or-username> --display-name <name>`
409
- to change the viewer display name. Claude.ai exports preserve conversation
410
- summaries and split structured thinking parts from visible assistant answers
411
- when the export includes that detail. Repeated manual uploads are incremental:
412
- unchanged conversations are skipped, and updated conversations replace the
413
- stable session for that provider/account/conversation id. Existing malformed
414
- pre-v1 web-chat archives are not migrated automatically; reimport from the
415
- original export after a reset or cleanup.
418
+ to change the viewer display name.
419
+
420
+ For newer OpenAI privacy exports named `OpenAI-export`, unzip the download and
421
+ import the `User Online Activity` folder. Running `agentlog import chatgpt`
422
+ without a path starts a walkthrough that asks for export paths one at a time,
423
+ then account username/email and display name. ChatGPT
424
+ conversations may be split across multiple
425
+ `Conversations__...chatgpt...part-000N` ZIPs or folders; passing the parent
426
+ folder is best, but the walkthrough can also collect the split part folders
427
+ individually and preserve `chat.html`, manifests, ZIPs, and attached files in
428
+ the shared raw export archive. Claude.ai exports preserve conversation summaries
429
+ and split structured
430
+ thinking parts from visible assistant answers when the export includes that
431
+ detail. Repeated manual uploads are incremental: unchanged conversations are
432
+ skipped, and updated conversations replace the stable session for that
433
+ provider/account/conversation id. Existing malformed pre-v1 web-chat archives
434
+ are not migrated automatically; reimport from the original export after a reset
435
+ or cleanup.
416
436
 
417
437
  Tool calls and tool results are normalized before archive write where provider
418
438
  data is available. For example, Devin tool calls live in
@@ -432,16 +452,19 @@ importer/parser logic to rebuild the local archive without redoing setup:
432
452
 
433
453
  ```sh
434
454
  npm install -g agentel@latest
435
- agentlog update --yes --since all
455
+ agentlog update --yes
436
456
  ```
437
457
 
438
458
  `agentlog update` preserves `config.json`, redaction settings, web account
439
- labels, source histories, and recall integrations. It removes derived local
440
- archive, import, index, cache, and sync bookkeeping, then reimports configured
441
- local sources from the stored preferences. It does not touch remote sync objects
442
- by default; use `agentlog sync replace` when the remote should match the rebuilt
443
- local archive. It also does not rediscover manual ChatGPT/Claude.ai export
444
- files; reimport those web exports from the original ZIP/folder when needed.
459
+ labels, manually imported ChatGPT/Claude.ai archives, source histories, and
460
+ recall integrations. It removes derived local archive, import, index, cache, and
461
+ sync bookkeeping, then reimports configured local sources from the stored
462
+ preferences. The rebuild window comes from the initial backfill or an explicit
463
+ all-source import such as `agentlog import --source all --since all`; the
464
+ fallback for legacy configs is `all`. The watcher's rolling
465
+ `imports.defaultSinceDays` is not used by `agentlog update`. It does not touch
466
+ remote sync objects by default; use `agentlog sync replace` when the remote
467
+ should match the rebuilt local archive.
445
468
 
446
469
  Use `agentlog config` to change `~/.agentlog/config.json` without rerunning the
447
470
  init wizard:
@@ -489,8 +512,11 @@ saved in config and used by later `agentlog import --source all` runs unless
489
512
  Default init sources:
490
513
 
491
514
  - Codex CLI sessions and Codex Desktop sessions from Codex state, shown as
492
- separate toggles; Codex SDK jobs are available as an opt-in batch source
493
- - Claude Code CLI transcripts from `~/.claude/projects`
515
+ separate toggles, including linked Codex subagent child sessions when
516
+ `thread_spawn_edges` metadata is present; Codex SDK jobs are available as an
517
+ opt-in batch source
518
+ - Claude Code CLI transcripts from `~/.claude/projects`, including subagent
519
+ definition snapshots and `subagents/*.jsonl` runs imported as child sessions
494
520
  - Claude Code Desktop metadata and Claude Workspace/local-agent sessions from
495
521
  the Claude app data, shown as separate toggles
496
522
  - Gemini CLI saved chats/checkpoints under `~/.gemini/tmp`, plus session/export JSONL stores with tool, usage, and checkpoint metadata
@@ -545,6 +571,7 @@ agentlog import --source codex-sdk --since all
545
571
  agentlog import chatgpt
546
572
  agentlog import claude-web
547
573
  agentlog import chatgpt ~/Downloads/chatgpt-export.zip --username you@example.com
574
+ agentlog import chatgpt "~/Downloads/OpenAI-export/User Online Activity" --username you@example.com
548
575
  agentlog import claude-web ~/Downloads/claude-export --username you --display-name "Personal Claude"
549
576
  agentlog import --source claude --since 30d
550
577
  agentlog import --source claude-code-desktop --since all
@@ -433,7 +433,10 @@ Embedded history web app functions:
433
433
  - `renderMarkdownLink(label, href)`: renders safe links.
434
434
  - `renderSkillLink(name, skillPath)`: renders `$skill` links.
435
435
  - `compactSkillPath(value)`: shortens skill paths for display.
436
- - `setView(mode)`: toggles readable and raw Markdown views.
436
+ - `captureRelativeScrollPosition()`: captures the detail pane scroll ratio.
437
+ - `restoreRelativeScrollPosition(position, serial)`: restores a captured scroll
438
+ ratio after a view-mode layout swap.
439
+ - `setView(mode, options)`: toggles readable and raw Markdown views.
437
440
  - `sessionDetailsText(payload)`: builds copyable session details.
438
441
  - `copyText(value)`: writes text to the clipboard.
439
442
  - `copySessionDetails()`: copies session metadata for pasting into agents.
@@ -559,8 +562,8 @@ Import dispatch and generic providers:
559
562
  - `matchesImportedSessionRepo(session, repo, wantedRepos)`: checks repo filters
560
563
  for sessions with repo or scope attribution.
561
564
  - `importCodexProvider(provider, since, options, env)`: imports Codex CLI,
562
- Desktop, or opt-in exec/SDK threads from state DB, rollout files, and Codex
563
- supplementary summaries when available.
565
+ Desktop, or opt-in exec/SDK threads from the state DB, session index, rollout
566
+ files, and Codex supplementary summaries when available.
564
567
  - `importCursorProvider(provider, since, options, env)`: imports Cursor SQLite
565
568
  and Cursor project transcript sessions; supervisor calls set
566
569
  `cursorRecovery=false` to skip raw SQLite salvage/backfill.
@@ -655,8 +658,9 @@ Source location and file helpers:
655
658
  tool names are kept with interactive Claude Code conversations.
656
659
  - `readInitialLines(file, maxLines, maxBytes)`: reads a bounded prefix of a
657
660
  large JSONL file.
658
- - `readCodexThreads(env)`: queries Codex state DB for top-level threads and
659
- optional `stage1_outputs` summary documents.
661
+ - `readCodexThreads(env)`: queries Codex state DB for top-level threads, merges
662
+ `session_index.jsonl` titles, and reads optional `stage1_outputs` summary
663
+ documents.
660
664
  - `sqliteTableExists(dbPath, tableName)`: checks optional SQLite tables before
661
665
  querying version-dependent Codex state.
662
666
  - `codexStateDb(env)`: resolves Codex state DB path.
@@ -95,15 +95,20 @@ split as non-assistant input, assistant output, and Claude thinking output, not
95
95
  reconstructed billing context windows.
96
96
 
97
97
  ```sh
98
- agentlog update --yes --since all
98
+ agentlog update --yes
99
99
  ```
100
100
 
101
101
  `agentlog update` preserves config preferences, redaction settings, web account
102
- labels, source histories, and recall integrations. It removes derived local
103
- archive/import/index state and reimports configured local sources. Manual web
104
- exports still need to be imported again from the original export file when those
105
- archives need to be rebuilt. `agentlog reset` is the heavier path: it removes
106
- 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
107
112
  application histories such as Cursor, Codex, Claude, Gemini, or Devin logs
108
113
  untouched.
109
114
 
@@ -195,36 +200,36 @@ package-prefixed scheme.
195
200
 
196
201
  | Source type | Version |
197
202
  | --- | --- |
198
- | `codex-cli-history` | `0.2.6.0` |
199
- | `codex-desktop-history` | `0.2.6.0` |
200
- | `codex-sdk-history` | `0.2.6.0` |
201
- | `cli-history` | `0.2.6.0` |
202
- | `claude-sdk-history` | `0.2.6.0` |
203
- | `claude-code-desktop-metadata` | `0.2.6.0` |
204
- | `claude-workspace-desktop` | `0.2.6.0` |
205
- | `cursor-workspace-sqlite` | `0.2.6.0` |
206
- | `cursor-global-sqlite` | `0.2.6.0` |
207
- | `cursor-raw-sqlite-salvage` | `0.2.6.0` |
208
- | `cursor-agent-transcripts` | `0.2.6.0` |
209
- | `devin-cli-history` | `0.2.6.0` |
210
- | `gemini-cli-history` | `0.2.6.0` |
211
- | `cline-task-history` | `0.2.6.0` |
212
- | `opencode-cli-history` | `0.2.6.0` |
213
- | `opencode-cli-sqlite-history` | `0.2.6.0` |
214
- | `opencode-desktop-history` | `0.2.6.0` |
215
- | `opencode-desktop-sqlite-history` | `0.2.6.0` |
216
- | `opencode-web-sqlite-history` | `0.2.6.0` |
217
- | `opencode-history` | `0.2.6.0` |
218
- | `opencode-sqlite-history` | `0.2.6.0` |
219
- | `aider-chat-history` | `0.2.6.0` |
220
- | `antigravity-history` | `0.2.6.0` |
221
- | `antigravity-trajectory-summary` | `0.2.6.0` |
222
- | `windsurf-trajectory-export` | `0.2.6.0` |
223
- | `web-chat-export` | `0.2.6.0` |
224
- | `chatgpt-export` | `0.2.6.0` |
225
- | `claude-web-export` | `0.2.6.0` |
226
- | `claude-web-memory` | `0.2.6.0` |
227
- | `import` | `0.2.6.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` |
228
233
 
229
234
  `cursor-sqlite-history` and `antigravity-brain` are compatibility aliases for
230
235
  older labels. Fingerprints include the parser version prefix, so changing the
@@ -360,29 +365,72 @@ stable local command for the archived source.
360
365
  - Import selector: `codex-cli`
361
366
  - Provider: `codex`
362
367
  - Source type: `codex-cli-history`
363
- - Primary store: `~/.codex/state_5.sqlite`
368
+ - Primary stores: `~/.codex/state_5.sqlite` and
369
+ `~/.codex/session_index.jsonl`
364
370
  - Session files: rollout paths referenced by the `threads` table, plus
365
371
  unindexed `rollout-*.jsonl` files under `sessions` and `archived_sessions`
366
372
  - Source split: `threads.source = "cli"`
367
373
  - Overrides:
368
374
  - `CODEX_STATE_DB` overrides the state database path.
375
+ - `CODEX_SESSION_INDEX` overrides the session index path.
369
376
  - `CODEX_HOME` is used for the fallback sessions root.
370
377
 
371
378
  The importer reads `id`, `rollout_path`, `created_at`, `updated_at`, `source`,
372
- `cwd`, and `title` from the Codex state database using `sqlite3`. When the
373
- 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
374
394
  `rollout_summary` and `raw_memory` as supplementary Codex summary documents and
375
395
  adds them to the archived transcript. The importer also scans
376
396
  `~/.codex/sessions` and `~/.codex/archived_sessions` for `rollout-*.jsonl` and
377
397
  `rollout-*.jsonl.zst` files that are not referenced by the state database, so
378
398
  older archived rollouts still get backed up.
379
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
+
380
413
  The rollout JSONL parser captures readable `response_item` reasoning summaries,
381
414
  Codex `event_msg` assistant/user messages, task and compaction markers, local
382
415
  shell calls, web search calls, custom tool calls such as `apply_patch`, tool
383
416
  outputs, and token-count usage deltas. Shell calls that run `apply_patch`
384
417
  through a heredoc are promoted to edit tool calls with `patch`, `diff`, and
385
- 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
386
434
  first, then the `threads.cwd` column. If neither is available, the session is
387
435
  archived under `codex/uncategorized` instead of inheriting the supervisor's
388
436
  current directory. Repo attribution is computed from the resolved directory.
@@ -393,15 +441,17 @@ Reading `.zst` sessions requires `zstd` or `unzstd`.
393
441
  - Import selector: `codex-desktop`
394
442
  - Provider: `codex`
395
443
  - Source type: `codex-desktop-history`
396
- - Primary store: `~/.codex/state_5.sqlite`
444
+ - Primary stores: `~/.codex/state_5.sqlite` and
445
+ `~/.codex/session_index.jsonl`
397
446
  - Session files: rollout paths referenced by the `threads` table
398
447
  - Source split: `threads.source = "vscode"`
399
448
  - Overrides: same as Codex CLI
400
449
 
401
- Codex Desktop uses the same state database, summary-document handling, and
402
- rollout parser as Codex CLI. The only distinction is the `threads.source` value.
403
- This is why the web source dropdown can split Codex CLI and Codex Desktop even
404
- 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.
405
455
 
406
456
  ## Codex SDK Jobs
407
457
 
@@ -427,22 +477,49 @@ in the separate SDK jobs aggregate instead of primary interactive totals.
427
477
  - Import command: `agentlog import chatgpt <path> [--scope local|team]`
428
478
  - Provider: `chatgpt`
429
479
  - Source type: `chatgpt-export`
430
- - 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
431
482
  - Default archive scope: `chatgpt`
432
483
 
433
- ChatGPT is not scanned automatically from a desktop app. The import command
434
- without a path prints official export instructions for OpenAI's Privacy Portal
435
- and ChatGPT Data Controls. The user then provides the downloaded official export
436
- file. ZIP imports prefer `conversations.json`, then another JSON file with
437
- `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.
438
512
 
439
513
  For OpenAI export mappings, agentlog reads each node message, normalizes
440
- `author.role`, extracts `content.parts`, and uses `create_time` or `update_time`
441
- as the timestamp. Web imports are scope-based by default because they generally
442
- do not have a reliable local working directory. Since official exports do not
443
- usually include usage, the importer archives estimated per-message
444
- `metadata.usage` from native message content and marks the resulting session
445
- 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.
446
523
 
447
524
  ## Claude Code CLI
448
525
 
@@ -489,6 +566,26 @@ also include Remote Control attachment counts/details, available tool names,
489
566
  MCP server names, queue timing/content, agent ids, slugs, API error counts, and
490
567
  MCP structured-content counts.
491
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.
588
+
492
589
  When the Claude desktop app has a matching
493
590
  `~/Library/Application Support/Claude/claude-code-sessions/**/local_*.json`
494
591
  record with `cliSessionId`, the CLI importer uses that sidecar's generated
@@ -885,8 +982,8 @@ per-message timestamp exists, it uses the source file's mtime with stable
885
982
  millisecond offsets so imports do not get stamped with the time of import.
886
983
 
887
984
  Cursor project slugs are decoded back to local paths when possible. For example,
888
- `Users-bzhou-Documents-GitHub-spring-next` resolves to
889
- `/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
890
987
  working directory can be resolved for a newer transcript, it archives under
891
988
  `cursor/uncategorized` instead of assigning the session to the current repo.
892
989
 
@@ -969,14 +1066,18 @@ created by Desktop, CLI, and Web clients, so agentlog classifies each SQLite
969
1066
  session row individually. Desktop sessions are identified by session ids in
970
1067
  OpenCode Desktop sidecar state such as `ai.opencode.desktop/*.dat`; sub-sessions
971
1068
  inherit Desktop classification from a Desktop parent. CLI sessions are
972
- identified by session-level `agent` or `model` metadata. Remaining non-`local`
973
- shared core rows are labeled as Web sessions. Rows without reliable client
974
- 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
975
1073
  `session`, `message`, `part`, and `project` tables provide session
976
1074
  metadata, working directory, user/assistant messages, reasoning text, tool
977
- calls, tool outputs, model/provider ids, cost, and token usage. Because the
978
- database is a multi-session source, raw preservation stores it as a shared raw
979
- 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.
980
1081
 
981
1082
  agentlog also reads OpenCode's JSON session store directly. Sessions provide the
982
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.6
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.6",
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
  }