opencode-manager 0.3.1 → 0.4.0

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.
@@ -5,15 +5,47 @@ Overview
5
5
  --------
6
6
  - Purpose: Inspect, filter, and clean OpenCode metadata stored on disk.
7
7
  - Scope: Lists projects and sessions from local storage; supports filtering, search, interactive selection and deletion, and quick navigation between views.
8
- - UI: Terminal UI built with @opentui/react.
8
+ - Dual interface: Terminal UI (TUI) built with @opentui/react for interactive use, plus a Commander-based CLI for scripting and automation.
9
9
 
10
10
  Architecture
11
11
  ------------
12
- - Entry: `opencode/src/opencode-tui.tsx` main TUI app and panels.
13
- - Data layer: `opencode/src/lib/opencode-data.ts` — reads/writes metadata JSON, computes derived fields, formatting helpers.
14
- - Scripts: `opencode/package.json` → `bun run tui` runs the app.
15
- - CLI wrapper: `opencode/manage_opencode_projects.py` preserves the legacy entry point, resolves Bun (`--bun` overrides PATH), sets `--root` (defaults to `~/.local/share/opencode`), and forwards any extra args after `--` directly to the TUI.
16
- - Spec diff script: `opencode/opencode-gen.sh` shells out to `opencode generate`, saves the JSON spec under `~/repos/research/opencode/opencode-<version>-spec.json`, and diffs it against the previous snapshot (prefers `delta`, falls back to `diff`).
12
+ The codebase follows a dual-mode architecture with shared libraries:
13
+
14
+ ### Entry Points
15
+ - `src/bin/opencode-manager.ts` Main entrypoint; routes to CLI or TUI based on subcommand.
16
+ - CLI subcommands: `projects`, `sessions`, `chat`, `tokens` dynamic import of CLI module
17
+ - TUI mode: no subcommand, or explicit `tui` subcommand → dynamic import of TUI module
18
+
19
+ ### CLI Module (`src/cli/`)
20
+ - `index.ts` — Commander program with global options (`--root`, `--format`, `--limit`, `--sort`, `--yes`, `--dry-run`, `--quiet`, `--clipboard`, `--backup-dir`); exports `runCLI(args)`.
21
+ - `commands/` — Subcommand implementations:
22
+ - `projects.ts` — `list`, `delete` with dry-run/backup support
23
+ - `sessions.ts` — `list`, `delete`, `rename`, `move`, `copy`
24
+ - `chat.ts` — `list`, `show`, `search` with clipboard support
25
+ - `tokens.ts` — `session`, `project`, `global` token summaries
26
+ - `tui.ts` — Launches TUI from CLI context
27
+ - `formatters/` — Output formatters:
28
+ - `json.ts` — JSON with envelope (`{ok, data, meta}`)
29
+ - `ndjson.ts` — Newline-delimited JSON for streaming
30
+ - `table.ts` — Column-aligned tables with truncation
31
+ - `output.ts` — Format selector routing by `--format` flag
32
+ - `errors.ts` — Exit codes (0-4), error classes, validation helpers
33
+ - `resolvers.ts` — ID resolution with exact/prefix matching
34
+ - `backup.ts` — Pre-deletion backup to timestamped directories
35
+
36
+ ### TUI Module (`src/tui/`)
37
+ - `app.tsx` — Main TUI app with Projects, Sessions, Chat panels
38
+ - `index.tsx` — Exports `launchTUI(options)`, `bootstrap(args)`
39
+ - `args.ts` — TUI-specific arg parsing (`--root`, `--help`)
40
+
41
+ ### Shared Libraries (`src/lib/`)
42
+ - `opencode-data.ts` — Data layer: load/save metadata, compute tokens, filtering, formatting
43
+ - `search.ts` — Fuzzy search via fast-fuzzy (sessions) and tokenized search (projects)
44
+ - `clipboard.ts` — Cross-platform clipboard (`pbcopy`/`xclip`)
45
+
46
+ ### Other Files
47
+ - `manage_opencode_projects.py` — Legacy wrapper; routes CLI/TUI via `src/bin/opencode-manager.ts`
48
+ - `opencode-gen.sh` — Spec diff script for OpenCode JSON specs
17
49
 
18
50
  Metadata Layout & Helpers
19
51
  -------------------------
@@ -37,6 +69,8 @@ Key Features
37
69
  - Rename sessions inline (Shift+R) with validation.
38
70
  - Move sessions to another project (M) with project selector.
39
71
  - Copy sessions to another project (P) with new session ID generation.
72
+ - View chat history (V) with message navigation and clipboard support.
73
+ - Search chat content (F) across sessions with fuzzy matching.
40
74
  - Projects ↔ Sessions workflow
41
75
  - Pressing Enter on a project jumps to the Sessions tab with the project filter set; status text confirms the active filter.
42
76
  - `C` clears the filter (and notifies the user) so global searches go back to all sessions.
@@ -53,6 +87,7 @@ Key Features
53
87
 
54
88
  Work Completed
55
89
  --------------
90
+ ### TUI Features
56
91
  - Switched Projects list labels to show path instead of project ID; kept ID in the details panel.
