Skip to content

Commit 8daa3d7

Browse files
Merge branch 'dev' into PR jairad26#41 - resolve conflicts
2 parents 2ecc6ae + c22eead commit 8daa3d7

88 files changed

Lines changed: 10421 additions & 477 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
---
2+
name: local-opencode-override
3+
description: Use when a repo-local opencode build should replace the installed `opencode` command in your shell, especially after rebuilding `packages/opencode/dist` during local development.
4+
compatibility: opencode
5+
---
6+
7+
# Local opencode override
8+
9+
Use this when you want `opencode` in your shell to run the binary built from this repo instead of a globally installed copy.
10+
11+
## Preferred approach
12+
13+
Follow the existing OpenCode convention and point `~/.opencode/bin/opencode` at the repo build output.
14+
15+
Why this path:
16+
17+
- the install flow already uses `~/.opencode/bin`
18+
- desktop code and GitHub actions already expect that location
19+
- your shell can keep using `opencode` with no extra alias
20+
21+
## Steps
22+
23+
1. Build the current-platform CLI:
24+
25+
```bash
26+
bun run --cwd packages/opencode build --single --skip-embed-web-ui
27+
```
28+
29+
2. Link the built binary into the standard user bin location:
30+
31+
```bash
32+
mkdir -p "$HOME/.opencode/bin"
33+
ln -sf \
34+
"/absolute/path/to/repo/packages/opencode/dist/opencode-<platform>/bin/opencode" \
35+
"$HOME/.opencode/bin/opencode"
36+
```
37+
38+
Example for this repo on Apple Silicon:
39+
40+
```bash
41+
ln -sf \
42+
"/Users/jairadhakrishnan/github.com/jairad26/opencode/packages/opencode/dist/opencode-darwin-arm64/bin/opencode" \
43+
"$HOME/.opencode/bin/opencode"
44+
```
45+
46+
3. Make sure `~/.opencode/bin` is early in `PATH`.
47+
48+
For zsh:
49+
50+
```bash
51+
export PATH="$HOME/.opencode/bin:$PATH"
52+
```
53+
54+
4. Reload the shell and verify:
55+
56+
```bash
57+
zsh -lc 'hash -r && command -v opencode && opencode --version'
58+
```
59+
60+
## Rebuild behavior
61+
62+
The symlink target path stays the same across rebuilds for the same platform, so rerunning the build replaces the binary in place.
63+
64+
## Alternative
65+
66+
If you only want a temporary override, use the launcher support built into `packages/opencode/bin/opencode`:
67+
68+
```bash
69+
OPENCODE_BIN_PATH="/absolute/path/to/repo/packages/opencode/dist/opencode-<platform>/bin/opencode" opencode
70+
```
71+
72+
## Revert
73+
74+
To stop using the repo build:
75+
76+
```bash
77+
rm -f "$HOME/.opencode/bin/opencode"
78+
```
79+
80+
Then reinstall or relink the version you want.
Lines changed: 274 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,274 @@
1+
---
2+
name: opencode-memory
3+
description: Use when the user asks to recall prior OpenCode work, previous sessions, plans, prompt history, memory, or earlier project context stored on the local machine.
4+
compatibility: opencode
5+
---
6+
7+
# OpenCode Memory Browser
8+
9+
Lightweight, read-only access to your local OpenCode history. No injection, no bloat — just the ability to look things up when it would help.
10+
11+
This skill is specifically about OpenCode data stored on the local machine. It is not for ChatGPT history, Claude cloud history, generic browser history, or external memory products.
12+
13+
All data lives in local SQLite databases and plain files. You query them directly using `sqlite3` via bash. No bundled scripts or external dependencies needed.
14+
15+
## When to Use
16+
17+
### Auto-trigger (agent decides)
18+
19+
- You are resuming work on a project and suspect prior sessions exist.
20+
- The user references something done previously ("we did this before", "last time", "that plan we made").
21+
- A recurring issue suggests checking if it was encountered before.
22+
- The user asks about the state of plans, past decisions, or previous approaches.
23+
- You need context that might exist in history but is not in the current session.
24+
25+
### User-triggered (explicit request)
26+
27+
- "Check my history"
28+
- "What did we do in the last session?"
29+
- "Show me my plans"
30+
- "Search for when we discussed X"
31+
- "What projects have I worked on?"
32+
- "Look at previous conversations about Y"
33+
34+
### Do NOT use when
35+
36+
- The task is clearly brand new with no relevant history.
37+
- Fresh repo context (files, git log) is sufficient.
38+
- The user explicitly says they don't care about prior work.
39+
40+
## Storage Locations
41+
42+
```
43+
Databases: ${XDG_DATA_HOME:-$HOME/.local/share}/opencode/opencode*.db
44+
Plans: ${XDG_DATA_HOME:-$HOME/.local/share}/opencode/plans/*.md
45+
Session diffs: ${XDG_DATA_HOME:-$HOME/.local/share}/opencode/storage/session_diff/<session-id>.json
46+
Prompt history: ${XDG_STATE_HOME:-$HOME/.local/state}/opencode/prompt-history.jsonl
47+
```
48+
49+
The database path respects `$XDG_DATA_HOME` if set (default: `~/.local/share`).
50+
51+
Important: OpenCode may store session history in multiple channel-specific databases such as:
52+
53+
- `opencode.db`
54+
- `opencode-dev.db`
55+
- `opencode-local.db`
56+
- other `opencode-<channel>.db` files
57+
58+
When recalling prior work, search **all local `opencode*.db` files**, not just `opencode.db`.
59+
60+
## Database Schema (what matters)
61+
62+
- **project**`id` (text PK), `worktree` (path), `name` (often NULL, derive from worktree basename)
63+
- **session**`id` (text, e.g. `ses_xxx`), `project_id` (FK), `parent_id` (NULL = main session, set = subagent), `title`, `summary`, `time_created`, `time_updated`
64+
- **message**`id`, `session_id` (FK), `data` (JSON with `$.role` = `"user"` or `"assistant"`), `time_created`
65+
- **part**`id`, `message_id` (FK), `session_id` (FK), `data` (JSON with `$.type` = `"text"` and `$.text` = content)
66+
67+
Timestamps are Unix milliseconds. Use `datetime(col/1000, 'unixepoch', 'localtime')` to display them.
68+
69+
## Ready-to-Use Queries
70+
71+
All queries use `sqlite3` in read-only mode. Always run via bash.
72+
73+
**Shorthand used below:**
74+
75+
```
76+
DATA_ROOT="${XDG_DATA_HOME:-$HOME/.local/share}/opencode"
77+
STATE_ROOT="${XDG_STATE_HOME:-$HOME/.local/state}/opencode"
78+
DBS=("$DATA_ROOT"/opencode*.db)
79+
```
80+
81+
If the glob does not match anything, verify the storage root first with `ls "$DATA_ROOT"`.
82+
83+
### Quick summary
84+
85+
```bash
86+
for DB in "${DBS[@]}"; do
87+
[ -f "$DB" ] || continue
88+
DB_URI="file:${DB}?mode=ro"
89+
printf '\n== %s ==\n' "$DB"
90+
sqlite3 "$DB_URI" "
91+
SELECT 'projects', COUNT(*) FROM project
92+
UNION ALL SELECT 'sessions (main)', COUNT(*) FROM session WHERE parent_id IS NULL
93+
UNION ALL SELECT 'sessions (total)', COUNT(*) FROM session
94+
UNION ALL SELECT 'messages', COUNT(*) FROM message
95+
UNION ALL SELECT 'todos', COUNT(*) FROM todo;
96+
"
97+
done
98+
```
99+
100+
### List projects
101+
102+
Set `DB_URI` to the database you want to inspect first, for example:
103+
104+
```bash
105+
DB="$DATA_ROOT/opencode-dev.db"
106+
DB_URI="file:${DB}?mode=ro"
107+
```
108+
109+
```bash
110+
sqlite3 "$DB_URI" "
111+
SELECT
112+
COALESCE(p.name, CASE WHEN p.worktree = '/' THEN '(global)' ELSE REPLACE(p.worktree, RTRIM(p.worktree, REPLACE(p.worktree, '/', '')), '') END) AS name,
113+
p.worktree,
114+
(SELECT COUNT(*) FROM session s WHERE s.project_id = p.id AND s.parent_id IS NULL) AS sessions
115+
FROM project p
116+
ORDER BY p.time_updated DESC
117+
LIMIT 10;
118+
"
119+
```
120+
121+
### List recent sessions
122+
123+
```bash
124+
for DB in "${DBS[@]}"; do
125+
[ -f "$DB" ] || continue
126+
DB_URI="file:${DB}?mode=ro"
127+
sqlite3 "$DB_URI" "
128+
SELECT
129+
'${DB}' AS db,
130+
s.id,
131+
COALESCE(s.title, 'untitled') AS title,
132+
COALESCE(p.name, CASE WHEN p.worktree = '/' THEN '(global)' ELSE REPLACE(p.worktree, RTRIM(p.worktree, REPLACE(p.worktree, '/', '')), '') END) AS project,
133+
datetime(s.time_updated/1000, 'unixepoch', 'localtime') AS updated,
134+
(SELECT COUNT(*) FROM message m WHERE m.session_id = s.id) AS msgs
135+
FROM session s
136+
LEFT JOIN project p ON p.id = s.project_id
137+
WHERE s.parent_id IS NULL
138+
ORDER BY s.time_updated DESC
139+
LIMIT 10;
140+
"
141+
done
142+
```
143+
144+
### Sessions for a specific project
145+
146+
Set `DB_URI` to the likely matching database, then replace the worktree path with the actual project path:
147+
148+
```bash
149+
sqlite3 "$DB_URI" "
150+
SELECT s.id, COALESCE(s.title, 'untitled'),
151+
datetime(s.time_updated/1000, 'unixepoch', 'localtime')
152+
FROM session s
153+
JOIN project p ON p.id = s.project_id
154+
WHERE p.worktree = '/path/to/project'
155+
AND s.parent_id IS NULL
156+
ORDER BY s.time_updated DESC
157+
LIMIT 10;
158+
"
159+
```
160+
161+
To find the worktree for the current directory: `git rev-parse --show-toplevel`
162+
163+
### Read messages from a session
164+
165+
Replace the session ID:
166+
167+
```bash
168+
sqlite3 "$DB_URI" "
169+
SELECT
170+
json_extract(m.data, '$.role') AS role,
171+
datetime(m.time_created/1000, 'unixepoch', 'localtime') AS time,
172+
GROUP_CONCAT(json_extract(p.data, '$.text'), char(10)) AS text
173+
FROM message m
174+
LEFT JOIN part p ON p.message_id = m.id
175+
AND json_extract(p.data, '$.type') = 'text'
176+
WHERE m.session_id = 'SESSION_ID_HERE'
177+
GROUP BY m.id
178+
ORDER BY m.time_created ASC
179+
LIMIT 50;
180+
"
181+
```
182+
183+
### Search across all conversations
184+
185+
Replace the search term:
186+
187+
```bash
188+
for DB in "${DBS[@]}"; do
189+
[ -f "$DB" ] || continue
190+
DB_URI="file:${DB}?mode=ro"
191+
sqlite3 "$DB_URI" "
192+
SELECT
193+
'${DB}' AS db,
194+
s.id AS session_id,
195+
COALESCE(s.title, 'untitled') AS title,
196+
json_extract(m.data, '$.role') AS role,
197+
datetime(m.time_created/1000, 'unixepoch', 'localtime') AS time,
198+
substr(json_extract(p.data, '$.text'), 1, 200) AS snippet
199+
FROM part p
200+
JOIN message m ON m.id = p.message_id
201+
JOIN session s ON s.id = m.session_id
202+
WHERE s.parent_id IS NULL
203+
AND json_extract(p.data, '$.type') = 'text'
204+
AND json_extract(p.data, '$.text') LIKE '%SEARCH_TERM%'
205+
ORDER BY m.time_created DESC
206+
LIMIT 10;
207+
"
208+
done
209+
```
210+
211+
### List saved plans
212+
213+
```bash
214+
ls -lt "$DATA_ROOT"/plans/*.md 2>/dev/null | head -20
215+
```
216+
217+
To read a specific plan:
218+
219+
```bash
220+
cat "$DATA_ROOT"/plans/FILENAME.md
221+
```
222+
223+
### Show recent prompt history
224+
225+
```bash
226+
tail -20 "$STATE_ROOT"/prompt-history.jsonl
227+
```
228+
229+
Each line is a JSON object. The user's input is typically in the `input` or `text` field.
230+
231+
## Workflow
232+
233+
### Quick recall (most common)
234+
235+
1. Check **prompt history first** with `rg -n -i "term1|term2" "$STATE_ROOT/prompt-history.jsonl"` to recover the user's original wording and likely time window.
236+
2. Run the **summary** query across all local databases to see which DB/channel has the relevant history.
237+
3. If you need sessions for the current project, get the worktree with `git rev-parse --show-toplevel`, then run the **project sessions** query against the likely matching DB(s).
238+
4. If you need a specific topic, run the **search** query across all DBs using both the exact phrase and adjacent terms.
239+
5. If you need full conversation detail, run the **messages** query with the session ID from the matching DB.
240+
241+
### Plan review
242+
243+
1. List plans with `ls -lt "$DATA_ROOT"/plans/*.md`.
244+
2. Read a plan with `cat "$DATA_ROOT"/plans/<filename>.md`.
245+
246+
### Deep investigation
247+
248+
1. Search prompt history first to anchor wording/date.
249+
2. Run **projects/sessions** across all local DBs.
250+
3. Search with neighboring terms, not just the user’s remembered phrasing.
251+
4. Read only the best candidate session tails before expanding further.
252+
5. Cross-reference with session diffs or plans if needed.
253+
254+
## Critical Rules
255+
256+
1. **Read-only.** Never write to or modify the database or any OpenCode files.
257+
2. **Use bash + sqlite3.** Do not try to read `opencode*.db` with the Read tool — they are binary files. Always query via `sqlite3` in bash.
258+
3. **Don't dump everything.** Use `LIMIT` and `LIKE` to keep output focused. The database can contain tens of thousands of messages.
259+
4. **Summarize for the user.** After retrieving data, distill the relevant parts. Don't paste raw query output.
260+
5. **Respect privacy.** Session history may contain sensitive data. Only surface what is relevant to the current task.
261+
6. **Set path variables first.** At the start of any memory lookup, set `DATA_ROOT`, `STATE_ROOT`, and `DBS` exactly as shown above so the commands work on XDG and non-XDG setups and cover every local channel database.
262+
263+
## Fallback: Web UI
264+
265+
If the user needs visual dashboards or a browsable interface:
266+
267+
1. Check if OpenCode web is running: `curl -s http://127.0.0.1:4096/api/health 2>/dev/null || echo "not running"`
268+
2. If running, direct the user to `http://127.0.0.1:4096`.
269+
3. If not running, suggest `opencode web`.
270+
4. Note: `opencode.local` only works with mDNS enabled (`opencode web --mdns`). Don't assume it exists.
271+
272+
## Deep Reference
273+
274+
See `references/storage-format.md` for the full storage layout, all table schemas, and additional query examples.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
[ 776ms] [INFO] LegacyDataMixin will be applied to all legacy elements.
2+
Set `_legacyUndefinedCheck: true` on element class to enable. @ https://www.youtube.com/s/_/ytmainappweb/_/js/k=ytmainappweb.kevlar_base.en_US.Zy1ieGo0Hzs.es5.O/am=AAAAEAAAkA/d=1/br=1/rs=AGKMywEoMmE2M2iEKvHkivOZLVLxkMo3Ng/m=kevlar_base_module,kevlar_main_module:9886
3+
[ 908ms] [ERROR] Failed to load resource: the server responded with a status of 403 () @ https://accounts.google.com/v3/signin/identifier?continue=https%3A%2F%2Fwww.youtube.com%2Fsignin%3Faction_handle_signin%3Dtrue%26app%3Ddesktop%26hl%3Den%26next%3D%252Fsignin_passive%26feature%3Dpassive&dsh=S154197866%3A1774986442026494&hl=en&passive=true&service=youtube&uilel=3&flowName=GlifWebSignIn&flowEntry=ServiceLogin&ifkv=AT1y2_U0Vl4z2FHUjPAQ3OYT5OCMIaJRktOwr1xYhruCcOhgq_MBHPJYen2iNP_yy_nGU0Y08PwU:0
4+
[ 1600ms] [INFO] Banner not shown: beforeinstallpromptevent.preventDefault() called. The page must call beforeinstallpromptevent.prompt() to show the banner. @ https://www.youtube.com/:0
5+
[ 4988ms] [WARNING] The resource https://i.ytimg.com/generate_204 was preloaded using link preload but not used within a few seconds from the window's load event. Please make sure it has an appropriate `as` value and it is preloaded intentionally. @ https://www.youtube.com/:0

0 commit comments

Comments
 (0)