agentel 0.2.4 → 0.2.5

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.4
44
+ npm install -g brianlzhou/agentlog#v0.2.5
45
45
  agentlog init
46
46
  ```
47
47
 
@@ -234,7 +234,7 @@ still run `agentlog import --source all` for a one-time catch-up,
234
234
  `agentlog watcher login enable` later. The default
235
235
  watcher choices are Codex CLI, Codex Desktop, Claude Code CLI, Claude Code
236
236
  Desktop, Claude Workspace, Gemini CLI, Antigravity, Devin CLI, Cursor, Cline,
237
- OpenCode, and Aider. New configs still support
237
+ OpenCode CLI, OpenCode Desktop, OpenCode Web, and Aider. New configs still support
238
238
  `imports.autoDiscoverSources=true`, but init records the chosen watcher list
239
239
  exactly by setting `imports.autoDiscoverSources=false`.
240
240
  Cursor raw SQLite recovery is intentionally left to explicit imports such as
@@ -493,7 +493,7 @@ Default init sources:
493
493
  to same-project workspace sessions, duplicate prefix pruning, and newer
494
494
  `~/.cursor/projects/<project>/agent-transcripts` files
495
495
  - Cline task folders from VS Code/JetBrains globalStorage, including checkpoint diffs when present
496
- - OpenCode JSON session/message/part storage under `~/.local/share/opencode`
496
+ - OpenCode CLI/core SQLite and project JSON storage under `~/.local/share/opencode`, plus OpenCode Desktop app storage and Web sessions when present
497
497
  - Aider repo-local `.aider.chat.history.md` transcripts, with `.aider.llm.history`
498
498
  model/usage enrichment, `.aider.input.history` backups, and matching auto-commit diffs
499
499
 
@@ -528,7 +528,7 @@ The same choices can be run directly:
528
528
 
529
529
  ```sh
530
530
  agentlog import --source all --since all
531
- agentlog import --sources codex-cli,codex-desktop,claude,claude-code-desktop,claude-workspace,gemini-cli,antigravity,devin-cli,cursor,cline,opencode,aider --since all
531
+ agentlog import --sources codex-cli,codex-desktop,claude,claude-code-desktop,claude-workspace,gemini-cli,antigravity,devin-cli,cursor,cline,opencode-cli,opencode-desktop,opencode-web,aider --since all
532
532
  agentlog import --source codex-desktop --since 90d
533
533
  agentlog import --source codex-cli --since 30d
534
534
  agentlog import chatgpt ~/Downloads/chatgpt-export.zip --username you@example.com
@@ -790,13 +790,13 @@ Cline helpers:
790
790
 
791
791
  OpenCode helpers:
792
792
 
793
- - `openCodeDatabaseFiles(env)`: resolves normalized OpenCode `opencode.db`
793
+ - `openCodeDatabaseFiles(env, options)`: resolves normalized OpenCode `opencode.db`
794
794
  files from data-root defaults and database override env vars.
795
- - `openCodeStorageRoots(env)`: resolves global and project-scoped OpenCode
795
+ - `openCodeStorageRoots(env, options)`: resolves global and project-scoped OpenCode
796
796
  `storage` directories, plus override env vars.
797
797
  - `readOpenCodeSqliteSessionsFromDb(dbPath)`: reads the `session`, `message`,
798
798
  `part`, and `project` tables from `opencode.db` and emits
799
- `opencode-sqlite-history` sessions.
799
+ desktop or explicitly configured SQLite sessions.
800
800
  - `openCodeSessionFiles(root)`: finds session JSON files.
801
801
  - `openCodeMessageSessionIds(root)`: finds message-only OpenCode session
802
802
  directories when session metadata is missing.
@@ -183,30 +183,35 @@ package-prefixed scheme.
183
183
 
184
184
  | Source type | Version |
185
185
  | --- | --- |
