An opencode plugin for integrating with Vectorize Hindsight, an AI agent memory system. The plugin gives each opencode agent one configured Hindsight bank for automatic recall, automatic retention, manual tools, and TUI retain.
Status: This package is pre-1.0 alpha software. The one-agent/one-bank configuration model is a breaking pre-1.0 change. Test with non-critical memory banks before relying on it for important workflows.
- Per-agent Hindsight configuration via
agent.<name>.options.hindsight. - Global defaults with per-agent overrides.
applyMode: "opt-in"andapplyMode: "opt-out"support.- One Hindsight bank per enabled agent.
- Automatic memory recall at root session start.
- Configure session-start context injection with a Hindsight mental model ID or a custom recall query, with per-agent overrides.
- Automatic transcript retention on
session.statusidle events. - On-demand TUI session retention with
/hindsight-retain. - Pre-compaction retention and recall support.
- Manual tools:
hindsight_retainhindsight_recallhindsight_reflect
- Root-session-only automatic behavior, while manual tools remain available to configured child agents.
- Graceful degradation when disabled, unconfigured, or when Hindsight/API calls fail.
Advanced workflows that need multiple banks per agent should use the Hindsight CLI or Hindsight MCP server directly.
- Bun 1.3.10 or newer compatible runtime for development.
- opencode with
@opencode-ai/plugin>=1.14.41. - A running Hindsight API endpoint.
- Optional Hindsight API token, depending on your Hindsight deployment.
After the package is published to npm, install it in the environment where opencode loads plugins:
bun add @toady00/opencode-hindsightFor local development from this repository:
bun install
bun run buildThen reference the package from your opencode configuration.
If you are testing from a local checkout before publishing, build the package first and use your package manager's local-link workflow from the opencode configuration environment.
For a single shared project memory bank, this is the smallest useful setup:
.opencode/opencode.json:
.opencode/tui.json:
{
"plugin": ["@toady00/opencode-hindsight"]
}With this configuration, root sessions automatically recall from project at
startup, retain transcripts to project as the session goes idle, expose manual
retain/recall/reflect tools for configured agents, and enable the
/hindsight-retain TUI slash command.
The TUI command is configured in tui.json, not opencode.json. Keep all
Hindsight options, including hindsightApiUrl, defaults, applyMode, and
per-agent behavior, on the server plugin in opencode.json; the TUI plugin
reads that server configuration at runtime.
By default, automatic retention waits for three new user turns before retaining.
Set retainEveryNTurns to 1 while smoke-testing if you want the first idle
event after a prompt to retain immediately.
Add the server plugin to opencode.json:
{
"plugin": [
[
"@toady00/opencode-hindsight",
{
"hindsightApiUrl": "http://localhost:8888",
"hindsightApiToken": "optional-token",
"applyMode": "opt-in",
"debug": false,
"defaults": {
"bankId": "project",
"async": true,
"tags": ["source:opencode", "repo:my-project"],
"retainStrategy": "conversation",
"retainMode": "full-session",
"retainEveryNTurns": 3,
"retainConversationExtras": false,
"autoRetain": true,
"autoRecall": true,
"sessionStartMentalModel": null,
"sessionStartRecallPrompt": null
}
}
]
]
}Add the TUI plugin to tui.json if you want the /hindsight-retain TUI slash
command:
{
"plugin": ["@toady00/opencode-hindsight"]
}If you pin the server plugin to a version, pin the TUI plugin to the same version:
{
"plugin": ["@toady00/opencode-hindsight@0.2.2"]
}You can also configure the Hindsight endpoint via environment variables:
export HINDSIGHT_API_URL="http://localhost:8888"
export HINDSIGHT_API_TOKEN="optional-token"
export HINDSIGHT_DEBUG="true"Environment variables are used when the equivalent plugin options are omitted.
| Option | Description | Default |
|---|---|---|
hindsightApiUrl |
Hindsight API URL. Required unless HINDSIGHT_API_URL is set. |
none |
hindsightApiToken |
Optional API token. Can also use HINDSIGHT_API_TOKEN. |
none |
applyMode |
"opt-in" enables only agents with explicit hindsight config; "opt-out" enables agents unless they explicitly disable Hindsight. |
"opt-in" |
debug |
Enable debug logging. Can also use HINDSIGHT_DEBUG. |
false |
defaults |
Agent Hindsight defaults shared by enabled agents. | built-in defaults |
If no Hindsight API URL is configured, the plugin logs an error and returns no hooks so opencode can continue.
applyMode controls how the plugin decides whether an agent receives Hindsight
behavior:
"opt-in": agents are disabled by default. Add anoptions.hindsightblock to enable an agent. Setenabled: falseinside that block to keep the agent disabled while documenting its intended configuration."opt-out": agents are enabled by default and receive plugin defaults. Setenabled: falsein an agent'soptions.hindsightblock to disable that agent.
When enabled is omitted from an agent config, the apply mode decides the
default. When enabled: true is present, that agent is enabled in either mode.
The defaults object and each agent's options.hindsight block use the same
field names:
| Field | Type | Default | Description |
|---|---|---|---|
enabled |
boolean |
apply-mode dependent | Per-agent override for whether Hindsight behavior is enabled. |
bankId |
string |
omitted | Hindsight bank used by this agent for automatic recall, automatic retention, manual tools, and TUI retain. |
async |
boolean |
true |
Whether retain calls use Hindsight async processing. |
tags |
string[] |
[] |
Tags attached to retain calls. |
retainStrategy |
string |
omitted | Hindsight retain strategy name. Must exist in Hindsight bank configuration. |
retainMode |
"full-session" | "last-turn" |
"full-session" |
Transcript scope used for idle auto-retain. |
retainEveryNTurns |
number |
3 |
User-turn interval for idle auto-retain. Minimum is 1. |
retainConversationExtras |
boolean |
false |
Whether retained transcripts include extra non-conversational content. By default, retain sends only conversational text and omits tool outputs, reasoning parts, thinking-style tags, synthetic text, ignored text, injected Hindsight memory blocks, and legacy user system prompts. Set to true to preserve the older, more verbose retention behavior where text-bearing extras are retained. |
autoRetain |
boolean |
true |
Whether idle and pre-compaction transcript retention run for root sessions. |
autoRecall |
boolean |
true |
Whether root session-start and compaction recall run. |
sessionStartMentalModel |
string | null |
undefined |
Hindsight mental model ID to fetch at root session start instead of performing generic recall. Use null to explicitly clear an inherited default. |
sessionStartRecallPrompt |
string | null |
undefined |
Custom query string for root session-start recall when no mental model is configured. Use null to explicitly clear an inherited default. |
Agent-level values replace plugin-level defaults using a shallow override model.
For example, a per-agent tags array replaces default tags instead of merging
with them.
Agent settings live under each agent's options.hindsight field:
{
"agent": {
"build": {
"options": {
"hindsight": {
"enabled": true,
"bankId": "build-memory",
"retainMode": "last-turn",
"retainEveryNTurns": 2,
"retainConversationExtras": false,
"tags": ["source:opencode", "agent:build"],
"async": true,
"retainStrategy": "conversation",
"autoRetain": true,
"autoRecall": true,
"sessionStartMentalModel": "build-agent-context"
}
}
},
"review": {
"options": {
"hindsight": {
"enabled": true,
"bankId": "review-memory",
"sessionStartMentalModel": null,
"sessionStartRecallPrompt": "Relevant code review preferences, recurring review findings, project risk areas, and recent review context."
}
}
},
"plan": {
"options": {
"hindsight": {
"enabled": false
}
}
}
}
}Agent markdown frontmatter uses the same nested hindsight object. Use nested
YAML only:
hindsight:
enabled: true
bankId: tester-memory
async: false
retainStrategy: conversation
retainMode: last-turn
retainEveryNTurns: 1
retainConversationExtras: false
autoRetain: true
autoRecall: true
tags:
- source:opencode
- agent:tester
sessionStartMentalModel: null
sessionStartRecallPrompt: Relevant testing conventions, flaky tests, and recent QA context for this repository.Add @toady00/opencode-hindsight to tui.json to enable the
/hindsight-retain slash command:
{
"plugin": ["@toady00/opencode-hindsight"]
}The package exports a ./tui entrypoint, but opencode resolves that entrypoint
internally when loading tui.json; do not put
@toady00/opencode-hindsight/tui in config. Also do not put the TUI plugin in
opencode.json; server plugins and TUI plugins are loaded by different
opencode runtimes.
Keep Hindsight options on the server plugin in opencode.json; no separate TUI
options are needed. The TUI plugin reads the loaded server plugin tuple from
opencode state when /hindsight-retain runs, so the same hindsightApiUrl,
hindsightApiToken, applyMode, and defaults apply to manual TUI retain.
Plugin and config changes, including adding the TUI plugin entry, require restarting opencode before they take effect.
To use the command, open a session in the TUI and type /hindsight-retain in
the command palette. The command retains the current session transcript to the
agent's configured bankId on demand. Manual TUI retain always sends the full
session transcript, uses the opencode session ID as the Hindsight document ID,
and re-running the command for the same session overwrites that retained
document. The retained transcript is filtered the same way as automatic
retention, so tool call records, tool outputs, reasoning parts, thinking-style
tags, synthetic text, ignored text, and injected Hindsight memory blocks are not
sent to Hindsight. It does not update automatic retain turn counters;
retainEveryNTurns only affects idle auto-retain.
Set retainConversationExtras: true in plugin defaults or per-agent
hindsight config if you want retained transcripts to keep text-bearing extras
such as tool outputs, reasoning/thinking text, synthetic/ignored text, and
legacy user system prompts.
If /hindsight-retain is missing or cannot find configuration, check:
.opencode/tui.jsoncontains the package spec, for example"plugin": ["@toady00/opencode-hindsight"]..opencode/opencode.jsoncontains the server plugin tuple withhindsightApiUrlorHINDSIGHT_API_URLis set.- opencode was restarted after editing either config file.
Root sessions can receive context from either a Hindsight mental model or a
recall query. Configure these fields in plugin-level defaults or override them
per agent.
Precedence rules:
- If
sessionStartMentalModelis configured, the plugin fetches that mental model ID from the agent'sbankIdand injects the content.recall()is not called. - If only
sessionStartRecallPromptis configured, the plugin callsrecall()with that custom query instead of the built-in default. - If neither is configured, the plugin uses the built-in default recall query.
sessionStartMentalModel and sessionStartRecallPrompt are mutually exclusive
in effect: a configured mental model always wins. Set a field to null to clear
an inherited plugin default for a specific agent.
Plugin-level default mental model:
{
"plugin": [
["@toady00/opencode-hindsight", {
"hindsightApiUrl": "http://localhost:8888",
"defaults": {
"bankId": "project-memory",
"sessionStartMentalModel": "project-architecture"
}
}]
]
}Per-agent custom recall prompt, clearing an inherited mental model:
{
"agent": {
"review": {
"options": {
"hindsight": {
"bankId": "review-memory",
"sessionStartMentalModel": null,
"sessionStartRecallPrompt": "Relevant code review preferences, recurring review findings, project risk areas, and recent review context."
}
}
}
}
}YAML frontmatter clearing an inherited mental model:
hindsight:
bankId: review-memory
sessionStartMentalModel: null
sessionStartRecallPrompt: Relevant code review context.Validation and limitations:
sessionStartMentalModelexpects a mental model ID, not the display name.- Empty strings and whitespace-only values are ignored with warnings.
- Invalid per-agent values, such as non-string non-null values, fall back to valid plugin defaults.
nullexplicitly clears an inherited plugin default without a warning.
For root sessions, the plugin marks a session for recall when the
session.created event arrives and the agent has autoRecall: true and a
configured bankId. On the next experimental.chat.system.transform hook, the
bank is queried with this fixed query unless session-start configuration
overrides it:
Relevant project context, user preferences, and recent work for this agent.
Successful recall results are appended to the system prompt in a
<hindsight_memories> block with an ISO timestamp. Existing system prompt
entries are preserved.
If the bank query fails, the session remains marked for recall so the plugin can retry on the next system transform. If the bank query succeeds but no memories are returned, the recall marker is consumed and no memory block is injected.
Automatic retention runs on session.status events where
status.type === "idle". The plugin also accepts the deprecated session.idle
event for compatibility with older event producers.
Auto-retain only runs for root sessions with autoRetain: true and a configured
bankId. Child sessions are skipped for automatic retention.
The plugin fetches all session messages, formats user and assistant
conversational text as a transcript, strips any previously injected Hindsight
memory blocks, tool/reasoning parts, thinking-style tags, synthetic text, and
ignored text, and retains the transcript to bankId using the session ID as the
document ID. Repeated retains overwrite the same session document.
Set retainConversationExtras: true to keep text-bearing extras in retained
transcripts and preserve the older, more verbose retention behavior.
The plugin extracts the last retainEveryNTurns user turns and their assistant
responses, formats that window as a transcript, and retains it as a new unique
document.
Before compaction, the plugin attempts to retain the full transcript to bankId
using the session ID as the document ID. This bypasses normal turn throttling and
retainMode. It then attempts compaction recall and appends any recalled memory
block to the compaction context.
Retention uses Hindsight async processing by default (async: true). Set
async: false when retain calls must wait for Hindsight to finish processing
before the plugin treats the retain as successful. The plugin submits async
retain operations but does not poll them or report later async failures.
retainStrategy applies to retain calls. Strategy names must already exist in
Hindsight bank configuration; this plugin only passes the configured strategy
name through to Hindsight.
Configured tags are attached to retain calls only. Recall and reflect tag
filtering is out of scope for this plugin.
Configured agents receive these tools:
Stores information in the agent's configured bankId.
Parameters:
content— required; cannot be empty.context— optional first-class Hindsight retain context.
retainStrategy, tags, and async behavior are controlled by user
configuration, not by tool arguments.
Example request:
{
"content": "The project uses Bun and tsup for building the plugin.",
"context": "Repository setup decision"
}Searches the agent's configured bankId and returns matching memories.
Parameters:
query— required; cannot be empty.
Synthesizes an answer from the agent's configured bankId.
Parameters:
query— required; cannot be empty.
Manual tools can be used in child sessions if the child agent has resolved Hindsight configuration. There is no child-session restriction on manual tools.
Install dependencies:
bun installBuild the ESM bundle and declarations:
bun run buildRun tests:
bun run testWatch build output during development:
bun run devThis project uses bd for issue tracking. After cloning the repository or
creating a new worktree, run this from the worktree root:
bd bootstrapThis project uses the official Hindsight opencode plugin as a reference point for the integration pattern while focusing this package's configuration on one Hindsight bank per opencode agent.
{ "plugin": [ [ "@toady00/opencode-hindsight", { "hindsightApiUrl": "http://localhost:8888", "applyMode": "opt-out", "defaults": { "bankId": "project", "autoRetain": true, "autoRecall": true, "tags": ["source:opencode", "repo:my-project"] } } ] ] }