opencode-hindsight-plus
v0.3.13
Published
Claude-aligned Hindsight for OpenCode: transform-local recall, multi-bank, ingest tools, synthetic-user inject, knowledge pages
Maintainers
Readme
opencode-hindsight-plus
Hindsight memory plugin for OpenCode — persistent long-term memory with Claude Code-aligned per-turn auto-recall.
Fork of @vectorize-io/opencode-hindsight with per-user-turn memory injection (see SOURCE.txt).
Features
- Custom tools:
hindsight_retain,hindsight_recall,hindsight_reflect— the agent calls these explicitly - Per-turn auto-recall: On every user message, queries Hindsight with the current prompt (Claude Code
UserPromptSubmitalignment). DefaultrecallContextTurns: 1uses only the latest user text — no full-session re-fetch (Clauderecall.pypath). Multi-turn prior context (recallContextTurns > 1) is composed from the transform payload already in hand. Default inject mode issynthetic-user(asynthetic: truetext part on the latest user message, closer to ClaudeadditionalContext). SetrecallInjectMode: "system"to fold intosystem[0]instead (that path still loads session messages). Tool-loop reuses the turn cache. Successful inject logs at INFO (chars). Optional TUI toast via"injectToast": true(fresh inject only; tool-loop silent). - Multi-bank recall:
recallAdditionalBanksmerges results from extra banks (ClauderecallAdditionalBanks). - Auto-retain: Captures conversation on
session.idle(Claude CodeStopalignment). Throttle is Claude-styleuserTurns % retainEveryNTurns === 0. Transcripts are sanitized (stripU+0000/ C0 controls) before retain. - SessionEnd flush: Force-retains any pending turns on
session.deletedand plugindispose(Claude CodeSessionEndalignment), even when underretainEveryNTurns - Tool trajectory retain (opt-in): Set
retainToolCalls: trueto include tool call inputs/outputs in retained transcripts (skipshindsight_*tools). Default isfalse(Claude Code-aligned) to avoid fact/consolidation blowups from agent tool noise - Retain tag templates:
retainTags/retainMetadatasupport{session_id},{bank_id},{timestamp},{user_id}(emptyuser:tags dropped when unset) - Bank routing:
directoryBankMap(path → bank) +resolveWorktrees(linked worktrees share main-repo bank) — Claudebank.pyorder - Coding-oriented bank missions: default
bankMission/retainMissionguide fact extraction - Tools:
hindsight_retain/recall/reflect,hindsight_bank_current,hindsight_ingest,hindsight_ingest_file, plushindsight_page_*knowledge pages (Claudeagent_knowledge_*equivalents) - Compaction hook: Retains + injects query-relevant memories during context compaction so they survive window trimming
Quick Start
The plugin defaults to Hindsight Cloud (https://api.hindsight.vectorize.io). Just enable it and provide your API key.
1. Enable the plugin
Add to your opencode.json (project) or ~/.config/opencode/opencode.json (global):
{
"$schema": "https://opencode.ai/config.json",
"plugin": ["opencode-hindsight-plus"]
}OpenCode auto-installs plugins listed here on startup — no npm install required.
2. Provide your Hindsight Cloud API key
Get an API key at ui.hindsight.vectorize.io/connect, then:
export HINDSIGHT_API_TOKEN="your-api-key"
# Optional: override the memory bank ID (defaults to "opencode")
export HINDSIGHT_BANK_ID="my-project"That's it — the plugin now reads/writes against your Cloud bank.
Using a self-hosted Hindsight instance
Point HINDSIGHT_API_URL at your server (the API key is then optional):
export HINDSIGHT_API_URL="http://localhost:8888"Or configure inline in opencode.json:
{
"$schema": "https://opencode.ai/config.json",
"plugin": [
[
"opencode-hindsight-plus",
{
"hindsightApiUrl": "http://localhost:8888"
}
]
]
}Configuration
Plugin Options
Pass options directly in opencode.json:
{
"plugin": [
[
"opencode-hindsight-plus",
{
"hindsightApiUrl": "http://localhost:8888",
"bankId": "my-project",
"autoRecall": true,
"autoRetain": true,
"recallBudget": "mid"
}
]
]
}Config File
Create ~/.hindsight/opencode.json for persistent configuration:
{
"hindsightApiUrl": "http://localhost:8888",
"hindsightApiToken": "your-api-key",
"recallBudget": "mid",
"retainEveryNTurns": 3,
"debug": false
}Environment Variables
| Variable | Description | Default |
| ----------------------------- | -------------------------------------------------------- | ------------------------------------- |
| HINDSIGHT_API_URL | Hindsight API base URL | https://api.hindsight.vectorize.io |
| HINDSIGHT_API_TOKEN | API key for authentication | (none — required for Hindsight Cloud) |
| HINDSIGHT_BANK_ID | Static memory bank ID | opencode |
| HINDSIGHT_AGENT_NAME | Agent name for dynamic bank IDs | opencode |
| HINDSIGHT_AUTO_RECALL | Auto-recall on every user turn | true |
| HINDSIGHT_AUTO_RETAIN | Auto-retain on session idle | true |
| HINDSIGHT_RETAIN_MODE | full-session or last-turn | full-session |
| HINDSIGHT_RECALL_BUDGET | Recall budget: low, mid, high | mid |
| HINDSIGHT_RECALL_MAX_TOKENS | Max tokens for recall results | 1024 |
| HINDSIGHT_MIN_RECALL_PROMPT_CHARS | Skip auto-recall when user prompt is shorter | 5 |
| HINDSIGHT_RETAIN_TOOL_CALLS | Include tool call/result parts in retained transcripts | false |
| HINDSIGHT_RETAIN_TAGS | Comma-separated retain tags (templates supported) | {session_id} |
| HINDSIGHT_USER_ID | Used by {user_id} template in retain tags/metadata | (empty) |
| HINDSIGHT_ENABLE_KNOWLEDGE_PAGES | Register hindsight_page_* tools | true |
| HINDSIGHT_RECALL_INJECT_MODE | synthetic-user (default) or system | synthetic-user |
| HINDSIGHT_INJECT_TOAST | Show TUI toast on fresh memory inject | false |
| HINDSIGHT_RECALL_ADDITIONAL_BANKS | Comma-separated extra banks to merge on recall | (none) |
| HINDSIGHT_RECALL_TAGS | Comma-separated, filter recalls | (none) |
| HINDSIGHT_RECALL_TAGS_MATCH | Tag match mode: any, all, any_strict, all_strict | any |
| HINDSIGHT_RETAIN_TAGS | Comma-separated, added to every retain | (none) |
| HINDSIGHT_DYNAMIC_BANK_ID | Enable dynamic bank ID derivation | true |
| HINDSIGHT_RESOLVE_WORKTREES | Share bank across git linked worktrees | true |
| HINDSIGHT_BANK_MISSION | Bank mission/context | (none) |
Debug logging is a config-only option (
"debug": trueinopencode.jsonplugin options or~/.hindsight/opencode.json) — there is intentionally noHINDSIGHT_DEBUGenv var, because environment variables are unreliable to set for OpenCode's plugin runtime (notably on Windows). Errors and the resolved API URL/bank are logged regardless of this setting;debugonly adds verbose tracing. All plugin logs go to OpenCode's log stream (service=hindsight), visible with--print-logsor in the OpenCode log files.
Configuration Priority
Settings are loaded in this order (later wins):
- Built-in defaults
~/.hindsight/opencode.json- Plugin options from
opencode.json - Environment variables
Tools
hindsight_retain
Store information in long-term memory. The agent uses this to save important facts, user preferences, project context, and decisions.
hindsight_recall
Search long-term memory. The agent uses this proactively before answering questions where prior context would help.
hindsight_reflect
Generate a synthesized answer from long-term memory. Unlike recall (raw memories), reflect produces a coherent summary.
Knowledge pages (enableKnowledgePages, default true)
| Tool | Purpose |
|------|---------|
| hindsight_page_list | List page ids/names |
| hindsight_page_get | Read full page content |
| hindsight_page_create | Create page (name + source_query, optional page_id) |
| hindsight_page_update | Update name / source_query |
| hindsight_page_delete | Delete page |
| hindsight_page_refresh | Re-run source_query against current memories |
Disable:
{ "enableKnowledgePages": false }Dynamic Bank IDs (per-project isolation)
Default: dynamicBankId: true with dynamicBankGranularity: ["gitProject"].
Each git repository gets its own memory bank (main worktree basename). Linked worktrees of the same repo share one bank. Non-git directories fall back to the working-directory basename.
| Field | Meaning |
|-------|---------|
| gitProject | Main worktree basename (default) — worktrees share memory |
| project | Working directory basename — worktrees may split |
| agent | agentName (default opencode) |
| channel / user | From HINDSIGHT_CHANNEL_ID / HINDSIGHT_USER_ID |
Disable isolation (single global bank):
{
"dynamicBankId": false,
"bankId": "opencode"
}Or set:
export HINDSIGHT_DYNAMIC_BANK_ID=false
export HINDSIGHT_BANK_ID=opencodeCompose multiple dimensions:
{
"dynamicBankId": true,
"dynamicBankGranularity": ["agent", "gitProject"]
}Note: The bank ID is derived once when the plugin loads for a directory. For per-user isolation, set env vars before launching OpenCode:
export HINDSIGHT_CHANNEL_ID="slack-general"
export HINDSIGHT_USER_ID="user123"Development
npm install
npm test # Run tests
npm run build # Build to dist/License
MIT