186
- | `codex-cli-history` | `0.2.4.0` |
187
- | `codex-desktop-history` | `0.2.4.0` |
188
- | `cli-history` | `0.2.4.0` |
189
- | `claude-sdk-history` | `0.2.4.0` |
190
- | `claude-code-desktop-metadata` | `0.2.4.0` |
191
- | `claude-workspace-desktop` | `0.2.4.0` |
192
- | `cursor-workspace-sqlite` | `0.2.4.0` |
193
- | `cursor-global-sqlite` | `0.2.4.0` |
194
- | `cursor-raw-sqlite-salvage` | `0.2.4.0` |
195
- | `cursor-agent-transcripts` | `0.2.4.0` |
196
- | `devin-cli-history` | `0.2.4.0` |
197
- | `gemini-cli-history` | `0.2.4.0` |
198
- | `cline-task-history` | `0.2.4.0` |
199
- | `opencode-history` | `0.2.4.0` |
200
- | `opencode-sqlite-history` | `0.2.4.0` |
201
- | `aider-chat-history` | `0.2.4.0` |
202
- | `antigravity-history` | `0.2.4.0` |
203
- | `antigravity-trajectory-summary` | `0.2.4.0` |
204
- | `windsurf-trajectory-export` | `0.2.4.0` |
205
- | `web-chat-export` | `0.2.4.0` |
206
- | `chatgpt-export` | `0.2.4.0` |
207
- | `claude-web-export` | `0.2.4.0` |
208
- | `claude-web-memory` | `0.2.4.0` |
209
- | `import` | `0.2.4.0` |
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` |
210
215
 
211
216
  `cursor-sqlite-history` and `antigravity-brain` are compatibility aliases for
212
217
  older labels. Fingerprints include the parser version prefix, so changing the
@@ -249,12 +254,13 @@ The setup UI, import defaults, and history source filters use this grouped order
249
254
  Claude.ai, Claude SDK jobs
250
255
  3. Google: Gemini CLI, Antigravity
251
256
  4. Cognition: Devin CLI
252
- 5. Other: Cursor, Cline, OpenCode, Aider
257
+ 5. Other: Cursor, Cline, OpenCode CLI, OpenCode Desktop, OpenCode Web, Aider
253
258
 
254
259
  `agentlog import --source all` uses the default import order from
255
260
  `src/sources.js`: `codex-cli`, `codex-desktop`, `claude`,
256
261
  `claude-code-desktop`, `claude-workspace`, `gemini-cli`, `antigravity`,
257
- `devin-cli`, `cursor`, `cline`, `opencode`, `aider`. Claude SDK jobs are
262
+ `devin-cli`, `cursor`, `cline`, `opencode-cli`, `opencode-desktop`,
263
+ `opencode-web`, `aider`. Claude SDK jobs are
258
264
  intentionally opt-in. Windsurf local cache scanning is disabled for now because
259
265
  current Cascade transcripts are encrypted binary stores, but downloaded
260
266
  trajectory Markdown exports are importable with an explicit path.
@@ -421,9 +427,32 @@ message roles, text content, timestamps, assistant thinking summaries,
421
427
  token usage. Tool calls and results are normalized into the shared
422
428
  `metadata.toolCalls[]`, `metadata.toolResult`, and `metadata.usage` shapes.
423
429
  Bash or shell tool calls that invoke `apply_patch` are reclassified as edit
424
- calls and retain the patch text under `arguments.diff`. Repo attribution is
425
- computed from the parsed `cwd`; if no cwd is present the session is archived
426
- under an uncategorized provider scope.
430
+ calls and retain the patch text under `arguments.diff`.
431
+
432
+ When the Claude desktop app has a matching
433
+ `~/Library/Application Support/Claude/claude-code-sessions/**/local_*.json`
434
+ record with `cliSessionId`, the CLI importer uses that sidecar's generated
435
+ `title` and `originCwd` while preserving both the transcript and sidecar in raw
436
+ archive storage. This is the source of Claude's readable auto names such as
437
+ "Fix cursor import paths handling"; the transcript JSONL itself may only contain
438
+ 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
440
+ `originCwd` when available, otherwise the parsed `cwd`; Claude-created
441
+ `.claude/worktrees/<name>` directories are attributed to their parent project
442
+ when that project still exists, even if the temporary worktree has been deleted.
443
+ The original worktree path remains stored as `cwd`. If no cwd is present the
444
+ session is archived under an uncategorized provider scope.
445
+
446
+ A sanitized subset of sidecar metadata is also copied into
447
+ `metadata.sessionSummary.claudeCodeSidecar`: the app/CLI session ids, title
448
+ source, cwd/origin cwd, worktree path/name, branch names, created/last-activity
449
+ timestamps, model/effort, permission modes, completed turn count, archive state,
450
+ enabled MCP tool count, MCP server names, and sidecar source path. The sidecar
451
+ `model` also contributes to normalized `models[]` through `sessionSummary`
452
+ model usage. Full MCP configuration remains available only through raw
453
+ preservation rather than promoted metadata. After this parser behavior changes,
454
+ run `agentlog update --yes --since all` or `agentlog import claude --since all`
455
+ to rebuild existing local Claude Code archives.
427
456
 
428
457
  ## Claude SDK Jobs
429
458
 
@@ -834,18 +863,25 @@ original checkpoint files remain in raw backups.
834
863
 
835
864
  ## OpenCode
836
865
 
837
- - Import selector: `opencode`
866
+ - Import selectors: `opencode-cli`, `opencode-desktop`, `opencode-web`, or `opencode` for all three
838
867
  - Provider: `opencode`
839
868
  - Source types:
840
- - `opencode-sqlite-history` for the normalized `opencode.db` store
841
- - `opencode-history` for the JSON `storage/` layout
842
- - Primary data root: `~/.local/share/opencode`
843
- - Alternate macOS data root: `~/Library/Application Support/opencode`
844
- - Additional desktop roots:
869
+ - `opencode-cli-history` for CLI JSON `storage/` sessions
870
+ - `opencode-cli-sqlite-history` for the CLI/core normalized `~/.local/share/opencode/opencode.db` store
871
+ - `opencode-desktop-history` for desktop/app JSON `storage/` sessions
872
+ - `opencode-desktop-sqlite-history` for the desktop/app normalized `opencode.db` store
873
+ - `opencode-web-sqlite-history` for web sessions in the shared normalized SQLite store
874
+ - `opencode-history` and `opencode-sqlite-history` for older or explicitly configured archives
875
+ - CLI data root: `~/.local/share/opencode`
876
+ - Desktop/app data roots:
877
+ - `~/Library/Application Support/ai.opencode.desktop`
878
+ - `~/Library/Application Support/opencode`
845
879
  - `~/.local/share/ai.opencode.app`
846
880
  - `~/Library/Application Support/ai.opencode.app`
847
881
  - SQLite database:
848
- - `opencode.db`
882
+ - CLI/core root: `~/.local/share/opencode/opencode.db`
883
+ - desktop/app roots: `opencode.db`
884
+ - explicit overrides only: `AGENTLOG_OPENCODE_DB`, `AGENTLOG_OPENCODE_DATABASE`, `OPENCODE_DB`, or `AGENTLOG_OPENCODE_DATA_DIR`
849
885
  - Storage roots:
850
886
  - `~/.local/share/opencode/storage`
851
887
  - `~/.local/share/opencode/project/<project-slug>/storage`
@@ -862,8 +898,17 @@ original checkpoint files remain in raw backups.
862
898
  - `AGENTLOG_OPENCODE_STORAGE_DIR` or `AGENTLOG_OPENCODE_STORAGE_ROOTS`
863
899
  points directly at one or more `storage` directories.
864
900
 
865
- agentlog first reads OpenCode's normalized SQLite store when `opencode.db` is
866
- present. The `session`, `message`, `part`, and `project` tables provide session
901
+ agentlog reads OpenCode's normalized SQLite store from the shared core
902
+ `~/.local/share/opencode/opencode.db` root, desktop/app roots, or when a
903
+ database is explicitly configured. The shared core database can contain sessions
904
+ created by Desktop, CLI, and Web clients, so agentlog classifies each SQLite
905
+ session row individually. Desktop sessions are identified by session ids in
906
+ OpenCode Desktop sidecar state such as `ai.opencode.desktop/*.dat`; sub-sessions
907
+ 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
911
+ `session`, `message`, `part`, and `project` tables provide session
867
912
  metadata, working directory, user/assistant messages, reasoning text, tool
868
913
  calls, tool outputs, model/provider ids, cost, and token usage. Because the
869
914
  database is a multi-session source, raw preservation stores it as a shared raw
@@ -879,7 +924,11 @@ If a session metadata file is missing but `storage/message/<session-id>/` and
879
924
  session from those message and part files.
880
925
 
881
926
  When both SQLite and JSON records exist for the same OpenCode session id,
882
- agentlog prefers `opencode-sqlite-history` and merges the raw source file list.
927
+ agentlog prefers SQLite source types such as `opencode-cli-sqlite-history`
928
+ and merges the raw source file list.
929
+ After this source handling change, run `agentlog import --source opencode
930
+ --since all` or `agentlog update --yes --since all` to rebuild existing local
931
+ OpenCode archives with the corrected CLI/Desktop/Web split.
883
932
 
884
933
  When `session_diff/<session-id>.json` is present, agentlog adds a supplementary
885
934
  edit tool call with the diff payload. Unified diff text is rendered inline in
package/docs/release.md CHANGED
@@ -30,7 +30,6 @@ npm run smoke:pack
30
30
  - selected docs
31
31
  - `README.md`
32
32
  - `LICENSE`
33
- - `agentlog-spec.md`
34
33
  - `package.json`
35
34
 
36
35
  It should not include local settings, test fixtures, `.git`, `.claude`, logs,
@@ -65,5 +64,5 @@ After tagging and pushing the release, sanity-check both public install forms:
65
64
 
66
65
  ```sh
67
66
  npm install -g agentel
68
- npm install -g brianlzhou/agentlog#v0.2.4
67
+ npm install -g brianlzhou/agentlog#v0.2.5
69
68
  ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentel",
3
- "version": "0.2.4",
3
+ "version": "0.2.5",
4
4
  "description": "Local-first archive and recall layer for agent coding sessions.",
5
5
  "type": "commonjs",
6
6
  "license": "MIT",
package/src/cli.js CHANGED
@@ -2544,7 +2544,7 @@ function resumeCommandForSession(session) {
2544
2544
  if (provider === "devin" && sourceType === "devin-cli-history") {
2545
2545
  return `devin -r ${shellArg(sessionId.replace(/^devin-/, ""))}`;
2546
2546
  }
2547
- if (provider === "opencode" && ["opencode-history", "opencode-sqlite-history"].includes(sourceType)) {
2547
+ if (provider === "opencode" && ["opencode-cli-history", "opencode-cli-sqlite-history", "opencode-desktop-history", "opencode-desktop-sqlite-history", "opencode-web-sqlite-history", "opencode-history", "opencode-sqlite-history"].includes(sourceType)) {
2548
2548
  return `opencode --session ${shellArg(sessionId.replace(/^opencode-/, ""))}`;
2549
2549
  }
2550
2550
  if (provider === "gemini_cli" && sourceType === "gemini-cli-history") {
@@ -3188,6 +3188,7 @@ function statsCompanyFromProvider(provider) {
3188
3188
  if (["claude_code", "claude_desktop", "claude_sdk", "claude_web"].includes(value)) return "anthropic";
3189
3189
  if (["gemini_cli", "antigravity"].includes(value)) return "google";
3190
3190
  if (value === "devin" || value === "windsurf") return "cognition";
3191
+ if (value === "cursor") return "cursor";
3191
3192
  return "unknown";
3192
3193
  }
3193
3194
 
@@ -3201,7 +3202,7 @@ function statsCompanyFromModel(model) {
3201
3202
  if (text.includes("devin") || text.includes("cognition")) return "cognition";
3202
3203
  if (text.includes("windsurf") || text.includes("swe-")) return "cognition";
3203
3204
  if (text.includes("antigravity")) return "google";
3204
- if (text.startsWith("composer-") || text.startsWith("cursor-") || text === "auto") return "cursor";
3205
+ if (text.startsWith("composer-") || text.startsWith("cursor-") || text === "auto" || text === "default") return "cursor";
3205
3206
  return "";
3206
3207
  }
3207
3208
 
@@ -3519,7 +3520,7 @@ const RECALL_TARGET_SOURCE_MAP = {
3519
3520
  devin: ["devin-cli"],
3520
3521
  cursor: ["cursor"],
3521
3522
  cline: ["cline"],
3522
- opencode: ["opencode"],
3523
+ opencode: ["opencode-cli", "opencode-desktop", "opencode-web"],
3523
3524
  aider: ["aider"]
3524
3525
  };
3525
3526
 
@@ -3600,6 +3601,9 @@ function normalizeRecallTarget(target) {
3600
3601
  "gemini-cli": "gemini",
3601
3602
  "devin-cli": "devin",
3602
3603
  "open-code": "opencode",
3604
+ "opencode-cli": "opencode",
3605
+ "opencode-desktop": "opencode",
3606
+ "opencode-web": "opencode",
3603
3607
  open_code: "opencode",
3604
3608
  clinecli: "cline",
3605
3609
  "cline-cli": "cline",
@@ -5158,12 +5162,28 @@ function importSourceOptions(discovered) {
5158
5162
  defaultSelected: Boolean(discovered.cline?.sessions)
5159
5163
  },
5160
5164
  {
5161
- source: "opencode",
5162
- label: "OpenCode",
5163
- count: discovered.opencode?.sessions || 0,
5164
- summary: sourceSummary(discovered.opencode),
5165
- description: "OpenCode JSON session, message, part, and session_diff storage from ~/.local/share/opencode.",
5166
- defaultSelected: Boolean(discovered.opencode?.sessions)
5165
+ source: "opencode-cli",
5166
+ label: "OpenCode CLI",
5167
+ count: discovered.opencodeCli?.sessions || 0,
5168
+ summary: sourceSummary(discovered.opencodeCli),
5169
+ description: "OpenCode CLI/core SQLite database plus project JSON session, message, part, and session_diff storage from ~/.local/share/opencode.",
5170
+ defaultSelected: Boolean(discovered.opencodeCli?.sessions)
5171
+ },
5172
+ {
5173
+ source: "opencode-desktop",
5174
+ label: "OpenCode Desktop",
5175
+ count: discovered.opencodeDesktop?.sessions || 0,
5176
+ summary: sourceSummary(discovered.opencodeDesktop),
5177
+ description: "OpenCode Desktop app-specific SQLite database and app storage.",
5178
+ defaultSelected: Boolean(discovered.opencodeDesktop?.sessions)
5179
+ },
5180
+ {
5181
+ source: "opencode-web",
5182
+ label: "OpenCode Web",
5183
+ count: discovered.opencodeWeb?.sessions || 0,
5184
+ summary: sourceSummary(discovered.opencodeWeb),
5185
+ description: "OpenCode web sessions from the shared OpenCode SQLite store.",
5186
+ defaultSelected: Boolean(discovered.opencodeWeb?.sessions)
5167
5187
  },
5168
5188
  {
5169
5189
  source: "aider",
@@ -5741,7 +5761,9 @@ mark.search-match.search-match-current{background:#fde047;color:#422006;box-shad
5741
5761
  <button class="select-option" type="button" data-value="devin-cli">Devin CLI</button>
5742
5762
  <button class="select-option" type="button" data-value="cursor">Cursor</button>
5743
5763
  <button class="select-option" type="button" data-value="cline">Cline</button>
5744
- <button class="select-option" type="button" data-value="opencode">OpenCode</button>
5764
+ <button class="select-option" type="button" data-value="opencode-cli">OpenCode CLI</button>
5765
+ <button class="select-option" type="button" data-value="opencode-desktop">OpenCode Desktop</button>
5766
+ <button class="select-option" type="button" data-value="opencode-web">OpenCode Web</button>
5745
5767
  <button class="select-option" type="button" data-value="aider">Aider</button>
5746
5768
  </div>
5747
5769
  </div>
@@ -6017,7 +6039,7 @@ function brandKeyForSourceValue(value) {
6017
6039
  if (key === 'devin-cli') return 'devin';
6018
6040
  if (key === 'cursor') return 'cursor';
6019
6041
  if (key === 'cline') return 'cline';
6020
- if (key === 'opencode') return 'opencode';
6042
+ if (['opencode-cli', 'opencode-desktop', 'opencode-web'].includes(key)) return 'opencode';
6021
6043
  return '';
6022
6044
  }
6023
6045
 
@@ -6268,6 +6290,21 @@ function providerLabel(provider) {
6268
6290
  return labels[provider] || provider || 'unknown';
6269
6291
  }
6270
6292
 
6293
+ function sourceTypeLabel(provider, sourceType) {
6294
+ const labels = {
6295
+ 'opencode-cli-history': 'OpenCode CLI',
6296
+ 'opencode-cli-sqlite-history': 'OpenCode CLI',
6297
+ 'opencode-desktop-history': 'OpenCode Desktop',
6298
+ 'opencode-desktop-sqlite-history': 'OpenCode Desktop',
6299
+ 'opencode-web-sqlite-history': 'OpenCode Web',
6300
+ 'opencode-history': 'OpenCode',
6301
+ 'opencode-sqlite-history': 'OpenCode'
6302
+ };
6303
+ if (labels[sourceType]) return labels[sourceType];
6304
+ const providerText = providerLabel(provider);
6305
+ return sourceType ? providerText + ' / ' + sourceType : providerText;
6306
+ }
6307
+
6271
6308
  const PROVIDER_COLORS = {
6272
6309
  codex: '#2563EB',
6273
6310
  chatgpt: '#10A37F',
@@ -6296,6 +6333,7 @@ const COMPANY_LABELS = {
6296
6333
  google: 'Google',
6297
6334
  cognition: 'Cognition',
6298
6335
  windsurf: 'Cognition',
6336
+ cursor: 'Cursor',
6299
6337
  stealth: 'Stealth',
6300
6338
  unknown: 'Unknown'
6301
6339
  };
@@ -6306,6 +6344,7 @@ const COMPANY_COLORS = {
6306
6344
  google: PROVIDER_COLORS.gemini_cli,
6307
6345
  cognition: PROVIDER_COLORS.devin,
6308
6346
  windsurf: PROVIDER_COLORS.devin,
6347
+ cursor: PROVIDER_COLORS.cursor,
6309
6348
  stealth: PROVIDER_COLORS.unknown,
6310
6349
  unknown: PROVIDER_COLORS.unknown
6311
6350
  };
@@ -6788,7 +6827,7 @@ function sessionNode(item, includeExcerpt) {
6788
6827
  button.type = 'button';
6789
6828
  button.dataset.id = item.session_id || '';
6790
6829
  const title = item.title || '(untitled session)';
6791
- const source = providerLabel(item.provider) + (item.source_type ? ' / ' + item.source_type : '');
6830
+ const source = sourceTypeLabel(item.provider, item.source_type);
6792
6831
  const scope = item.repo_display || item.repo || item.scope || 'unknown repo';
6793
6832
  const folderPath = searchResultFolderPath(item);
6794
6833
  const folderLabel = folderPath || scope;
@@ -7024,7 +7063,7 @@ function renderSession(payload) {
7024
7063
  }
7025
7064
  if (sessionMetaRight) {
7026
7065
  const innerParts = [];
7027
- if (payload.source_type) innerParts.push('<span class="meta-source">' + esc(payload.source_type) + '</span>');
7066
+ if (payload.source_type) innerParts.push('<span class="meta-source">' + esc(sourceTypeLabel(payload.provider, payload.source_type)) + '</span>');
7028
7067
  const repoRaw = payload.repo_display || payload.repo || payload.scope || '';
7029
7068
  if (repoRaw) {
7030
7069
  if (innerParts.length) innerParts.push('<span class="meta-dot" aria-hidden="true">\u00b7</span>');
@@ -8276,7 +8315,7 @@ function sessionDetailsText(payload) {
8276
8315
  'Title: ' + (payload.title || '(untitled session)'),
8277
8316
  'Thread ID: ' + (payload.session_id || ''),
8278
8317
  'Provider: ' + [providerLabel(payload.provider), payload.provider].filter(Boolean).join(' / '),
8279
- payload.source_type ? 'Source type: ' + payload.source_type : '',
8318
+ payload.source_type ? 'Source: ' + sourceTypeLabel(payload.provider, payload.source_type) + ' (' + payload.source_type + ')' : '',
8280
8319
  payload.repo_display || payload.repo || payload.scope ? 'Repo or path: ' + (payload.repo_display || payload.repo || payload.scope) : '',
8281
8320
  payload.cwd ? 'Working directory: ' + payload.cwd : '',
8282
8321
  payload.started_at ? 'Started: ' + payload.started_at : '',
@@ -10282,7 +10321,10 @@ Import sources:
10282
10321
  devin-cli Devin for Terminal sessions from ~/.local/share/devin/cli/sessions.db
10283
10322
  cursor Cursor SQLite history plus newer agent-transcripts folders
10284
10323
  cline Cline task folders from VS Code/JetBrains globalStorage
10285
- opencode OpenCode JSON session/message/part storage
10324
+ opencode-cli OpenCode CLI/core SQLite database plus project JSON session/message/part storage
10325
+ opencode-desktop OpenCode Desktop app-specific SQLite database and app storage
10326
+ opencode-web OpenCode web sessions from the shared OpenCode SQLite store
10327
+ opencode OpenCode CLI, Desktop, and Web aggregate
10286
10328
  aider Aider repo-local markdown chat history
10287
10329
  all configured default local sources
10288
10330
 
@@ -10304,7 +10346,7 @@ Examples:
10304
10346
  agentlog import --source cline --since all
10305
10347
  agentlog import --source opencode --since all
10306
10348
  agentlog import --source aider --since all
10307
- agentlog import --sources codex-cli,codex-desktop,claude,claude-code-desktop,claude-workspace,gemini-cli,antigravity,devin-cli,cursor,cline,opencode,aider --since all
10349
+ agentlog import --sources codex-cli,codex-desktop,claude,claude-code-desktop,claude-workspace,gemini-cli,antigravity,devin-cli,cursor,cline,opencode-cli,opencode-desktop,opencode-web,aider --since all
10308
10350
  agentlog import --source all --since all --dry-run
10309
10351
  agentlog import --source cursor --since all --explain-skips
10310
10352
  agentlog import --source cursor --since all --explain-skips --json
package/src/config.js CHANGED
@@ -81,7 +81,10 @@ function effectiveImportSources(config) {
81
81
  const imports = config?.imports || {};
82
82
  const configured = enabledImportSources(Array.isArray(imports.sources) ? imports.sources : []);
83
83
  if (imports.autoDiscoverSources === false) return configured.length ? configured : undefined;
84
- return enabledImportSources([...new Set([...configured, ...IMPORT_SOURCE_ORDER])]);
84
+ const defaultSources = configured.includes("opencode")
85
+ ? IMPORT_SOURCE_ORDER.filter((source) => !["opencode-cli", "opencode-desktop", "opencode-web"].includes(source))
86
+ : IMPORT_SOURCE_ORDER;
87
+ return enabledImportSources([...new Set([...configured, ...defaultSources])]);
85
88
  }
86
89
 
87
90
  function saveConfig(config, env = process.env) {
package/src/doctor.js CHANGED
@@ -68,7 +68,9 @@ function sourceCoverage(discovery, cfg) {
68
68
  coverageRow("devin-cli", "Devin CLI", discovery.devinCli, configured),
69
69
  coverageRow("cursor", "Cursor", discovery.cursor, configured),
70
70
  coverageRow("cline", "Cline", discovery.cline, configured),
71
- coverageRow("opencode", "OpenCode", discovery.opencode, configured),
71
+ coverageRow("opencode-cli", "OpenCode CLI", discovery.opencodeCli, configured),
72
+ coverageRow("opencode-desktop", "OpenCode Desktop", discovery.opencodeDesktop, configured),
73
+ coverageRow("opencode-web", "OpenCode Web", discovery.opencodeWeb, configured),
72
74
  coverageRow("aider", "Aider", discovery.aider, configured)
73
75
  ];
74
76
  return rows.map((row) => ({
@@ -81,7 +83,10 @@ function coverageRow(source, label, result = {}, configured) {
81
83
  return {
82
84
  source,
83
85
  label,
84
- configured: configured.has(source) || (source === "claude-code-desktop" && configured.has("claude-desktop")) || (source === "claude-workspace" && configured.has("claude-desktop")),
86
+ configured: configured.has(source)
87
+ || (source === "claude-code-desktop" && configured.has("claude-desktop"))
88
+ || (source === "claude-workspace" && configured.has("claude-desktop"))
89
+ || (source.startsWith("opencode-") && configured.has("opencode")),
85
90
  sessions: result?.sessions || 0,
86
91
  oldest: result?.oldest || "",
87
92
  details: result?.details || {},
@@ -200,7 +205,13 @@ function parserUpdateCommand(sourceType) {
200
205
  "devin-cli-history": "devin-cli",
201
206
  "gemini-cli-history": "gemini-cli",
202
207
  "cline-task-history": "cline",
208
+ "opencode-cli-history": "opencode-cli",
209
+ "opencode-cli-sqlite-history": "opencode-cli",
210
+ "opencode-desktop-history": "opencode-desktop",
211
+ "opencode-desktop-sqlite-history": "opencode-desktop",
212
+ "opencode-web-sqlite-history": "opencode-web",
203
213
  "opencode-history": "opencode",
214
+ "opencode-sqlite-history": "opencode",
204
215
  "aider-chat-history": "aider",
205
216
  "antigravity-history": "antigravity"
206
217
  }[canonicalSourceType(sourceType)];
@@ -76,11 +76,35 @@ const PROVIDER_ADAPTERS = [
76
76
  {
77
77
  source: "opencode",
78
78
  provider: "opencode",
79
- sourceType: "opencode-history",
79
+ sourceType: "opencode-cli-history",
80
80
  label: "OpenCode",
81
81
  run: ({ helpers, since, options, env }) =>
82
82
  helpers.importStructuredProvider("opencode", helpers.readOpenCodeSessions(env, { ...options, since }), since, options, env)
83
83
  },
84
+ {
85
+ source: "opencode-cli",
86
+ provider: "opencode",
87
+ sourceType: "opencode-cli-history",
88
+ label: "OpenCode CLI",
89
+ run: ({ helpers, since, options, env }) =>
90
+ helpers.importStructuredProvider("opencode", helpers.readOpenCodeSessions(env, { ...options, since, openCodeKind: "cli" }), since, options, env)
91
+ },
92
+ {
93
+ source: "opencode-desktop",
94
+ provider: "opencode",
95
+ sourceType: "opencode-desktop-history",
96
+ label: "OpenCode Desktop",
97
+ run: ({ helpers, since, options, env }) =>
98
+ helpers.importStructuredProvider("opencode", helpers.readOpenCodeSessions(env, { ...options, since, openCodeKind: "desktop" }), since, options, env)
99
+ },
100
+ {
101
+ source: "opencode-web",
102
+ provider: "opencode",
103
+ sourceType: "opencode-web-sqlite-history",
104
+ label: "OpenCode Web",
105
+ run: ({ helpers, since, options, env }) =>
106
+ helpers.importStructuredProvider("opencode", helpers.readOpenCodeSessions(env, { ...options, since, openCodeKind: "web" }), since, options, env)
107
+ },
84
108
  {
85
109
  source: "aider",
86
110
  provider: "aider",