57
92
  - Sessions list uses session title prominently; added title to details; updated onSelect/Enter status lines to show title and ID.
58
93
  - Redesigned Help screen into two columns with color-coded sections and key chips; removed wall-of-text effect.
@@ -69,36 +104,79 @@ Work Completed
69
104
  - Added session move feature (M): select target project, relocate session JSON, update projectID field.
70
105
  - Added session copy feature (P): select target project, create new session with generated ID, preserve original.
71
106
 
107
+ ### CLI Implementation (Phase 1-4)
108
+ - Created Commander-based CLI with global options and subcommand routing.
109
+ - Refactored entrypoint to route CLI vs TUI via dynamic imports.
110
+ - Extracted shared libraries (`clipboard.ts`, `search.ts`) from TUI for CLI reuse.
111
+ - Implemented output formatters: JSON with envelope, NDJSON for streaming, table with truncation.
112
+ - Projects commands: `list` (with `--missing-only`, `--search`), `delete` (with `--dry-run`, `--backup-dir`).
113
+ - Sessions commands: `list` (with `--project`, `--search`, fuzzy matching), `delete`, `rename`, `move`, `copy`.
114
+ - Chat commands: `list` (with `--include-parts`), `show` (by `--message` or `--index`, with `--clipboard`), `search`.
115
+ - Tokens commands: `session`, `project`, `global` summaries with breakdown tables.
116
+ - Error handling with typed exit codes (0-4) and consistent error formatting.
117
+ - ID resolution helpers with exact and prefix matching.
118
+ - Pre-deletion backup to timestamped directories.
119
+ - Comprehensive test suite: 350+ tests covering formatters, commands, resolvers, errors, exit codes.
120
+
72
121
  How To Run
73
122
  ----------
74
- - Zero-install via npm: `bunx opencode-manager [--root /path/to/storage]` (preferred).
75
- - Local dev: `bun run tui [-- --root /path/to/storage]`.
76
- - Legacy launcher: `./manage_opencode_projects.py [--root PATH] [--bun /path/to/bun] [-- ...extra TUI args]` keeps older automation working while delegating to Bun.
77
- - Keys:
78
- - Global: `Tab`/`1`/`2` switch tabs, `/` search, `X` clear search, `R` reload, `Q` quit, `?` help
79
- - Projects: `Space` select, `A` select all, `M` toggle missing, `D` delete, `Enter` view sessions
80
- - Sessions: `Space` select, `S` sort, `D` delete, `Y` copy ID, `Shift+R` rename, `M` move, `P` copy, `C` clear filter
81
- - Optional tmux usage (when permitted): `tmux new -s opencode-tui 'bun run tui'`
82
- - CLI help: `bun run tui -- --help` (or `bunx opencode-manager -- --help`, or `manage_opencode_projects.py -- --help`) prints the built-in usage block with key bindings.
123
+ ### TUI Mode (Interactive)
124
+ - Zero-install: `bunx opencode-manager [--root /path/to/storage]` (preferred)
125
+ - Local dev: `bun run tui [-- --root /path/to/storage]`
126
+ - Legacy launcher: `./manage_opencode_projects.py [--bun /path/to/bun]`
127
+ - TUI help: `bunx opencode-manager --help` shows key bindings
128
+
129
+ ### CLI Mode (Scripting)
130
+ - Projects: `bunx opencode-manager projects list --format json`
131
+ - Sessions: `bunx opencode-manager sessions list --project <id> --limit 10`
132
+ - Chat: `bunx opencode-manager chat search --query "fix bug" --format ndjson`
133
+ - Tokens: `bunx opencode-manager tokens global --format table`
134
+ - Delete with backup: `bunx opencode-manager sessions delete --session <id> --yes --backup-dir ./backups`
135
+ - Dry run: `bunx opencode-manager projects delete --id <id> --dry-run`
136
+
137
+ ### Global CLI Options
138
+ - `--root <path>` — Metadata store root (default: `~/.local/share/opencode`)
139
+ - `--format <json|ndjson|table>` — Output format (default: `table`)
140
+ - `--limit <n>` — Max records (default: 200)
141
+ - `--sort <updated|created>` — Sort order (default: `updated`)
142
+ - `--yes` — Skip confirmation for destructive ops
143
+ - `--dry-run` — Preview changes without executing
144
+ - `--quiet` — Suppress non-essential output
145
+ - `--clipboard` — Copy output to clipboard
146
+ - `--backup-dir <path>` — Backup before deletion
147
+
148
+ ### Exit Codes
149
+ - 0: Success
150
+ - 1: Internal error
151
+ - 2: Usage/validation error (missing `--yes`, bad args)
152
+ - 3: Resource not found (invalid project/session/message ID)
153
+ - 4: File operation error (backup/delete failure)
154
+
155
+ ### TUI Keys
156
+ - Global: `Tab`/`1`/`2` switch tabs, `/` search, `X` clear search, `R` reload, `Q` quit, `?/H` help
157
+ - Projects: `Space` select, `A` select all, `M` toggle missing, `D` delete, `Enter` view sessions, `Esc` clear selection
158
+ - Sessions: `Space` select, `A` select all, `S` sort, `V` view chat, `F` search chats, `Shift+R` rename, `M` move, `P` copy, `Y` copy ID, `C` clear filter, `D` delete, `Enter` details, `Esc` clear selection
159
+
160
+ ### Optional
161
+ - tmux: `tmux new -s opencode-manager 'bun run tui'`
83
162
 
