opencode-sesh 0.14.1 → 1.0.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.
- package/AGENTS.md +9 -10
- package/CHANGELOG.md +12 -0
- package/README.md +4 -2
- package/bin/sesh-waiting.sh +2 -2
- package/bin/sesh.sh +2 -2
- package/install.sh +58 -33
- package/package.json +17 -7
- package/plugins/sesh-list.ts +64 -0
- package/tui-plugins/sesh-panel/package.json +9 -0
- package/tui-plugins/sesh-panel/server.ts +2 -0
- package/{tui/sesh-panel.tsx → tui-plugins/sesh-panel/tui.tsx} +523 -230
- package/opencode/tools/sesh-list.ts +0 -51
package/AGENTS.md
CHANGED
|
@@ -10,9 +10,9 @@ territory: read this first, then the specific file you need.
|
|
|
10
10
|
1. **`bin/`** — a fullscreen [fzf](https://github.com/junegunn/fzf) picker for
|
|
11
11
|
any terminal. Lists **all** sessions across **all** project directories,
|
|
12
12
|
full-text searchable, with transcript preview and resume/fork/delete.
|
|
13
|
-
2. **`tui/sesh-panel.tsx`** — a SolidJS/OpenTUI plugin for the opencode TUI: a
|
|
14
|
-
recent-sessions section in the sidebar plus an `
|
|
15
|
-
3. **`
|
|
13
|
+
2. **`tui-plugins/sesh-panel/tui.tsx`** — a SolidJS/OpenTUI plugin for the opencode TUI: a
|
|
14
|
+
recent-sessions section in the sidebar plus an `alt+o` / `/sesh` picker.
|
|
15
|
+
3. **`plugins/sesh-list.ts`** — the `sesh_list` custom tool, so the agent
|
|
16
16
|
can list sessions across every directory by querying the global `opencode
|
|
17
17
|
db` store (the native `opencode session list` is project-scoped).
|
|
18
18
|
|
|
@@ -29,7 +29,7 @@ bun install # dev deps (TypeScript, opencode/OpenTUI types)
|
|
|
29
29
|
bun run test # fixture-DB regression suite — must stay green
|
|
30
30
|
bun run test:changelog # release-tooling regressions (scripts/changelog.sh)
|
|
31
31
|
bun run test:picker # PTY picker suite (needs fzf >= 0.73)
|
|
32
|
-
bun run typecheck # tsc over tui/ and
|
|
32
|
+
bun run typecheck # tsc over tui-plugins/ and plugins/
|
|
33
33
|
bun run lint:sh # bash -n on every script
|
|
34
34
|
HOME=/tmp/fakehome bash install.sh # installer smoke test (never touches ~/.config)
|
|
35
35
|
```
|
|
@@ -47,15 +47,14 @@ HOME=/tmp/fakehome bash install.sh # installer smoke test (never touches ~/.co
|
|
|
47
47
|
stay on `opencode session delete`.
|
|
48
48
|
- `contrib/` — caller-side integrations (currently cmux). Nothing here may add
|
|
49
49
|
window management to sesh itself.
|
|
50
|
-
- `tui/sesh-panel.tsx` — SolidJS panel, `/** @jsxImportSource @opentui/solid */`.
|
|
51
|
-
- `
|
|
50
|
+
- `tui-plugins/sesh-panel/tui.tsx` — SolidJS panel, `/** @jsxImportSource @opentui/solid */`.
|
|
51
|
+
- `plugins/sesh-list.ts` — the agent-facing `sesh_list` tool.
|
|
52
52
|
- `scripts/changelog.sh` — release tooling: drafts conventional commits,
|
|
53
53
|
writes a dated version, prints release notes and
|
|
54
54
|
checks the compare links. `tests/changelog.sh` covers it in a throwaway repo.
|
|
55
55
|
- `themes/`, `tests/`, `install.sh`, `README.md`.
|
|
56
56
|
|
|
57
|
-
The
|
|
58
|
-
`sesh-list` tool. Do not rename it without updating the docs.
|
|
57
|
+
The tool name in opencode is `sesh_list`. Do not rename it without updating the docs.
|
|
59
58
|
|
|
60
59
|
## Data flow (fzf picker)
|
|
61
60
|
|
|
@@ -137,7 +136,7 @@ Resume happens in place (`exec` after `cd` to the session's cwd).
|
|
|
137
136
|
and writes the new dated version and compare link. The released section is
|
|
138
137
|
used as the GitHub release body.
|
|
139
138
|
|
|
140
|
-
## TUI panel (`tui/sesh-panel.tsx`)
|
|
139
|
+
## TUI panel (`tui-plugins/sesh-panel/tui.tsx`)
|
|
141
140
|
|
|
142
141
|
- **Sidebar:** `api.slots.register` on `sidebar_content` (append mode — native
|
|
143
142
|
sidebar content stays). Pinned directories sort first, then directory groups
|
|
@@ -231,5 +230,5 @@ Resume happens in place (`exec` after `cd` to the session's cwd).
|
|
|
231
230
|
- `bun run typecheck` — `tsc` over `tui/` and `opencode/`.
|
|
232
231
|
- `bun run lint:sh` — `bash -n` on every script.
|
|
233
232
|
- `HOME=/tmp/fakehome bash install.sh` — installer smoke test.
|
|
234
|
-
- Keep `tui/sesh-panel.tsx` and any installed copy byte-identical when testing
|
|
233
|
+
- Keep `tui-plugins/sesh-panel/tui.tsx` and any installed copy byte-identical when testing
|
|
235
234
|
the panel locally.
|
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,17 @@ All notable changes to this project are documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [1.0.0] - 2026-10-07
|
|
9
|
+
|
|
10
|
+
### Breaking changes
|
|
11
|
+
|
|
12
|
+
- Migrate to OpenCode V2 plugin API with full feature parity _(breaking)_
|
|
13
|
+
|
|
14
|
+
### Fixed
|
|
15
|
+
|
|
16
|
+
- **tui:** Adapt V2 theme colors for overlays and markdown previews
|
|
17
|
+
- **tui:** Center home recent sessions list horizontally
|
|
18
|
+
|
|
8
19
|
## [0.14.1] - 2026-10-01
|
|
9
20
|
|
|
10
21
|
### Fixed
|
|
@@ -407,6 +418,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
407
418
|
- Fixture-database regression suite, TypeScript typechecking, and ShellCheck in
|
|
408
419
|
CI.
|
|
409
420
|
|
|
421
|
+
[1.0.0]: https://github.com/ozandogrultan/opencode-sesh/compare/v0.14.1...v1.0.0
|
|
410
422
|
[0.14.1]: https://github.com/ozandogrultan/opencode-sesh/compare/v0.14.0...v0.14.1
|
|
411
423
|
[0.14.0]: https://github.com/ozandogrultan/opencode-sesh/compare/v0.13.0...v0.14.0
|
|
412
424
|
[0.13.0]: https://github.com/ozandogrultan/opencode-sesh/compare/v0.12.0...v0.13.0
|
package/README.md
CHANGED
|
@@ -2,10 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://github.com/ozandogrultan/opencode-sesh/actions/workflows/ci.yml)
|
|
4
4
|
|
|
5
|
-
**
|
|
5
|
+
**An [OpenCode V2](https://opencode.ai/v2/) plugin and terminal session browser.** Search every session
|
|
6
6
|
across every project, preview the transcript, and resume in place — from your
|
|
7
7
|
terminal or from inside the TUI.
|
|
8
8
|
|
|
9
|
+
The TUI plugin and agent tool require OpenCode V2 and are not compatible with V1.
|
|
10
|
+
|
|
9
11
|
`opencode` keeps a growing pile of sessions, and its native lists (`<leader>l`,
|
|
10
12
|
`/sessions`) are scoped to the current project. `sesh` shows all of them —
|
|
11
13
|
grouped by directory, full-text searchable, and previewable from anywhere.
|
|
@@ -253,7 +255,7 @@ any SQL interpolation.
|
|
|
253
255
|
Flat scripts back the terminal UI — the picker (`sesh.sh`), the refresh engine
|
|
254
256
|
(`sesh-list.sh`, driven by a per-picker `sesh-refresh-worker.sh` that serializes
|
|
255
257
|
scans), preview renderer (`sesh-preview.sh`), deleter (`sesh-delete.sh`) and
|
|
256
|
-
shortcut help (`sesh-shortcuts.sh`). The TUI panel (`tui/sesh-panel.tsx`) is a
|
|
258
|
+
shortcut help (`sesh-shortcuts.sh`). The TUI panel (`tui-plugins/sesh-panel/tui.tsx`) is a
|
|
257
259
|
SolidJS OpenTUI plugin that talks to the opencode SDK over the same store; the
|
|
258
260
|
`sesh-list` agent tool reads it through `opencode db`.
|
|
259
261
|
|
package/bin/sesh-waiting.sh
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
#
|
|
14
14
|
# Usage: sesh-waiting.sh [--json]
|
|
15
15
|
# default prints a human table; --json prints [{id,reason,title,directory,updated}]
|
|
16
|
-
# Keep NEEDS_INPUT_SQL in sync with the TUI sidebar copy in tui/sesh-panel.tsx.
|
|
16
|
+
# Keep NEEDS_INPUT_SQL in sync with the TUI sidebar copy in tui-plugins/sesh-panel/tui.tsx.
|
|
17
17
|
set -euo pipefail
|
|
18
18
|
|
|
19
19
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
@@ -52,7 +52,7 @@ DB_PATH=$(resolve_db) || { echo 'sesh: session database unavailable' >&2; exit 1
|
|
|
52
52
|
NOW_MS=$(python3 -c 'import time; print(int(time.time() * 1000))' 2>/dev/null || date +%s000)
|
|
53
53
|
STUCK_BEFORE=$((NOW_MS - 600000))
|
|
54
54
|
|
|
55
|
-
# NEEDS_INPUT_SQL (shared heuristic — keep in sync with tui/sesh-panel.tsx).
|
|
55
|
+
# NEEDS_INPUT_SQL (shared heuristic — keep in sync with tui-plugins/sesh-panel/tui.tsx).
|
|
56
56
|
read -r -d '' QUERY <<SQL || true
|
|
57
57
|
SELECT s.id AS id, s.directory AS directory, s.title AS title, s.time_updated AS updated,
|
|
58
58
|
CASE WHEN EXISTS (
|
package/bin/sesh.sh
CHANGED
|
@@ -41,8 +41,8 @@ if [ "${1:-}" = --check ]; then
|
|
|
41
41
|
# The TUI panel is a copied file that opencode imports once at startup. Report
|
|
42
42
|
# when the installed copy has fallen behind this package so upgrades are not
|
|
43
43
|
# silently stale.
|
|
44
|
-
panel_bundled="$SCRIPT_DIR/../tui/sesh-panel.tsx"
|
|
45
|
-
panel_installed="${XDG_CONFIG_HOME:-$HOME/.config}/opencode/plugins/sesh-panel.tsx"
|
|
44
|
+
panel_bundled="$SCRIPT_DIR/../tui-plugins/sesh-panel/tui.tsx"
|
|
45
|
+
panel_installed="${XDG_CONFIG_HOME:-$HOME/.config}/opencode/tui-plugins/sesh-panel/tui.tsx"
|
|
46
46
|
if [ -f "$panel_installed" ] && [ -f "$panel_bundled" ]; then
|
|
47
47
|
if cmp -s "$panel_bundled" "$panel_installed"; then
|
|
48
48
|
echo 'sesh: sidebar panel is current'
|
package/install.sh
CHANGED
|
@@ -23,12 +23,12 @@ SYNC_PANEL=0
|
|
|
23
23
|
|
|
24
24
|
# Fallback plugin version for when the opencode CLI is unavailable; the
|
|
25
25
|
# installer prefers the local opencode version so the panel matches its SDK.
|
|
26
|
-
PLUGIN_VERSION_FALLBACK="
|
|
26
|
+
PLUGIN_VERSION_FALLBACK="2.0.18"
|
|
27
27
|
# Peer line the panel was developed and typechecked against. A checkout's
|
|
28
28
|
# package.json overrides these, so dependency bumps cannot drift the installed
|
|
29
29
|
# config out of sync (solid-js moves with OpenTUI via @opentui/keymap's peer).
|
|
30
30
|
OPENTUI_RANGE="^0.5.11"
|
|
31
|
-
SOLID_VERSION="1.9.
|
|
31
|
+
SOLID_VERSION="1.9.15"
|
|
32
32
|
if [ -f "$SOURCE_DIR/package.json" ] && command -v jq >/dev/null 2>&1; then
|
|
33
33
|
opentui_range=$(jq -r '.devDependencies["@opentui/solid"] // empty' "$SOURCE_DIR/package.json" 2>/dev/null || true)
|
|
34
34
|
solid_version=$(jq -r '.devDependencies["solid-js"] // empty' "$SOURCE_DIR/package.json" 2>/dev/null || true)
|
|
@@ -65,9 +65,11 @@ LAUNCHER="$BIN_DIR/sesh"
|
|
|
65
65
|
# `/sesh` is registered by the TUI plugin (a markdown command cannot open the
|
|
66
66
|
# dialog); this path only exists so we can clean up an obsolete install.
|
|
67
67
|
COMMAND_DST="$CONFIG_DIR/commands/sesh.md"
|
|
68
|
-
TOOL_DST="$CONFIG_DIR/
|
|
69
|
-
|
|
68
|
+
TOOL_DST="$CONFIG_DIR/plugins/sesh-list.ts"
|
|
69
|
+
PANEL_DIR="$CONFIG_DIR/tui-plugins/sesh-panel"
|
|
70
|
+
PANEL_DST="$PANEL_DIR/tui.tsx"
|
|
70
71
|
PACKAGE_JSON="$CONFIG_DIR/package.json"
|
|
72
|
+
OPENCODE_JSON="$CONFIG_DIR/opencode.json"
|
|
71
73
|
TUI_JSON="$CONFIG_DIR/tui.json"
|
|
72
74
|
|
|
73
75
|
# Remove a file only when it carries our marker, so a user's own file with a
|
|
@@ -94,6 +96,19 @@ remove_tui_entry() {
|
|
|
94
96
|
fi
|
|
95
97
|
}
|
|
96
98
|
|
|
99
|
+
remove_opencode_entry() {
|
|
100
|
+
[ -f "$OPENCODE_JSON" ] || return 0
|
|
101
|
+
command -v jq >/dev/null 2>&1 || return 0
|
|
102
|
+
local tmp
|
|
103
|
+
tmp=$(mktemp "${TMPDIR:-/tmp}/sesh-opencode.XXXXXX") || return 0
|
|
104
|
+
if jq 'if (.plugins | type) == "array" then .plugins = [.plugins[] | select(. != "./tui-plugins/sesh-panel")] else . end' "$OPENCODE_JSON" > "$tmp" 2>/dev/null; then
|
|
105
|
+
cmp -s "$OPENCODE_JSON" "$tmp" || mv "$tmp" "$OPENCODE_JSON"
|
|
106
|
+
rm -f "$tmp"
|
|
107
|
+
else
|
|
108
|
+
rm -f "$tmp"
|
|
109
|
+
fi
|
|
110
|
+
}
|
|
111
|
+
|
|
97
112
|
# The launcher is a symlink we create. Treat it as ours only when it resolves to
|
|
98
113
|
# a sesh launcher, so a foreign symlink is never replaced on install nor deleted
|
|
99
114
|
# on uninstall. Recognized by the exact source path, a `.../bin/sesh` target, or
|
|
@@ -125,7 +140,9 @@ install_file() {
|
|
|
125
140
|
}
|
|
126
141
|
|
|
127
142
|
install_tui_panel() {
|
|
128
|
-
install_file "$SOURCE_DIR/tui/sesh-panel.
|
|
143
|
+
install_file "$SOURCE_DIR/tui-plugins/sesh-panel/package.json" "$PANEL_DIR/package.json"
|
|
144
|
+
install_file "$SOURCE_DIR/tui-plugins/sesh-panel/server.ts" "$PANEL_DIR/server.ts"
|
|
145
|
+
install_file "$SOURCE_DIR/tui-plugins/sesh-panel/tui.tsx" "$PANEL_DST"
|
|
129
146
|
|
|
130
147
|
local opencode_version='' raw_version='' plugin_version=''
|
|
131
148
|
if command -v opencode >/dev/null 2>&1; then
|
|
@@ -134,33 +151,32 @@ install_tui_panel() {
|
|
|
134
151
|
fi
|
|
135
152
|
plugin_version="${opencode_version:-$PLUGIN_VERSION_FALLBACK}"
|
|
136
153
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
printf '{\n "$schema": "https://opencode.ai/tui.json",\n "plugin": []\n}\n' > "$TUI_JSON"
|
|
143
|
-
tui_created=1
|
|
144
|
-
note "created $TUI_JSON"
|
|
154
|
+
local opencode_created=0 opencode_tmp=''
|
|
155
|
+
if [ ! -f "$OPENCODE_JSON" ]; then
|
|
156
|
+
printf '{\n "$schema": "https://opencode.ai/config.json",\n "plugins": []\n}\n' > "$OPENCODE_JSON"
|
|
157
|
+
opencode_created=1
|
|
158
|
+
note "created $OPENCODE_JSON"
|
|
145
159
|
fi
|
|
146
|
-
|
|
160
|
+
opencode_tmp=$(mktemp "${TMPDIR:-/tmp}/sesh-opencode.XXXXXX")
|
|
147
161
|
if jq '
|
|
148
|
-
(.
|
|
149
|
-
| ($plugins |
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
rm -f "$tui_tmp"
|
|
162
|
+
(.plugins // []) as $plugins
|
|
163
|
+
| if ($plugins | index("./tui-plugins/sesh-panel")) then . else .plugins = $plugins + ["./tui-plugins/sesh-panel"] end
|
|
164
|
+
' "$OPENCODE_JSON" > "$opencode_tmp" 2>/dev/null; then
|
|
165
|
+
if cmp -s "$OPENCODE_JSON" "$opencode_tmp"; then
|
|
166
|
+
note "opencode.json already registers the sesh panel"
|
|
167
|
+
rm -f "$opencode_tmp"
|
|
155
168
|
else
|
|
156
|
-
mv "$
|
|
157
|
-
note "registered ./plugins/sesh-panel
|
|
169
|
+
mv "$opencode_tmp" "$OPENCODE_JSON"
|
|
170
|
+
note "registered ./tui-plugins/sesh-panel in opencode.json"
|
|
158
171
|
fi
|
|
159
172
|
else
|
|
160
|
-
rm -f "$
|
|
161
|
-
note "warning: could not update $
|
|
173
|
+
rm -f "$opencode_tmp"
|
|
174
|
+
note "warning: could not update $OPENCODE_JSON; add \"./tui-plugins/sesh-panel\" to its plugins list by hand"
|
|
162
175
|
fi
|
|
163
176
|
|
|
177
|
+
# Clean up obsolete V1 tui.json entry if present
|
|
178
|
+
remove_tui_entry
|
|
179
|
+
|
|
164
180
|
# Local plugins resolve their imports from the config directory, and opencode
|
|
165
181
|
# runs `bun install` there at startup. Keep the required packages declared
|
|
166
182
|
# without clobbering versions the user already pinned.
|
|
@@ -171,10 +187,10 @@ install_tui_panel() {
|
|
|
171
187
|
note "created $PACKAGE_JSON"
|
|
172
188
|
fi
|
|
173
189
|
pkg_tmp=$(mktemp "${TMPDIR:-/tmp}/sesh-pkg.XXXXXX")
|
|
174
|
-
if jq --arg p "
|
|
190
|
+
if jq --arg p "^$plugin_version" --arg o "$OPENTUI_RANGE" --arg s "$SOLID_VERSION" '
|
|
175
191
|
.dependencies = ((.dependencies // {}) as $d
|
|
176
192
|
| {
|
|
177
|
-
"@opencode
|
|
193
|
+
"@opencode/plugin": ($d["@opencode/plugin"] // $p),
|
|
178
194
|
"@opentui/core": ($d["@opentui/core"] // $o),
|
|
179
195
|
"@opentui/keymap": ($d["@opentui/keymap"] // $o),
|
|
180
196
|
"@opentui/solid": ($d["@opentui/solid"] // $o),
|
|
@@ -217,8 +233,13 @@ if [ "$UNINSTALL" = 1 ]; then
|
|
|
217
233
|
fi
|
|
218
234
|
fi
|
|
219
235
|
remove_if_marker "$COMMAND_DST" "rich interactive picker" && note "removed $COMMAND_DST"
|
|
220
|
-
remove_if_marker "$TOOL_DST" "
|
|
221
|
-
remove_if_marker "$
|
|
236
|
+
remove_if_marker "$TOOL_DST" "sesh_list" && note "removed $TOOL_DST"
|
|
237
|
+
remove_if_marker "$CONFIG_DIR/tools/sesh-list.ts" "list opencode sessions for the agent" && note "removed $CONFIG_DIR/tools/sesh-list.ts"
|
|
238
|
+
if [ -d "$PANEL_DIR" ]; then
|
|
239
|
+
rm -rf "$PANEL_DIR" && note "removed $PANEL_DIR"
|
|
240
|
+
fi
|
|
241
|
+
remove_if_marker "$CONFIG_DIR/plugins/sesh-panel.tsx" "@jsxImportSource @opentui/solid" && note "removed $CONFIG_DIR/plugins/sesh-panel.tsx"
|
|
242
|
+
remove_opencode_entry && note "unregistered the panel from $OPENCODE_JSON"
|
|
222
243
|
remove_tui_entry && note "unregistered the panel from $TUI_JSON"
|
|
223
244
|
note "uninstalled (extraction cache and plugin dependencies left intact)"
|
|
224
245
|
exit 0
|
|
@@ -236,8 +257,10 @@ for path in \
|
|
|
236
257
|
bin/sesh-retitle.sh \
|
|
237
258
|
bin/sesh-waiting.sh \
|
|
238
259
|
bin/sesh-shortcuts.sh \
|
|
239
|
-
|
|
240
|
-
tui/sesh-panel.
|
|
260
|
+
plugins/sesh-list.ts \
|
|
261
|
+
tui-plugins/sesh-panel/package.json \
|
|
262
|
+
tui-plugins/sesh-panel/server.ts \
|
|
263
|
+
tui-plugins/sesh-panel/tui.tsx \
|
|
241
264
|
themes/glow-dark-clean.json; do
|
|
242
265
|
[ -f "$SOURCE_DIR/$path" ] || fail "installer bundle is incomplete: missing $path."
|
|
243
266
|
done
|
|
@@ -283,7 +306,9 @@ note "linked $LAUNCHER -> $SOURCE_DIR/bin/sesh"
|
|
|
283
306
|
# agent; the TUI plugin now registers the slash itself. Drop the old file so the
|
|
284
307
|
# two do not collide.
|
|
285
308
|
remove_if_marker "$COMMAND_DST" "rich interactive picker" && note "removed obsolete markdown command $COMMAND_DST"
|
|
286
|
-
[ "$INSTALL_TOOL" = 1 ] && install_file "$SOURCE_DIR/
|
|
309
|
+
[ "$INSTALL_TOOL" = 1 ] && install_file "$SOURCE_DIR/plugins/sesh-list.ts" "$TOOL_DST"
|
|
310
|
+
# Clean up obsolete V1 tool if present
|
|
311
|
+
remove_if_marker "$CONFIG_DIR/tools/sesh-list.ts" "list opencode sessions for the agent" && note "removed obsolete V1 tool"
|
|
287
312
|
|
|
288
313
|
if [ "$INSTALL_TUI" = 1 ]; then
|
|
289
314
|
install_tui_panel
|
|
@@ -292,7 +317,7 @@ fi
|
|
|
292
317
|
"$LAUNCHER" --check || fail "post-install check failed."
|
|
293
318
|
note "done"
|
|
294
319
|
note " picker: run 'sesh' in any terminal, or '/sesh' inside opencode"
|
|
295
|
-
note " sidebar:
|
|
320
|
+
note " sidebar: alt+o opens the full picker"
|
|
296
321
|
note_restart
|
|
297
322
|
case ":$PATH:" in
|
|
298
323
|
*":$BIN_DIR:"*) ;;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opencode-sesh",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"description": "Browse, search, preview and resume opencode sessions from the terminal and the TUI.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -21,18 +21,24 @@
|
|
|
21
21
|
"tui",
|
|
22
22
|
"cli"
|
|
23
23
|
],
|
|
24
|
+
"exports": {
|
|
25
|
+
"./tui": "./tui-plugins/sesh-panel/tui.tsx",
|
|
26
|
+
"./tool": "./plugins/sesh-list.ts"
|
|
27
|
+
},
|
|
24
28
|
"bin": {
|
|
25
29
|
"sesh": "bin/sesh"
|
|
26
30
|
},
|
|
27
31
|
"files": [
|
|
28
32
|
"bin/",
|
|
29
33
|
"contrib/",
|
|
30
|
-
"
|
|
34
|
+
"plugins/",
|
|
31
35
|
"themes/",
|
|
32
|
-
"tui/",
|
|
36
|
+
"tui-plugins/",
|
|
33
37
|
"install.sh",
|
|
34
38
|
"AGENTS.md",
|
|
35
39
|
"CHANGELOG.md",
|
|
40
|
+
"LICENSE",
|
|
41
|
+
"README.md",
|
|
36
42
|
"ROADMAP.md"
|
|
37
43
|
],
|
|
38
44
|
"publishConfig": {
|
|
@@ -40,7 +46,8 @@
|
|
|
40
46
|
},
|
|
41
47
|
"packageManager": "bun@1.4.2",
|
|
42
48
|
"engines": {
|
|
43
|
-
"node": ">=20"
|
|
49
|
+
"node": ">=20",
|
|
50
|
+
"opencode": ">=2.0.0"
|
|
44
51
|
},
|
|
45
52
|
"scripts": {
|
|
46
53
|
"prepare": "husky",
|
|
@@ -53,17 +60,20 @@
|
|
|
53
60
|
"postinstall": "bash install.sh --sync-panel || true",
|
|
54
61
|
"prepublishOnly": "bun run test && bun run typecheck"
|
|
55
62
|
},
|
|
63
|
+
"peerDependencies": {
|
|
64
|
+
"@opencode/plugin": ">=2.0.0"
|
|
65
|
+
},
|
|
56
66
|
"devDependencies": {
|
|
57
67
|
"@commitlint/cli": "^21.2.2",
|
|
58
68
|
"@commitlint/config-conventional": "^21.2.2",
|
|
59
|
-
"@opencode
|
|
60
|
-
"@opencode
|
|
69
|
+
"@opencode/client": "2.0.18",
|
|
70
|
+
"@opencode/plugin": "2.0.18",
|
|
61
71
|
"@opentui/core": "^0.5.11",
|
|
62
72
|
"@opentui/keymap": "^0.5.11",
|
|
63
73
|
"@opentui/solid": "^0.5.11",
|
|
64
74
|
"@types/node": "26.5.1",
|
|
65
75
|
"husky": "^9.1.7",
|
|
66
|
-
"solid-js": "1.9.
|
|
76
|
+
"solid-js": "1.9.15",
|
|
67
77
|
"typescript": "7.0.2"
|
|
68
78
|
}
|
|
69
79
|
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { Plugin } from "@opencode/plugin"
|
|
2
|
+
import { homedir } from "node:os"
|
|
3
|
+
import { join } from "node:path"
|
|
4
|
+
|
|
5
|
+
function dataHome(): string {
|
|
6
|
+
return process.env.XDG_DATA_HOME ?? join(homedir(), ".local", "share")
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const input = {
|
|
10
|
+
type: "object",
|
|
11
|
+
properties: {
|
|
12
|
+
limit: {
|
|
13
|
+
type: "number",
|
|
14
|
+
description: "Maximum sessions to return (0-1000; 0 returns none)",
|
|
15
|
+
default: 50,
|
|
16
|
+
},
|
|
17
|
+
directory: {
|
|
18
|
+
type: "string",
|
|
19
|
+
description: "Only sessions from this directory (default: all directories)",
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
required: [],
|
|
23
|
+
additionalProperties: false,
|
|
24
|
+
} as const
|
|
25
|
+
|
|
26
|
+
export default Plugin.define({
|
|
27
|
+
id: "sesh-list",
|
|
28
|
+
async setup(ctx) {
|
|
29
|
+
ctx.tool.transform((editor) => {
|
|
30
|
+
editor.add({
|
|
31
|
+
name: "sesh_list",
|
|
32
|
+
description: "List opencode sessions across all project directories, newest first",
|
|
33
|
+
input,
|
|
34
|
+
async execute(args: any) {
|
|
35
|
+
const limit = args.limit === undefined ? 50 : Number(args.limit)
|
|
36
|
+
if (!Number.isInteger(limit) || limit < 0 || limit > 1000) {
|
|
37
|
+
throw new Error("limit must be an integer between 0 and 1000")
|
|
38
|
+
}
|
|
39
|
+
if (limit === 0) return { content: "[]" }
|
|
40
|
+
|
|
41
|
+
const specifier = "bun:sqlite"
|
|
42
|
+
const sqlite: any = await import(specifier).catch(() => undefined)
|
|
43
|
+
if (typeof sqlite?.Database !== "function") {
|
|
44
|
+
throw new Error("sesh_list requires the Bun runtime (bun:sqlite)")
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const db = new sqlite.Database(join(dataHome(), "opencode", "opencode.db"), { readonly: true })
|
|
48
|
+
try {
|
|
49
|
+
const scoped = typeof args.directory === "string" && args.directory.length > 0
|
|
50
|
+
const query = `SELECT id, title, directory, time_updated AS updated, time_created AS created
|
|
51
|
+
FROM session_v2
|
|
52
|
+
WHERE parent_id IS NULL AND time_archived IS NULL${scoped ? " AND directory = ?" : ""}
|
|
53
|
+
ORDER BY time_updated DESC, id DESC
|
|
54
|
+
LIMIT ${limit}`
|
|
55
|
+
const rows = scoped ? db.query(query).all(args.directory) : db.query(query).all()
|
|
56
|
+
return { content: JSON.stringify(rows ?? []) }
|
|
57
|
+
} finally {
|
|
58
|
+
db.close?.()
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
})
|
|
62
|
+
})
|
|
63
|
+
},
|
|
64
|
+
})
|