@joe-broadhead/opencode-history 0.0.0-stage → 0.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/CHANGELOG.md ADDED
@@ -0,0 +1,19 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project are documented here. The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and versions follow [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
4
+
5
+ ## [0.0.0] - 2026-11-03
6
+
7
+ ### Added
8
+
9
+ - Nine tools under `history_<name>`: `search`, `brief`, `read`, `sessions`, `files`, `recall`, `sql`, `pin` and `status`. Every tool but `pin` is in Code Mode as `tools.history.<name>`, with search, brief and read pinned.
10
+ - A local SQLite full-text index of every OpenCode session, built from OpenCode's own database opened read-only, kept fresh from session events, with a partial fallback to the plugin session API.
11
+ - Search in three modes (stemmed words, exact substrings, regular expressions), with several phrasings per search, near matches, folded repeats, filters by scope, time, kind, tool, agent and path, and excerpts with a `seq` to read from.
12
+ - `history_recall`, which quotes evidence from the best sessions and can ask a model to answer from it; `history_sql`, one read-only statement over stable views, run in a child process with a 10-second limit; `history_pin`, which keeps a past session's brief or messages in the current session's instructions.
13
+ - Default permission rules after each agent's base allow: the reads are allowed, and `history_pin` and any unknown `history_*` tool ask. Status names agents without the rules.
14
+ - An index that changes only its own file, and refuses OpenCode's database and data folder, a path inside the project, and any other existing file.
15
+ - Built-in masks for common credentials, and a `mask` option, applied before text is indexed or shown.
16
+ - `/history-status`, `/history-reindex`, the `history_status` tool, and a status dialog in the terminal UI: `/history`, or **History: Status** in the command palette.
17
+ - A tools RPC for scripts, `history.sessions.tools`: every tool but `history_pin` as a method, run as a named session and its agent under their permission rules, with no model.
18
+ - The `history-recall` skill, and a Jelly declaration in `package.json`.
19
+ - A startup check for OpenCode `>=2.2.3 <2.3.0`, with `allowUntestedHost` to override it.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Joe Broadhead
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/NOTICE ADDED
@@ -0,0 +1,25 @@
1
+ @joe-broadhead/opencode-history bundles this third-party code into dist/.
2
+
3
+ ## zod 4.6.7 (MIT), in dist/index.js
4
+
5
+ MIT License
6
+
7
+ Copyright (c) 2025 Colin McDonnell
8
+
9
+ Permission is hereby granted, free of charge, to any person obtaining a copy
10
+ of this software and associated documentation files (the "Software"), to deal
11
+ in the Software without restriction, including without limitation the rights
12
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13
+ copies of the Software, and to permit persons to whom the Software is
14
+ furnished to do so, subject to the following conditions:
15
+
16
+ The above copyright notice and this permission notice shall be included in all
17
+ copies or substantial portions of the Software.
18
+
19
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,193 @@
1
- # Temporary Holding Version
1
+ # History for OpenCode
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Lets OpenCode agents search, read and recall your own past OpenCode sessions, in this project or any other, through a local full-text index.
4
+
5
+ Unofficial; not affiliated with OpenCode.
6
+
7
+ ## Requirements
8
+
9
+ - OpenCode `>=2.2.3 <2.3.0`, tested on 2.2.3 and 2.2.4. On any other version the plugin does not start, unless you set [`allowUntestedHost`](https://github.com/joe-broadhead/opencode-history/blob/HEAD/docs/configuration.md#options).
10
+ - macOS or Linux.
11
+ - Nothing else: no native programs, downloads or accounts. The index is SQLite with full-text search, through the `node:sqlite` module of OpenCode's runtime.
12
+
13
+ ## Install
14
+
15
+ ```sh
16
+ opencode plugin add @joe-broadhead/opencode-history
17
+ ```
18
+
19
+ Restart OpenCode. On first start the plugin indexes every session in OpenCode's database in the background, newest first. The tools work while it runs, over the sessions indexed so far. `/history-status`, or `/history` in the terminal UI, shows the progress.
20
+
21
+ ## Sign in
22
+
23
+ No sign-in or account. The plugin reads the OpenCode history on the machine it runs on.
24
+
25
+ ## Use
26
+
27
+ In Code Mode the tools are `tools.history.<name>`. The tool name and the permission action are `history_<name>`.
28
+
29
+ ```js
30
+ await tools.history.search({ query: ["login redirect loop", "OAuth callback redirects forever", "state mismatch"] })
31
+ await tools.history.brief({ sessionID: "ses_..." })
32
+ await tools.history.read({ sessionID: "ses_...", at: 42 })
33
+ await tools.history.sessions({ since: "7d", sort: "cost" })
34
+ await tools.history.files({ path: "src/auth/login.ts" })
35
+ await tools.history.recall({ question: "How did we fix the flaky upload test?", queries: ["flaky upload test", "upload test timeout"] })
36
+ await tools.history.sql({ sql: "select date(created) as day, round(sum(cost), 2) as cost from v_sessions group by day order by day desc", limit: 14 })
37
+ await tools.history.status({})
38
+ ```
39
+
40
+ - **Search, brief, read.** The usual lookup. `history_search` ranks sessions for two to four phrasings of one topic and returns excerpts, each with a `seq`. `history_brief` summarises one session: first prompt, compaction summaries, last reply, outcome, files edited, commands, subagents and todos. `history_read` reads the messages around a `seq`, with paging; with `kinds`, a window with none of those kinds widens to the nearest messages that have them. These three tools are pinned.
41
+ - **Sessions and files.** `history_sessions` lists sessions without a query, by last update, creation, cost or size. `history_files` lists the sessions that read or changed a file or folder, with counts per operation and the `seq` of the first touch.
42
+ - **Recall.** `history_recall` searches, takes the best sessions and returns quoted evidence with session IDs and `seq`s. With `synthesize: true` it also asks a model to write an answer from that evidence.
43
+ - **SQL.** `history_sql` runs one read-only `SELECT` or `WITH` statement over the index, for counts and reports. Its stable interface is four views, `v_sessions`, `v_docs`, `v_files` and `v_links`, and two full-text tables, `docs_words` (`MATCH`) and `docs_sub` (`text LIKE '%substring%'`). The other tables can change between versions.
44
+ - **Pin.** `history_pin` keeps a past session's brief, or a range of its messages, in the current session's instructions, so it stays in view through compactions. It is not in Code Mode, because it changes the current session.
45
+ - **Status.** `history_status` shows index progress, the source and the options in effect.
46
+
47
+ Search, sessions, files and recall look in the current project by default. They leave out the current session, subagent sessions and archived sessions unless you ask for them. The filters are `scope` (`project`, `directory`, `all` or `session`), `since` and `until` (an ISO date, or an age such as `36h`, `7d`, `3w`, `2m` or `1y`), `kinds`, `tool`, `agent`, `path`, `sessionID`, `includeSubagents`, `includeCurrent` and `includeArchived`.
48
+
49
+ Search has three modes. `words`, the default, matches stemmed words in any order and understands `"exact phrases"`, `-excluded` terms, `prefix*` and `OR`. A word joined by dots or dashes, such as a version `2.2.3`, an address `192.0.2.10` or a name `foo.bar.baz`, matches only as itself, not numbers or words with the same parts. `substring` matches exact text of at least three characters, for identifiers, paths and error messages. `regex` takes a JavaScript regular expression. Substring and regex mode read the newest 20,000 texts that may match, found through a trigram index.
50
+
51
+ When the sessions that have every word of a phrasing do not fill the page, a session that has only some of them also shows, marked `near match`, below them. Sessions in one directory that are runs of the same thing, with a near-identical title or the same first prompt, such as the runs of one scheduled prompt, show once, with a count of the `similar` others. When a search, `history_sessions` or `history_files` finds nothing, the result counts what the default filters left out, such as archived sessions, other projects or the current session's own subagents, and names the input that would show them.
52
+
53
+ One skill, `history-recall`, teaches the search, brief, read pattern and how to cite a session as `(ses_… #seq)`.
54
+
55
+ ### How it reads your history
56
+
57
+ The plugin API gives a plugin a session's context, which holds only the messages after the latest compaction, not the whole history. So the plugin opens OpenCode's own database (`~/.local/share/opencode/opencode.db`) **read-only** and copies the text it needs into an index of its own (`~/.local/share/opencode-history/index.db`). It never writes OpenCode's database, and it never changes a file it did not create. While OpenCode runs, session events keep the index current, and search, sessions and recall first catch up with anything newer, for at most about 200 ms.
58
+
59
+ The index holds prompts, replies, tool calls and their output, compaction summaries and session titles. Commands you run yourself in a session are indexed like `shell` tool calls, with the head and tail of their output. If the database cannot be read, the plugin falls back to the plugin session API, which has only the messages after each session's latest compaction; status says so and gives the fix.
60
+
61
+ ### Commands
62
+
63
+ - `/history-status` posts the status into the session: the connection, index progress and how far behind it is, the source, the database and index paths, the default scope, recall answers, the tools, agents without the default rules, the OpenCode version and one Next step.
64
+ - `/history-reindex` catches the index up with OpenCode's sessions. `/history-reindex rebuild` drops the index and indexes everything again.
65
+
66
+ ### Status dialog
67
+
68
+ In the terminal UI, `/history`, or **History: Status** in the command palette, opens a dialog with the same text as `/history-status`, without posting anything into the session. Press `r` to refresh it. While it is open it also refreshes when the server reconnects, an agent changes, or a session is created, deleted or goes idle. It changes nothing; close it with `esc`.
69
+
70
+ ### Scripts
71
+
72
+ A script or a cron job can call the same tools with no model, through `opencode api`. It runs as a session and its agent, under that agent's permission rules, and it can read history but never pin:
73
+
74
+ ```sh
75
+ opencode api post /api/rpc/history.sessions.tools/search \
76
+ -d '{"input":{"sessionID":"ses_…","input":{"query":["flaky upload test"],"scope":"all"}}}'
77
+ ```
78
+
79
+ See [Scripting](https://github.com/joe-broadhead/opencode-history/blob/HEAD/docs/scripting.md).
80
+
81
+ ## Permissions
82
+
83
+ The plugin puts a default block after each agent's base `* * allow` rule:
84
+
85
+ | Tool | Default |
86
+ |---|---|
87
+ | `history_search`, `history_read`, `history_brief`, `history_sessions`, `history_files`, `history_recall`, `history_sql`, `history_status` | allow |
88
+ | `history_pin`, which changes the current session's instructions | ask |
89
+ | any other `history_*` tool | ask |
90
+
91
+ Your own rules come later, so they win. `scope` chooses what is relevant; it is not access control. An agent that has these tools can read any indexed session in any project, and `history_sql` always covers every project. To keep an agent out of your history, deny the tools. A deny hides the matching tools:
92
+
93
+ ```jsonc
94
+ {
95
+ "agents": {
96
+ "reviewer": {
97
+ "permissions": [
98
+ { "action": "history_*", "resource": "*", "effect": "deny" }
99
+ ]
100
+ }
101
+ }
102
+ }
103
+ ```
104
+
105
+ Put the same rule in the top-level `permissions` to remove the tools from every agent, or name single tools such as `history_sql` or `history_pin`. Every rule needs `"resource"`. OpenCode skips a rule without it. Agents defined only in your config miss the default block; `/history-status` names them and gives the block to put first in their own `permissions`. The full rules are in [docs/configuration.md](https://github.com/joe-broadhead/opencode-history/blob/HEAD/docs/configuration.md#permissions).
106
+
107
+ ## Configure
108
+
109
+ Options go on the plugin entry in `opencode.json`:
110
+
111
+ ```jsonc
112
+ {
113
+ "plugins": [{
114
+ "package": "@joe-broadhead/opencode-history",
115
+ "options": {
116
+ "defaultScope": "project",
117
+ "mask": ["internal-token-[0-9a-f]{32}"],
118
+ "recall": { "synthesize": false }
119
+ }
120
+ }]
121
+ }
122
+ ```
123
+
124
+ `database` points at OpenCode's database and `indexPath` moves the index. `indexPath` must be a new file or an existing History index, outside OpenCode's data folder and outside the project; anything else fails setup with `INDEX_PATH_REFUSED` and is left untouched, whichever config sets it. `defaultScope` is the scope when a call names none. `index.reasoning`, `index.toolResults` and `index.maxDocChars` choose what is indexed. Built-in patterns mask common credentials before text is stored or shown: private keys, API keys and tokens with well-known prefixes (such as `sk-`, `ghp_`, `xai-`, `AKIA`), JSON Web Tokens, `Bearer` and `Authorization` header credentials, and `password=`, `secret=`, `token=` and `api_key=` values. `mask` adds your own patterns, and `maskDefaults: false` turns the built-in ones off. `recall.synthesize` and `recall.model` control recall answers. `allowUntestedHost` loads on an untested OpenCode version, with a warning in status. An invalid option fails setup and names the key, never the value. The full reference, with every limit and error code, is [docs/configuration.md](https://github.com/joe-broadhead/opencode-history/blob/HEAD/docs/configuration.md).
125
+
126
+ The `index` options, `mask` and `maskDefaults` apply to text indexed from then on. After you change them, run `/history-reindex rebuild` so the text already in the index follows them too.
127
+
128
+ ## Organisation rollout
129
+
130
+ An organisation can install the plugin for every user on a machine through OpenCode's system config: `/Library/Application Support/opencode/opencode.json` on macOS, `/etc/opencode/opencode.json` on Linux. It overrides user and project config.
131
+
132
+ ```json
133
+ {
134
+ "plugins": [{ "package": "@joe-broadhead/opencode-history", "options": { "mask": ["internal-token-[0-9a-f]{32}"] } }],
135
+ "permissions": [
136
+ { "action": "history_sql", "resource": "*", "effect": "deny" }
137
+ ]
138
+ }
139
+ ```
140
+
141
+ There is nothing to sign in to and no client ID to set. `mask` adds patterns that are masked before text is indexed or shown. A deny in `permissions` removes a tool for every agent; deny `history_*` to keep agents out of history altogether.
142
+
143
+ ## Troubleshooting
144
+
145
+ Start with `/history-status` or `history_status`. They end with one next step. Errors read `CODE: what happened. Next step: What to do.`
146
+
147
+ | State or code | What to do |
148
+ | --- | --- |
149
+ | `Source: plugin session API (partial)` | Status names the cause. `SOURCE_UNAVAILABLE`: point `database` at OpenCode's `opencode.db`, then restart OpenCode. `SOURCE_SCHEMA_UNKNOWN`: OpenCode's database has a layout this version does not know, so update the plugin or use a tested OpenCode. |
150
+ | `Connection: connecting`, `Index: building` | The first indexing pass is still running, and results cover only the sessions indexed so far. Wait for it to finish. |
151
+ | `Connection: failed` | The history is partial (see `Source`) or the index belongs to another plugin version (`INDEX_MISMATCH`). Follow the next step. |
152
+ | `Agents without default rules: …` | Those agents run every History tool, `history_pin` included, without asking. Put the block status shows first in each agent's own `permissions`. |
153
+ | `Index: ..., 35 s behind` | Seconds since the index was last in step with OpenCode. The next search, sessions or recall call catches up, or run `/history-reindex`. |
154
+ | A recent session is missing | Search, sessions and recall catch up for up to about 200 ms before they answer. A longer catch-up finishes in the background, so run `/history-reindex` to wait for it. |
155
+ | `HOST_UNTESTED` | Use OpenCode 2.2.3 or a later 2.2.x, or set `allowUntestedHost: true` and accept the warning. |
156
+ | `OPTIONS_INVALID` | The message names the option. Fix it in the plugin entry and restart. |
157
+ | `SOURCE_UNAVAILABLE` | OpenCode's database stopped answering. Check that `database` points at OpenCode's `opencode.db`, then restart OpenCode. |
158
+ | `INDEX_UNAVAILABLE` | `indexPath` must be a file the plugin can create and write. Fix it and restart. |
159
+ | `INDEX_PATH_REFUSED` | `indexPath` names OpenCode's database or data folder, a file inside the project, or an existing file that is not a History index. The file was left as it was. Set `indexPath` to a new file elsewhere, or remove it, and restart. |
160
+ | `INDEX_BUSY` | Another process, such as a second OpenCode, is writing the index. Retry in a moment. |
161
+ | `INDEX_FAILED` | Run `/history-status`, and if it persists, delete the index file and restart OpenCode. |
162
+ | `INDEX_MISMATCH`, `Index schema: ...` | Another OpenCode process running another version of the plugin rebuilt the index for its own version; status shows both versions. Restart every OpenCode process so they all run one version; the index is then rebuilt for it. |
163
+ | `SESSION_NOT_FOUND` | Find the session ID with `history_search` or `history_sessions`. |
164
+ | `QUERY_INVALID` | Fix the regular expression or the date, or search with `match: "words"`. |
165
+ | `SQL_REJECTED`, `SQL_FAILED` | Write one read-only `SELECT` or `WITH` statement, best over the `v_*` views. The message says what was wrong. |
166
+ | `SQL_TIMEOUT` | The statement ran longer than 10 seconds and was stopped. Filter by time or session, and bound a recursive `WITH`. |
167
+ | `PERMISSION_DENIED`, `SESSION_UNKNOWN`, `SESSION_AGENT_REQUIRED` | Scripts only: the session's agent may not use the tool, the session does not exist, or it names no agent. See [Scripting](https://github.com/joe-broadhead/opencode-history/blob/HEAD/docs/scripting.md). |
168
+ | `RECALL_MODEL_UNAVAILABLE` | OpenCode has no model to write the answer. Set `recall.model` to a model OpenCode can use, or call `history_recall` with `synthesize: false`. |
169
+ | `RECALL_FAILED` | The model call failed. Call `history_recall` with `synthesize: false` for the evidence only. |
170
+ | `PIN_TOO_LARGE` | Pin a shorter range, or a lower `maxChars`. |
171
+ | `OPERATION_FAILED` | Something unexpected failed. Retry, and if it persists, the OpenCode server log has one `opencode-history:` line with the error's class, its SQLite code and where it was thrown, to report. |
172
+
173
+ The full list of codes is in [docs/configuration.md](https://github.com/joe-broadhead/opencode-history/blob/HEAD/docs/configuration.md#errors). Error and status text never contains your input, session text or SQLite's own message.
174
+
175
+ ## Uninstall
176
+
177
+ ```sh
178
+ opencode plugin remove @joe-broadhead/opencode-history
179
+ ```
180
+
181
+ Removing the plugin keeps the index. To delete it, remove `~/.local/share/opencode-history` (or your `indexPath`, with its `-wal` and `-shm` files). OpenCode's database is not touched either way. Pins are instruction entries that OpenCode keeps on the sessions where you made them; the plugin does not remove them when it is uninstalled, so remove them first with `history_pin` and `"action": "remove"`. Rules you added to `permissions` stay until you remove them.
182
+
183
+ ## Links
184
+
185
+ - [Configuration reference](https://github.com/joe-broadhead/opencode-history/blob/HEAD/docs/configuration.md)
186
+ - [Scripting](https://github.com/joe-broadhead/opencode-history/blob/HEAD/docs/scripting.md)
187
+ - [Architecture](https://github.com/joe-broadhead/opencode-history/blob/HEAD/docs/architecture.md)
188
+ - [Security policy](https://github.com/joe-broadhead/opencode-history/blob/HEAD/SECURITY.md)
189
+ - [Changelog](https://github.com/joe-broadhead/opencode-history/blob/HEAD/CHANGELOG.md)
190
+ - [Contributing](https://github.com/joe-broadhead/opencode-history/blob/HEAD/CONTRIBUTING.md): build, tests and checks
191
+ - [Issues](https://github.com/joe-broadhead/opencode-history/issues)
192
+
193
+ Licensed under the [MIT licence](https://github.com/joe-broadhead/opencode-history/blob/HEAD/LICENSE).