84
163
  Packaging & Publish Checklist
85
164
  -----------------------------
86
- 1. Install dependencies with `bun install` (Bun v1.1+ only).
165
+ 1. Install dependencies with `bun install` (Bun v1.3+ only).
87
166
  2. Type-check via `bun run typecheck` (runs `tsc --noEmit`).
88
167
  3. Update the version in `package.json` as needed.
89
168
  4. Run `npm publish` (package exposes the Bun-native `opencode-manager` bin with public access).
90
169
 
91
170
  Outstanding Recommendations (Not Yet Implemented)
92
171
  -------------------------------------------------
93
- - UI polish
172
+ - TUI polish
94
173
  - Colorize project state in list labels (e.g., green for present, red for missing, gray for unknown).
95
174
  - Show a small timestamp snippet for Projects rows (created).
96
175
  - Add tiny icons or color accents to distinguish created vs updated descriptions in Sessions.
97
176
  - Add per-view mini legends with colored key chips under the panels (Projects/Sessions), consistent with the Help styling.
98
- - Show filtered counts (e.g., Showing X of Y).
177
+ - Show filtered counts (e.g., "Showing X of Y").
99
178
  - Search enhancements
100
- - Optional fuzzy matching; toggle to include/exclude `directory` in Sessions/Projects search for more control.
101
- - Persist search and sort preferences per tab (and optionally per project filter) during the app run.
179
+ - Optional fuzzy matching toggle in TUI; persist search and sort preferences per tab.
102
180
  - Save last-used search/sort to a small state file and restore on next launch.
103
181
  - Accessibility & layout
104
182
  - Ensure all active/inactive/focused states have adequate contrast and consistent highlight styles.
@@ -106,10 +184,12 @@ Outstanding Recommendations (Not Yet Implemented)
106
184
  - Performance
107
185
  - Debounce UI reactions to large search queries; short-circuit expensive filters when query is empty.
108
186
  - Testing
109
- - Add unit coverage for opencode-data helpers (formatting, parsing, sorting).
110
- - Add basic snapshot/E2E tests for rendering key panels and Help using a headless renderer (if available for @opentui).
111
- - Packaging/Docs
112
- - Add a README section specific to the TUI tool, with a short demo, common actions, and troubleshooting.
187
+ - Add integration tests for CLI commands with real fixture data.
188
+ - Add basic snapshot/E2E tests for TUI rendering (if headless renderer available for @opentui).
189
+ - CLI enhancements
190
+ - Shell completion scripts (bash/zsh/fish).
191
+ - `--json-lines` alias for `--format ndjson` compatibility.
192
+ - Template/profile support for common option combinations.
113
193
 
114
194
  Notes
115
195
  -----
package/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
 
4
4
  # OpenCode Metadata Manager
5
5
 
