opencode-agent-memory
Memory framework
Created by Josh Thomas
Published in joshuadavidthomas/opencode-agent-memory. Publisher page
360 GitHub stars
What it is
Letta-style editable memory blocks for OpenCode.
AutoGineer overview, from the brain’s own files
opencode-agent-memory is an experimental plugin for the OpenCode environment that introduces persistent, self-editable memory blocks and a semantic-searchable journal. Inspired by the Letta framework, it allows agents to maintain state across sessions by reading and writing to structured markdown files. The system supports global and project-specific memory scopes, enabling agents to store preferences, codebase conventions, and architectural details. Additionally, it features an optional, local-first journal for recording decisions and insights, utilizing local embeddings for semantic retrieval without external data transmission.
How it works
Memory model: Vector store
AutoGineer overview, from the brain’s own files
The plugin functions by injecting memory blocks as markdown files into the agent's context. These blocks are defined with YAML frontmatter containing metadata like labels and descriptions. Agents interact with these files using dedicated tools for listing, reading, updating, and replacing content. A separate journal system allows for append-only entries stored in markdown format, which are indexed for semantic search using local transformer models. Configuration is managed via a JSON file, allowing users to toggle global memory or the journal independently.
| Folder | Role | Files |
|---|---|---|
| .github | agent-config | 6 |
| src | source-code | 16 |
| .agents | folder | 5 |
| .amp | folder | 1 |
Requirements
Runtimes: Node.js, Bun
Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Google Antigravity, Kiro, OpenCode, Amp, Roo Code, Cline, JetBrains Junie, Devin (ex-Windsurf)
Set it up
- Not scanned by AutoGineerThe author’s README also describes installing it from a clone of its repository. Read its install section: AutoGineer did not scan that path. https://github.com/joshuadavidthomas/opencode-agent-memory/blob/a6d1c78abd2ff2daf1f9cfefb949dc23f4ca6ff1/README.md#installation
- Not scanned by AutoGineerIts dependencies are installed by npm when you run it and were not scanned by AutoGineer (4 declared). https://www.npmjs.com/package/opencode-agent-memory
Created by Josh Thomas. Published in joshuadavidthomas/opencode-agent-memory. Licence: MIT License.
Usage
AutoGineer overview, from the brain’s own files
- Managing agent persona and user preferences via persistent memory blocks.
- Storing project-specific architectural knowledge and coding conventions.
- Recording session-based insights and decisions in a searchable journal.
- Enabling agents to self-update their memory based on new project discoveries.
- “Update my project memory to include the new API authentication pattern.”
- The agent uses the memory_set or memory_replace tool to update the project-specific markdown file with the new authentication details.
- “Search my journal for previous decisions regarding the database migration.”
- The agent uses the journal_search tool to semantically query the local journal entries and return relevant findings.
Documentation by Josh Thomas
opencode-agent-memory
Letta-style editable memory blocks for OpenCode.
Experimental
This plugin is experimental. The core idea - giving the agent persistent, self-editable memory blocks - is adapted from Letta. Specifially, the plugin follows Letta's shared memory blocks pattern - the markdown files on disk are shared state that every OpenCode session can read and write.
Think of it as AGENTS.md with a harness. OpenCode supports rules via AGENTS.md and custom instruction files - this plugin is similar in spirit, but adds structure (scoped blocks with metadata and size limits), dedicated tools for memory operations, and prompting that encourages the agent to actively maintain its own memory. The content is similar; the scaffolding around it is what's different.
For background on the memory concept, see Letta's docs on memory and memory blocks.
Features
Persistent memory - Information survives across sessions and context compaction
Shared across sessions - Global blocks shared across all projects, project blocks shared across sessions in that codebase
Self-editing - The agent can read and modify its own memory with dedicated tools
Cache-stable system context - Memory is frozen per session and refreshed after context compaction, so edits do not repeatedly invalidate the provider prompt cache
Journal - Append-only entries with semantic search for capturing insights, decisions, and discoveries across sessions
Requirements
OpenCode v2.0.12 or later
Installation
Add to your OpenCode config (~/.config/opencode/opencode.json):
{
"plugins": ["opencode-agent-memory"]
}Restart OpenCode and you're ready to go.
Optionally, pin to a specific version for stability:
{
"plugins": ["[email protected]"]
}OpenCode fetches unpinned plugins from npm on each startup; pinned versions are cached and require a manual version bump to update.
Local Development
If you want to customize or contribute:
git clone https://github.com/joshuadavidthomas/opencode-agent-memory ~/.config/opencode/opencode-agent-memory
cd ~/.config/opencode/opencode-agent-memory
bun install
bun run buildThen add the checkout's absolute path to plugins in ~/.config/opencode/opencode.json.
Usage
Memory Tools
The plugin gives the agent 5 tools for managing memory:
| Tool | Description |
|---|---|
memory_list | List available memory blocks (labels, descriptions, sizes) |
memory_get | Read a block's current on-disk value and modification time |
memory_set | Create or update a memory block (full overwrite) |
memory_replace | Apply one or several exact replacements atomically |
memory_oversized | List blocks close to or over their soft size budget |
You interact with memory by editing the markdown files directly or asking the agent to update its memory.
Journal Tools
When the journal is enabled, the agent gets 3 additional tools:
| Tool | Description |
|---|---|
journal_write | Write a new journal entry with title, body, and optional tags |
journal_search | Search entries semantically, filter by project or tags, with pagination |
journal_read | Read a specific journal entry by ID |
Journal entries are append-only markdown files with YAML frontmatter, stored in ~/.config/opencode/journal/. Each entry records which project, model, provider, agent, and session it was written from. Semantic search uses local embeddings (all-MiniLM-L6-v2) - no data leaves your machine.
Default Blocks
By default, three blocks are seeded on first run:
| Block | Scope | Purpose |
|---|---|---|
persona | global | How the agent should behave and respond |
human | global | Details about you (preferences, habits, constraints) |
project | project | Codebase-specific knowledge (commands, architecture, conventions) |
These are just starting points. Create whatever blocks make sense for your workflow - debugging-notes, api-preferences, learned-patterns, etc.
Memory content is snapshotted when a session first uses it. Tool edits are immediately available through memory_get and remain visible in the conversation's tool results, while the injected snapshot stays byte-stable for prompt caching. OpenCode context compaction refreshes the snapshot from disk. Snapshots survive restarts and are cleaned up automatically.
Memory Locations
Global blocks:
~/.config/opencode/memory/*.mdProject blocks:
.opencode/memory/*.md(auto-gitignored)
Project-only Memory
To disable global memory blocks, set memory.disable_global in ~/.config/opencode/agent-memory.json:
{
"memory": {
"disable_global": true
}
}Restart OpenCode after changing this setting. It applies to all projects using this config file. The default is false; omitting the setting keeps global memory enabled.
When enabled, only the project block is seeded, and memory tools and system instructions use project scope only. Global blocks are not read, listed, or modified. Existing global files stay on disk untouched; set the option to false or remove it and restart to use them again. No migration is needed.
This setting only affects memory blocks. The optional journal remains shared across projects and is controlled separately by journal.enabled.
Journal-only Mode
To disable memory blocks and their tools while keeping the journal enabled:
{
"memory": {
"enabled": false
},
"journal": {
"enabled": true
}
}This does not seed, read, or inject memory blocks. It exposes only the journal tools and leaves existing memory files untouched.
A missing config file uses the defaults. For backward compatibility, unreadable files, malformed JSON, and non-object configuration also use defaults, with global memory enabled. OpenCode logs a warning on these failures. A malformed file cannot enforce the opt-out, even if it contains disable_global: true.
In a valid JSON object, invalid memory settings (such as "disable_global": "true" instead of a boolean) stop plugin initialization with a config error. Invalid journal settings disable the journal without discarding valid memory settings.
Block Format
Each block is a markdown file with YAML frontmatter:
| Field | Type | Default | Description |
|---|---|---|---|
label | string | filename | Unique identifier for the block |
description | string | generic | Tells the agent how to use this block |
limit | integer | 5000 | Soft in-context character budget |
read_only | boolean | false | Prevent agent from modifying |
All fields have defaults for graceful degradation, but description is essential - without it, the agent gets a generic fallback and won't know how to use the block effectively. See Letta's docs on the importance of the description field.
Writes above limit succeed instead of forcing retry loops. Over-budget blocks are marked over_limit in the next session snapshot so the agent can compact them with memory_replace or intentionally raise the limit.
Journal Configuration
The journal is opt-in. Enable it in ~/.config/opencode/agent-memory.json:
{
"journal": {
"enabled": true
}
}You can optionally suggest tags to guide the agent's classification:
{
"journal": {
"enabled": true,
"tags": [
{ "name": "perf", "description": "Performance optimization work" },
{ "name": "debugging", "description": "Debugging sessions and findings" }
]
}
}Tags are free-form strings - the agent can use any tag, not just the suggested ones. Suggested tags appear in the system prompt to provide guidance.
Inspiration
The memory architecture and philosophical framing are adapted from Letta (formerly MemGPT), a framework for building LLM agents with editable long-term memory.
Also worth exploring: private-journal-mcp by Jesse Vincent, which gives Claude a private journaling capability to process feelings and thoughts. His blog post about it explores similar territory around AI self-reflection and persistent inner experience.
Contributing
Contributions are welcome! Here's how to set up for development:
git clone https://github.com/joshuadavidthomas/opencode-agent-memory
cd opencode-agent-memory
bun install
bun run buildThen add the checkout's absolute path to your OpenCode config:
{
"plugins": ["/absolute/path/to/opencode-agent-memory"]
}License
opencode-agent-memory is licensed under the MIT license. See the LICENSE file for more information.
opencode-agent-memory is not built by, or affiliated with, the OpenCode team.
OpenCode is ©2025 Anomaly.
CHANGELOG.md
Changelog
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project attempts to adhere to Semantic Versioning.
<!-- ## [${version}] ### Added - for new features ### Changed - for changes in existing functionality ### Deprecated - for soon-to-be removed features ### Removed - for now removed features ### Fixed - for any bug fixes ### Security - in case of vulnerabilities [${version}]: https://github.com/joshuadavidthomas/opencode-agent-memory/releases/tag/v${version} -->
Unreleased
0.3.1
Fixed
Memory blocks and the journal note are now injected into compaction and generate requests, keeping the system prompt identical so the provider prompt cache is reused
Concurrent writes to the same memory block no longer fail with
ENOENT; each write now uses its own temp file
0.3.0
Added
Optional
memory.disable_globalsetting for project-only memory blocks, tools, and system instructions; existing global files are preserved for re-enablingOptional
memory.enabledsetting for journal-only operation without seeding, tools, or prompt injection for memory blocksmemory_getfor fresh on-disk reads andmemory_oversizedfor deterministic soft-budget auditsAtomic batch edits and optional limit updates in
memory_replacePersisted per-session memory snapshots that refresh after context compaction
Changed
Migrated the plugin entrypoint, tools, system-context hook, dependencies, tests, and development launcher to the stable OpenCode v2 API
Publish compiled ESM with an explicit v2 server entrypoint, verified from the packed artifact under Node
Memory character limits are soft budgets; over-limit writes succeed and are marked for compaction
Journal searches cache parsed entries and embeddings, load files in parallel, warm the model when enabled, and anchor title matches
Invalid memory settings in a valid JSON object report an initialization error; invalid journal settings no longer discard valid memory settings
Unreadable, malformed, or non-object configuration retains the default-settings fallback (global memory enabled), now with a warning in OpenCode's logs
Fixed
Removed per-request timestamps from injected memory metadata to preserve provider prompt caches
Matched memory tool label schemas to on-disk label validation
Use
js-yamlnamespace imports for Node ESM runtime compatibilityKeep journal model/provider metadata isolated across concurrent sessions
0.2.0
Added
Optional journal feature with semantic search, tagging, and tools for capturing insights and decisions across sessions
0.1.0
Added
Letta-style editable memory blocks for OpenCode
Three default memory blocks:
persona(global),human(global),project(project)Two scopes: global blocks (
~/.config/opencode/memory/) shared across all projects, project blocks (.opencode/memory/) scoped to codebaseThree memory tools:
memory_list,memory_set,memory_replaceSystem prompt injection via
experimental.chat.system.transformhookYAML frontmatter support for block metadata (label, description, limit, read_only)
Automatic gitignore for project memory blocks
Memory instructions and philosophical framing adapted from Letta
New Contributors
Josh Thomas <e-mail address on the upstream page> (maintainer)
37 files · 33 not served here
- .agents/check-opencode-v2 (not served here)
- .agents/check-package (not served here)
- .agents/check-plugin.ts (not served here)
- .agents/opencode (not served here)
- .agents/setup (not served here)
- .amp/services.yaml (not served here)
- .github/CODEOWNERS (not served here)
- .github/dependabot.yml (not served here)
- .github/workflows/lint.yml (not served here)
- .github/workflows/release.yml (not served here)
- .github/workflows/test.yml (not served here)
- .github/workflows/zizmor.yml (not served here)
- .gitignore (not served here)
- ATTRIBUTION.md
- CHANGELOG.md
- LICENSE
- README.md
- bun.lock (not served here)
- index.ts (not served here)
- package.json (not served here)
- src/embeddings.ts (not served here)
- src/frontmatter.test.ts (not served here)
- src/frontmatter.ts (not served here)
- src/journal.test.ts (not served here)
- src/journal.ts (not served here)
- src/letta.ts (not served here)
- src/memory.test.ts (not served here)
- src/memory.ts (not served here)
- src/plugin.test.ts (not served here)
- src/plugin.ts (not served here)
- src/prompt.test.ts (not served here)
- src/prompt.ts (not served here)
- src/snapshot.test.ts (not served here)
- src/snapshot.ts (not served here)
- src/tools.test.ts (not served here)
- src/tools.ts (not served here)
- tsconfig.json (not served here)
Advantages
- Persistent memory allows information to survive across sessions and context compaction. evidence: README.md
- Semantic search for journal entries runs locally with no data leaving the machine. evidence: README.md
- Memory is cache-stable, preventing repeated invalidation of the provider prompt cache. evidence: README.md
Limitations
- The plugin is currently experimental and may require manual configuration management. evidence: README.md
- Memory blocks have soft character limits that require agent management or manual intervention. evidence: README.md
Security
Risk level: No risk found
This brain runs
This brain runs nothing: AutoGineer found no hooks, scripts, plugin code or MCP servers in its files.
Attribution and licence
- Created by
- Josh Thomas
- Declared authors
- Josh Thomas (declared in package.json)
- Publisher
- Josh Thomas (Community)
- Source
- joshuadavidthomas/opencode-agent-memory · commit a6d1c78
- Licence
- MIT License (files served here)
- ATTRIBUTION.md (written by AutoGineer)
- Synced
AutoGineer is not affiliated with or endorsed by Josh Thomas.
Install from source
33 of its files are not served here, so there is no ZIP. joshuadavidthomas/opencode-agent-memory at a6d1c78