6
- Terminal UI for inspecting, filtering, and pruning OpenCode metadata stored on disk. The app is written in TypeScript, runs on Bun, and renders with [`@opentui/react`](https://github.com/open-tui/opentui).
6
+ Terminal UI for inspecting, filtering, and pruning OpenCode metadata stored on disk. The app is written in TypeScript, runs on Bun, and renders with [`@opentui/react`](https://github.com/sst/opentui).
7
7
 
8
8
  ## Screenshots
9
9
 
@@ -23,7 +23,9 @@ Terminal UI for inspecting, filtering, and pruning OpenCode metadata stored on d
23
23
  - List both OpenCode projects and sessions from a local metadata root.
24
24
  - Filter by "missing only", bulk-select, and delete metadata safely.
25
25
  - Jump from a project directly to its sessions and keep contextual filters.
26
- - Global search bar (`/` to focus, `Enter` to apply, `Esc` or `X` to clear).
26
+ - **Fuzzy search** across session titles and metadata (`/` to focus, results ranked by relevance).
27
+ - **View session chat history** with full conversation context (`V` to open viewer).
28
+ - **Search across all chat content** in sessions within a project (`F` to search).
27
29
  - Rename sessions inline (`Shift+R`) with title validation.
28
30
  - Move sessions between projects (`M`) preserving session ID.
29
31
  - Copy sessions to other projects (`P`) with new session ID generation.
@@ -56,7 +58,7 @@ The TUI displays token telemetry from OpenCode's stored message data at three le
56
58
  - Large datasets are handled with lazy computation to avoid UI freezes.
57
59
 
58
60
  ## Requirements
59
- - [Bun](https://bun.sh) **1.1.0+** (developed/tested on 1.2.x).
61
+ - [Bun](https://bun.sh) **1.3.0+** (developed/tested on 1.3.x).
60
62
  - A node-compatible terminal (truecolor improves readability but is optional).
61
63
 
62
64
  ## Installation
@@ -73,6 +75,13 @@ bunx opencode-manager --help
73
75
  The repository ships with a focused `.gitignore`, keeping `node_modules/`, caches, and logs out of Git history.
74
76
 
75
77
  ## Usage
78
+
79
+ The manager provides both a Terminal UI (TUI) and a scriptable CLI interface.
80
+
81
+ ### Terminal UI (TUI)
82
+
83
+ The TUI is the default interface when no subcommand is provided:
84
+
76
85
  ```bash
77
86
  # Preferred: zero-install command
78
87
  bunx opencode-manager --root ~/.local/share/opencode
@@ -85,9 +94,326 @@ bun run tui -- --root ~/.local/share/opencode
85
94
  ```
86
95
 
87
96
  Keyboard reference:
88
- - **Global**: `Tab`/`1`/`2` switch tabs, `/` search, `X` clear search, `R` reload, `Q` quit, `?` help.
89
- - **Projects**: `Space` toggle selection, `A` select all, `M` missing-only filter, `D` delete, `Enter` jump to Sessions.
90
- - **Sessions**: `Space` select, `S` toggle sort, `D` delete, `Y` copy ID, `Shift+R` rename, `M` move to project, `P` copy to project, `C` clear filter.
97
+ - **Global**: `Tab`/`1`/`2` switch tabs, `/` search (fuzzy), `X` clear search, `R` reload, `Q` quit, `?/H` help.
98
+ - **Projects**: `Space` toggle selection, `A` select all, `M` missing-only filter, `D` delete, `Enter` jump to Sessions, `Esc` clear selection.
99
+ - **Sessions**: `Space` select, `A` select all, `S` toggle sort, `V` view chat, `F` search chats, `D` delete, `Y` copy ID, `Shift+R` rename, `M` move, `P` copy, `C` clear filter, `Enter` details, `Esc` clear selection.
100
+ - **Chat Search**: Type query + `Enter` to search, `Up/Down` navigate, `Enter` opens result, `Esc` close.
101
+ - **Chat Viewer**: `Esc` close, `Up/Down` navigate, `PgUp/PgDn` jump 10, `Home/End` first/last, `Y` copy message.
102
+
103
+ ### Command Line Interface (CLI)
104
+
105
+ The CLI provides scriptable access to all management operations. Use subcommands to list, search, and modify metadata.
106
+
107
+ #### Global Options
108
+
109
+ | Option | Default | Description |
110
+ |--------|---------|-------------|
111
+ | `-r, --root <path>` | `~/.local/share/opencode` | Root path to OpenCode metadata store |
112
+ | `-f, --format <fmt>` | `table` | Output format: `json`, `ndjson`, or `table` |
113
+ | `-l, --limit <n>` | `200` | Maximum number of records to return |
114
+ | `--sort <order>` | `updated` | Sort order: `updated` or `created` |
115
+ | `-y, --yes` | `false` | Skip confirmation prompts for destructive operations |
116
+ | `-n, --dry-run` | `false` | Preview changes without executing |
117
+ | `-q, --quiet` | `false` | Suppress non-essential output |
118
+ | `-c, --clipboard` | `false` | Copy output to clipboard |
119
+ | `--backup-dir <path>` | — | Directory for backup copies before deletion |
120
+
121
+ #### Commands Overview
122
+
123
+ ```
124
+ opencode-manager
125
+ ├── projects
126
+ │ ├── list List projects (--missing-only, --search)
127
+ │ └── delete Delete project metadata (--id, --yes, --dry-run, --backup-dir)
128
+ ├── sessions
129
+ │ ├── list List sessions (--project, --search)
130
+ │ ├── delete Delete session metadata (--session, --yes, --dry-run, --backup-dir)
131
+ │ ├── rename Rename a session (--session, --title)
132
+ │ ├── move Move session to another project (--session, --to)
133
+ │ └── copy Copy session to another project (--session, --to)
134
+ ├── chat
135
+ │ ├── list List messages in a session (--session, --include-parts)
136
+ │ ├── show Show a specific message (--session, --message or --index, --clipboard)
137
+ │ └── search Search chat content across sessions (--query, --project)
138
+ ├── tokens
139
+ │ ├── session Show token usage for a session (--session)
140
+ │ ├── project Show token usage for a project (--project)
141
+ │ └── global Show global token usage
142
+ └── tui Launch the Terminal UI
143
+ ```
144
+
145
+ #### TUI Subcommand
146
+
147
+ The `tui` subcommand explicitly launches the Terminal UI. This is equivalent to running `opencode-manager` with no subcommand:
148
+
149
+ ```bash
150
+ # These are equivalent:
151
+ opencode-manager
152
+ opencode-manager tui
153
+ opencode-manager tui --root ~/.local/share/opencode
154
+ ```
155
+
156
+ Use the explicit `tui` subcommand when you want to be clear about intent in scripts or when combining with other options. Note that `tui --help` shows the TUI help screen (key bindings), not Commander CLI help.
157
+
158
+ #### Help System
159
+
160
+ The manager uses a dual help system depending on context:
161
+
162
+ | Command | Help Type | Content |
163
+ |---------|-----------|---------|
164
+ | `opencode-manager --help` | TUI help | Key bindings and TUI usage |
165
+ | `opencode-manager -h` | TUI help | Same as `--help` |
166
+ | `opencode-manager tui --help` | TUI help | Key bindings (routes to TUI help) |
167
+ | `opencode-manager projects --help` | CLI help | Commander subcommand help |
168
+ | `opencode-manager sessions --help` | CLI help | Commander subcommand help |
169
+ | `opencode-manager chat --help` | CLI help | Commander subcommand help |
170
+ | `opencode-manager tokens --help` | CLI help | Commander subcommand help |
171
+
172
+ **Why?** The root command defaults to launching the TUI, so `--help` shows TUI-relevant information (key bindings). CLI subcommands use standard Commander.js help showing options and usage.
173
+
174
+ To see all CLI subcommands, use any subcommand with `--help`:
175
+
176
+ ```bash
177
+ # Shows TUI key bindings
178
+ opencode-manager --help
179
+
180
+ # Shows CLI subcommand help with options
181
+ opencode-manager projects --help
182
+ opencode-manager projects list --help
183
+ ```
184
+
185
+ #### Output Format Examples
186
+
187
+ The CLI supports three output formats via `--format`:
188
+
189
+ **Table (default)** — Human-readable columnar output:
190
+
191
+ ```bash
192
+ $ bunx opencode-manager projects list --limit 3
193
+
194
+ # State Path Project ID Created
195
+ ---- ----- -------------------------------------------------- ------------------------ ----------------
196
+ 1 ✓ /home/user/repos/my-app a1b2c3d4e5f6g7h8i9j0k1l2 2026-01-04 09:20
197
+ 2 ✓ /home/user/repos/api-server b2c3d4e5f6g7h8i9j0k1l2m3 2026-01-03 14:15
198
+ 3 ✗ /home/user/repos/deleted-project c3d4e5f6g7h8i9j0k1l2m3n4 2025-12-28 10:30
199
+ ```
200
+
201
+ **JSON** — Structured output with metadata envelope:
202
+
203
+ ```bash
204
+ $ bunx opencode-manager sessions list --project prj_abc123 --format json --limit 2
205
+
206
+ {
207
+ "ok": true,
208
+ "data": [
209
+ {
210
+ "index": 1,
211
+ "sessionId": "sess_xyz789",
212
+ "projectId": "prj_abc123",
213
+ "directory": "/home/user/repos/my-app",
214
+ "title": "Refactor auth module",
215
+ "version": "1.1.4",
216
+ "updatedAt": "2026-01-05T14:32:00.000Z",
217
+ "createdAt": "2026-01-03T09:15:00.000Z"
218
+ },
219
+ {
220
+ "index": 2,
221
+ "sessionId": "sess_uvw456",
222
+ "projectId": "prj_abc123",
223
+ "directory": "/home/user/repos/my-app",
224
+ "title": "Add unit tests",
225
+ "version": "1.1.4",
226
+ "updatedAt": "2026-01-04T16:45:00.000Z",
227
+ "createdAt": "2026-01-02T11:20:00.000Z"
228
+ }
229
+ ],
230
+ "meta": {
231
+ "count": 2,
232
+ "limit": 2
233
+ }
234
+ }
235
+ ```
236
+
237
+ JSON output auto-detects your terminal: pretty-printed with indentation when output goes to a TTY, compact single-line when piped to another command.
238
+
239
+ The `meta` object contains:
240
+ - `count` — Number of items in the `data` array
241
+ - `limit` — The limit that was applied (if `--limit` was specified)
242
+
243
+ **NDJSON** — Newline-delimited JSON for streaming/piping:
244
+
245
+ ```bash
246
+ $ bunx opencode-manager sessions list --format ndjson --limit 2
247
+
248
+ {"index":1,"sessionId":"ses_abc123","projectId":"prj_xyz789","title":"Feature implementation","createdAt":"2026-01-06T10:30:00.000Z"}
249
+ {"index":2,"sessionId":"ses_def456","projectId":"prj_xyz789","title":"Bug fix session","createdAt":"2026-01-06T11:15:00.000Z"}
250
+ ```
251
+
252
+ Each line is a complete JSON object, ideal for piping to `jq` or line-by-line processing. For single-record commands like `tokens global`, NDJSON outputs one line with the same structure as the JSON `data` field.
253
+
254
+ **Piping examples:**
255
+
256
+ ```bash
257
+ # Count sessions per project
258
+ bunx opencode-manager sessions list --format ndjson | jq -s 'group_by(.projectId) | map({project: .[0].projectId, count: length})'
259
+
260
+ # Get all session IDs as plain text
261
+ bunx opencode-manager sessions list --format json | jq -r '.data[].sessionId'
262
+
263
+ # Export chat history to file
264
+ bunx opencode-manager chat list --session sess_xyz789 --include-parts --format json > chat-export.json
265
+
266
+ # Dry-run delete to preview affected files
267
+ bunx opencode-manager projects delete --id prj_old --dry-run --format json
268
+ ```
269
+
270
+ #### Token Output Format
271
+
272
+ Token commands (`tokens session`, `tokens project`, `tokens global`) return structured summaries of token usage.
273
+
274
+ **Session tokens** — Single session summary with `kind` discriminator:
275
+
276
+ ```bash
277
+ $ bunx opencode-manager tokens session --session sess_xyz789 --format json
278
+
279
+ # When token data is available (kind: "known"):
280
+ {
281
+ "ok": true,
282
+ "data": {
283
+ "kind": "known",
284
+ "tokens": {
285
+ "input": 12500,
286
+ "output": 8750,
287
+ "reasoning": 2100,
288
+ "cacheRead": 4200,
289
+ "cacheWrite": 950,
290
+ "total": 28500
291
+ }
292
+ }
293
+ }
294
+
295
+ # When token data is unavailable (kind: "unknown"):
296
+ {
297
+ "ok": true,
298
+ "data": {
299
+ "kind": "unknown",
300
+ "reason": "no_messages"
301
+ }
302
+ }
303
+ ```
304
+
305
+ The `reason` field indicates why tokens are unavailable:
306
+ - `"missing"` — Session metadata file not found
307
+ - `"parse_error"` — Token data couldn't be parsed
308
+ - `"no_messages"` — Session has no messages with token data
309
+
310
+ **Project/Global tokens** — Aggregate summary across multiple sessions:
311
+
312
+ ```bash
313
+ $ bunx opencode-manager tokens project --project prj_abc123 --format json
314
+
315
+ {
316
+ "ok": true,
317
+ "data": {
318
+ "total": {
319
+ "kind": "known",
320
+ "tokens": { "input": 125000, "output": 98000, "reasoning": 32000, "cacheRead": 15000, "cacheWrite": 6500, "total": 276500 }
321
+ },
322
+ "knownOnly": { "input": 125000, "output": 98000, "reasoning": 32000, "cacheRead": 15000, "cacheWrite": 6500, "total": 276500 },
323
+ "unknownSessions": 2
324
+ }
325
+ }
326
+ ```
327
+
328
+ Aggregate summary fields:
329
+ - `total` — Combined `TokenSummary` (same structure as session tokens)
330
+ - `knownOnly` — Token breakdown from sessions with available data only (omitted if all unknown)
331
+ - `unknownSessions` — Count of sessions where token data was unavailable
332
+
333
+ **Note:** The `tokens` commands require exact IDs (no prefix matching). Use full session/project IDs as shown in `sessions list` or `projects list` output.
334
+
335
+ #### Exit Codes
336
+
337
+ | Code | Meaning |
338
+ |------|---------|
339
+ | 0 | Success |
340
+ | 1 | General error |
341
+ | 2 | Usage error (missing required options, invalid arguments) |
342
+ | 3 | Resource not found (invalid project/session/message ID) |
343
+ | 4 | File operation error (backup or delete failure) |
344
+
345
+ #### ID Resolution
346
+
347
+ Most commands accept ID prefixes for convenience. The CLI will match the prefix to a unique ID:
348
+
349
+ ```bash
350
+ # Full ID
351
+ opencode-manager sessions delete --session sess_01JGNPE16DT1JX1YA8KTPMDRW3
352
+
353
+ # Prefix match (if unique)
354
+ opencode-manager sessions delete --session sess_01JGN
355
+
356
+ # Ambiguous prefix (fails with error listing matches)
357
+ opencode-manager sessions delete --session sess_01
358
+ # Error: Multiple sessions match prefix 'sess_01': sess_01JGN..., sess_01ABC...
359
+ ```
360
+
361
+ **Commands supporting prefix matching:**
362
+ - `projects delete --id`
363
+ - `sessions delete --session`, `sessions rename --session`, `sessions move --session`, `sessions copy --session`
364
+ - `sessions move --to`, `sessions copy --to` (project ID)
365
+ - `chat list --session`, `chat show --session`
366
+ - `chat show --message` (also supports 1-based `--index`)
367
+
368
+ **Commands requiring exact IDs:**
369
+ - `tokens session --session` — requires full session ID
370
+ - `tokens project --project` — requires full project ID
371
+
372
+ #### Clipboard Support
373
+
374
+ The `--clipboard` flag (or `Y` key in the TUI) copies content to the system clipboard. Platform support:
375
+
376
+ | Platform | Tool Required | Notes |
377
+ |----------|---------------|-------|
378
+ | **macOS** | None | Uses built-in `pbcopy` |
379
+ | **Linux** | `xclip` | Install via `apt install xclip` or equivalent |
380
+ | **Windows** | — | Not currently supported |
381
+
382
+ On Linux, if `xclip` is not installed, clipboard operations will fail silently in the TUI or show an error message in the CLI.
383
+
384
+ #### Delete Semantics
385
+
386
+ Delete commands (`projects delete`, `sessions delete`) remove **metadata files only**:
387
+
388
+ | Command | Deletes | Preserves |
389
+ |---------|---------|-----------|
390
+ | `projects delete` | Project metadata (`storage/project/<id>.json`) | Sessions, messages, parts |
391
+ | `sessions delete` | Session metadata (`storage/sessions/<projectId>.json` entry) | Message and part files |
392
+
393
+ **Safety features:**
394
+
395
+ - **Confirmation required** — Destructive operations require `--yes` flag or interactive confirmation:
396
+ ```bash
397
+ # Will prompt for confirmation (interactive)
398
+ opencode-manager projects delete --id prj_abc123
399
+
400
+ # Skip confirmation (scripts)
401
+ opencode-manager projects delete --id prj_abc123 --yes
402
+ ```
403
+
404
+ - **Dry-run preview** — Use `--dry-run` to see what would be deleted without making changes:
405
+ ```bash
406
+ opencode-manager sessions delete --session sess_xyz789 --dry-run
407
+ # Output shows files that would be affected
408
+ ```
409
+
410
+ - **Backup before delete** — Use `--backup-dir` to copy files before deletion:
411
+ ```bash
412
+ opencode-manager projects delete --id prj_abc123 --backup-dir ./backups --yes
413
+ # Creates backup, then deletes original
414
+ ```
415
+
416
+ **Note:** Session deletion leaves associated chat message files intact. To fully remove a session's data, you would need to manually delete the message files from `storage/message/<sessionId>/`.
91
417
 
92
418
  ## Development Workflow
93
419
  1. Install dependencies with `bun install`.
@@ -99,7 +425,9 @@ Keyboard reference:
99
425
  ```
100
426
  src/
101
427
  bin/opencode-manager.ts # Bun-native CLI shim exposed as the bin entry
102
- opencode-tui.tsx # Main TUI implementation (panels, search, help)
428
+ tui/
429
+ app.tsx # Main TUI implementation (panels, search, help)
430
+ index.tsx # TUI entrypoint with launchTUI(), parseArgs(), bootstrap()
103
431
  manage_opencode_projects.py # Legacy Python launcher for backwards compatibility
104
432
  opencode-gen.sh # Spec snapshot helper script
105
433
  PROJECT-SUMMARY.md # Extended design notes & roadmap
package/bun.lock CHANGED
@@ -7,6 +7,8 @@
7
7
  "dependencies": {
8
8
  "@opentui/core": "^0.1.44",
9
9
  "@opentui/react": "^0.1.44",
10
+ "commander": "^12.0.0",
11
+ "fast-fuzzy": "^1.12.0",
10
12
  "react": "^19.0.0",
11
13
  },
12
14
  "devDependencies": {
@@ -123,6 +125,8 @@
123
125
 
124
126
  "bun-webgpu-win32-x64": ["bun-webgpu-win32-x64@0.1.4", "", { "os": "win32", "cpu": "x64" }, "sha512-Z5yAK28xrcm8Wb5k7TZ8FJKpOI/r+aVCRdlHYAqI2SDJFN3nD4mJs900X6kNVmG/xFzb5yOuKVYWGg+6ZXWbyA=="],
125
127
 
128
+ "commander": ["commander@12.1.0", "", {}, "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA=="],
129
+
126
130
  "csstype": ["csstype@3.1.3", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="],
127
131
 
128
132
  "event-target-shim": ["event-target-shim@5.0.1", "", {}, "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ=="],
@@ -131,10 +135,14 @@
131
135
 
132
136
  "exif-parser": ["exif-parser@0.1.12", "", {}, "sha512-c2bQfLNbMzLPmzQuOr8fy0csy84WmwnER81W88DzTp9CYNPJ6yzOj2EZAh9pywYpqHnshVLHQJ8WzldAyfY+Iw=="],
133
137
 
138
+ "fast-fuzzy": ["fast-fuzzy@1.12.0", "", { "dependencies": { "graphemesplit": "^2.4.1" } }, "sha512-sXxGgHS+ubYpsdLnvOvJ9w5GYYZrtL9mkosG3nfuD446ahvoWEsSKBP7ieGmWIKVLnaxRDgUJkZMdxRgA2Ni+Q=="],
139
+
134
140
  "file-type": ["file-type@16.5.4", "", { "dependencies": { "readable-web-to-node-stream": "^3.0.0", "strtok3": "^6.2.4", "token-types": "^4.1.1" } }, "sha512-/yFHK0aGjFEgDJjEKP0pWCplsPFPhwyfwevf/pVxiN0tmE4L9LmwWxWukdJSHdoCli4VgQLehjJtwQBnqmsKcw=="],
135
141
 
136
142
  "gifwrap": ["gifwrap@0.10.1", "", { "dependencies": { "image-q": "^4.0.0", "omggif": "^1.0.10" } }, "sha512-2760b1vpJHNmLzZ/ubTtNnEx5WApN/PYWJvXvgS+tL1egTTthayFYIQQNi136FLEDcN/IyEY2EcGpIITD6eYUw=="],
137
143
 
144
+ "graphemesplit": ["graphemesplit@2.6.0", "", { "dependencies": { "js-base64": "^3.6.0", "unicode-trie": "^2.0.0" } }, "sha512-rG9w2wAfkpg0DILa1pjnjNfucng3usON360shisqIMUBw/87pojcBSrHmeE4UwryAuBih7g8m1oilf5/u8EWdQ=="],
145
+
138
146
  "ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="],
139
147
 
140
148
  "image-q": ["image-q@4.0.0", "", { "dependencies": { "@types/node": "16.9.1" } }, "sha512-PfJGVgIfKQJuq3s0tTDOKtztksibuUEbJQIYT3by6wctQo+Rdlh7ef4evJ5NCdxY4CfMbvFkocEwbl4BF8RlJw=="],
@@ -143,11 +151,13 @@
143
151
 
144
152
  "jpeg-js": ["jpeg-js@0.4.4", "", {}, "sha512-WZzeDOEtTOBK4Mdsar0IqEU5sMr3vSV2RqkAIzUEV2BHnUfKGyswWFPFwK5EeDo93K3FohSHbLAjj0s1Wzd+dg=="],
145
153
 
154
+ "js-base64": ["js-base64@3.7.8", "", {}, "sha512-hNngCeKxIUQiEUN3GPJOkz4wF/YvdUdbNL9hsBcMQTkKzboD7T/q3OYOuuPZLUE6dBxSGpwhk5mwuDud7JVAow=="],
155
+
146
156
  "mime": ["mime@3.0.0", "", { "bin": "cli.js" }, "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A=="],
147
157
 
148
158
  "omggif": ["omggif@1.0.10", "", {}, "sha512-LMJTtvgc/nugXj0Vcrrs68Mn2D1r0zf630VNtqtpI1FEO7e+O9FP4gqs9AcnBaSEeoHIPm28u6qgPR0oyEpGSw=="],
149
159
 
150
- "pako": ["pako@1.0.11", "", {}, "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw=="],
160
+ "pako": ["pako@0.2.9", "", {}, "sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA=="],
151
161
 
152
162
  "parse-bmfont-ascii": ["parse-bmfont-ascii@1.0.6", "", {}, "sha512-U4RrVsUFCleIOBsIGYOMKjn9PavsGOXxbvYGtMOEfnId0SVNsgehXh1DxUdVPLoxd5mvcEtvmKs2Mmf0Mpa1ZA=="],
153
163
 
@@ -189,6 +199,8 @@
189
199
 
190
200
  "three": ["three@0.177.0", "", {}, "sha512-EiXv5/qWAaGI+Vz2A+JfavwYCMdGjxVsrn3oBwllUoqYeaBO75J63ZfyaQKoiLrqNHoTlUc6PFgMXnS0kI45zg=="],
191
201
 
202
+ "tiny-inflate": ["tiny-inflate@1.0.3", "", {}, "sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw=="],
203
+
192
204
  "tinycolor2": ["tinycolor2@1.6.0", "", {}, "sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw=="],
193
205
 
194
206
  "token-types": ["token-types@4.2.1", "", { "dependencies": { "@tokenizer/token": "^0.3.0", "ieee754": "^1.2.1" } }, "sha512-6udB24Q737UD/SDsKAHI9FCRP7Bqc9D/MQUV02ORQg5iskjtLJlZJNdN4kKtcdtwCeWIwIHDGaUsTsCCAa8sFQ=="],
@@ -197,6 +209,8 @@
197
209
 
198
210
  "undici-types": ["undici-types@6.21.0", "", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="],
199
211
 
212
+ "unicode-trie": ["unicode-trie@2.0.0", "", { "dependencies": { "pako": "^0.2.5", "tiny-inflate": "^1.0.0" } }, "sha512-x7bc76x0bm4prf1VLg79uhAzKw8DVboClSN5VxJuQ+LKDOVEW9CdH+VY7SP+vX7xCYQqzzgQpFqz15zeLvAtZQ=="],
213
+
200
214
  "utif2": ["utif2@4.1.0", "", { "dependencies": { "pako": "^1.0.11" } }, "sha512-+oknB9FHrJ7oW7A2WZYajOcv4FcDR4CfoGB0dPNfxbi4GO05RRnFmt5oa23+9w32EanrYcSJWspUiJkLMs+37w=="],
201
215
 
202
216
  "web-tree-sitter": ["web-tree-sitter@0.25.10", "", { "peerDependencies": { "@types/emscripten": "^1.40.0" }, "optionalPeers": ["@types/emscripten"] }, "sha512-Y09sF44/13XvgVKgO2cNDw5rGk6s26MgoZPXLESvMXeefBf7i6/73eFurre0IsTW6E14Y0ArIzhUMmjoc7xyzA=="],
@@ -214,5 +228,7 @@
214
228
  "image-q/@types/node": ["@types/node@16.9.1", "", {}, "sha512-QpLcX9ZSsq3YYUUnD3nFDY8H7wctAhQj/TFKL8Ya8v5fMm3CFXxo8zStsLAl780ltoYoo1WvKUVGBQK+1ifr7g=="],
215
229
 
216
230
  "pixelmatch/pngjs": ["pngjs@6.0.0", "", {}, "sha512-TRzzuFRRmEoSW/p1KVAmiOgPco2Irlah+bGFCeNfJXxxYGwSw7YwAOAcd7X28K/m5bjBWKsC29KyoMfHbypayg=="],
231
+
232
+ "utif2/pako": ["pako@1.0.11", "", {}, "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw=="],
217
233
  }
218
234
  }