Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
145 changes: 118 additions & 27 deletions .github/i18n/README.ar.md

Large diffs are not rendered by default.

137 changes: 114 additions & 23 deletions .github/i18n/README.de.md

Large diffs are not rendered by default.

141 changes: 117 additions & 24 deletions .github/i18n/README.nl.md

Large diffs are not rendered by default.

121 changes: 108 additions & 13 deletions .github/i18n/README.tr.md

Large diffs are not rendered by default.

81 changes: 68 additions & 13 deletions .github/i18n/README.zh.md

Large diffs are not rendered by default.

53 changes: 41 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
[![npm downloads](https://img.shields.io/npm/dm/opencode-mem.svg)](https://www.npmjs.com/package/opencode-mem)
[![license](https://img.shields.io/npm/l/opencode-mem.svg)](https://www.npmjs.com/package/opencode-mem)
[![GitHub stars](https://img.shields.io/github/stars/tickernelz/opencode-mem.svg)](https://github.com/tickernelz/opencode-mem)
[![Website](https://img.shields.io/badge/website-opencode--mem.zhafron.my.id-blue)](https://opencode-mem.zhafron.my.id)
[![Docs](https://img.shields.io/badge/docs-opencode--mem.zhafron.my.id%2Fdocs-blue)](https://opencode-mem.zhafron.my.id/docs/)

![OpenCode Memory Banner](.github/pics/banner.png)

Expand All @@ -13,7 +15,16 @@ A persistent memory system for AI coding agents that enables long-term context r

## Core Features

Local Turso/libSQL database with native vector search, persistent project memories, automatic user profile learning, unified memory-prompt timeline, full-featured web UI, intelligent prompt-based memory extraction, multi-provider AI support (OpenAI, Anthropic), 12+ local embedding models, smart deduplication, and built-in privacy protection.
- **Local database:** embedded Turso/libSQL with native vector search, stored under `storagePath`. No separate vector database.
- **Intelligent prompt-based memory extraction (auto-capture):** when a session goes idle, a background AI request turns the technical work into persistent project memories.
- **Automatic recall:** relevant memories and the user profile are injected into the model's context (`chatMessage`).
- **User profile learning:** a cross-project summary of your preferences, patterns and workflows.
- **Memory hygiene:** smart deduplication, optional update-on-capture, and optional dreaming consolidation with recoverable trash.
- **Multi-provider AI support:** any provider configured in OpenCode (`opencodeProvider` / `opencodeModel`), or a manual API: OpenAI Chat Completions, OpenAI Responses, Anthropic, MiniMax, OrcaRouter, Atlas Cloud, Cheaper Inference, API Route, Runcrate, CloudGPU.
- **Embeddings:** 12+ local embedding models on CPU (no GPU needed) or any OpenAI-compatible embeddings API.
- **Full-featured web UI:** unified memory–prompt timeline, user profile, skill library, Markdown vault and health stats, with optional HTTP Basic Auth.
- **Privacy:** `<private>` tags, credential redaction before capture, and optional encryption at rest.
- **Portability:** optional Markdown vault backend, and `memory` tool `export` / `import` / `migrate` for moved or copied projects.

## Memory credential redaction

Expand Down Expand Up @@ -169,7 +180,7 @@ Enable AES-256-GCM encryption for local Turso shards in `~/.config/opencode/open
}
```

On first start the plugin creates `~/.config/opencode/opencode-mem-db.key` (32-byte hex key, `chmod 600`) and migrates existing plaintext shards. Override with `"databaseEncryptionKey": "env://OPENCODE_MEM_DB_KEY"` or `"file://~/path/to.key"` if you manage the key yourself. Losing the key means the encrypted databases cannot be opened.
On first start the plugin creates `~/.config/opencode/opencode-mem-db.key` (32-byte hex key, `chmod 600`) and migrates existing plaintext shards. Override with `"databaseEncryptionKey": "env://OPENCODE_MEM_DB_KEY"` or `"file://~/path/to.key"` if you manage the key yourself. Losing the key means the encrypted databases cannot be opened. `databaseEncryptionCipher` selects the cipher: `aes256gcm` (default), `aes128gcm`, `aegis256`, `aegis256x2`, `aegis128l`, `aegis128x2` or `aegis128x4`.

**Windows:** use `%USERPROFILE%\.config\opencode\opencode.json` (for example `C:\Users\<you>\.config\opencode\opencode.json`). This plugin does **not** read `%APPDATA%` or `%LOCALAPPDATA%` for its OpenCode plugin entry — put the file under `.config\opencode` in your user profile, then restart OpenCode. If the plugin does not appear, confirm that path and restart again.

Expand All @@ -189,10 +200,10 @@ You do **not** need to ask OpenCode to “remember” things for the plugin to w

### Automatic vs manual memory

| Approach | When it runs | What you do |
| ------------------------------------------------------ | --------------------------------------------------- | ------------------------------------------------------------------------------------------ |
| **Auto-capture** (`autoCaptureEnabled: true`, default) | After conversation turns when the session goes idle | Nothing — extraction is automatic |
| **Manual** `memory` tool / commands | On demand | `add`, `search`, `list`, `profile`, `forget`, `list-shards`, `migrate`, `export`, `import` |
| Approach | When it runs | What you do |
| ------------------------------------------------------ | --------------------------------------------------- | -------------------------------------------------------------------------------------------------- |
| **Auto-capture** (`autoCaptureEnabled: true`, default) | After conversation turns when the session goes idle | Nothing — extraction is automatic |
| **Manual** `memory` tool / commands | On demand | `add`, `search`, `list`, `profile`, `forget`, `list-shards`, `migrate`, `export`, `import`, `help` |

Manual search/add/list still work even if auto-capture has no provider configured. Auto-capture and user profile learning need a provider that can return structured/tool-call output.

Expand Down Expand Up @@ -236,7 +247,7 @@ If you have chatted for a while and still see the message, check that auto-captu

### Web UI

Open `http://127.0.0.1:4747` to browse the memory–prompt timeline, inspect captures, and manage the user profile. If you bind the server beyond loopback, see [Web UI HTTP Basic Auth](#web-ui-http-basic-auth).
Open `http://127.0.0.1:4747` to browse the memory–prompt timeline, inspect captures, and manage the user profile. The UI has five views: **Project memories** (`/project-memories`), **User profile** (`/user-profile`), **Skill library** (`/skill-library`), **Markdown vault** (`/markdown-vault`) and **Stats** (`/stats`). Change the port with `webServerPort`, or set `webServerEnabled: false` to run without the web UI. If you bind the server beyond loopback, see [Web UI HTTP Basic Auth](#web-ui-http-basic-auth).

## Usage Examples

Expand Down Expand Up @@ -266,6 +277,20 @@ Configure at `~/.config/opencode/opencode-mem.jsonc`:

The plugin creates a full commented template at this path on first startup. For every setting and comment, see [`opencode-mem.example.jsonc`](opencode-mem.example.jsonc).

Commonly tuned top-level options:

| Option | Default | What it does |
| --------------------------------------------------------------------- | ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
| `storagePath` | `"~/.opencode-mem/data"` | Where the memory databases live. |
| `webServerEnabled` / `webServerPort` / `webServerHost` | `true` / `4747` / `"127.0.0.1"` | Web UI server switch, port and bind address. |
| `autoCaptureEnabled` | `true` | Summarize idle sessions into memories (needs a provider, see [Auto-Capture AI Provider](#auto-capture-ai-provider)). |
| `similarityThreshold` / `maxMemories` | `0.6` / `10` | Minimum similarity score and maximum number of results for memory search. |
| `injectProfile` | `true` | Inject the user profile (preferences, patterns, workflows) into the AI context. |
| `deduplicationEnabled` / `deduplicationSimilarityThreshold` | `true` / `0.9` | Detect and remove duplicate memories. |
| `autoCleanupEnabled` / `autoCleanupRetentionDays` | `true` / `30` | At most once a day, delete prompts older than, and memories not updated within, the retention window. Pinned memories are kept. |
| `showAutoCaptureToasts` / `showUserProfileToasts` / `showErrorToasts` | `true` | Toasts for auto-capture, profile updates and errors. |
| `autoUpdate` | `true` | Clear OpenCode's cached install when a newer npm release is available. |

### Markdown vault backend (`memoryBackend`)

By default memories live only in Turso under `storagePath`. Optionally set a **generic Markdown folder** as the source of truth (Obsidian/Raneto-compatible plain `.md` files — not an Obsidian-specific integration):
Expand Down Expand Up @@ -356,9 +381,6 @@ are never touched. Set `dreaming.crossProject: true` (or `memory.defaultScope:
**Trash** (restore) and **Dream** (manual run). Soft-deleted rows are hard-purged after
`dreaming.trashRetentionDays` during normal cleanup.

Deeper related-threshold dreaming (update/supersede/flag, cross-project) lands in the
follow-up PR for #464.

### Choosing / configuring embeddings

Embeddings power similarity search for memories and the user profile. Configure them in the same file (`~/.config/opencode/opencode-mem.jsonc`). There is **no MLX backend** — local embeddings use `@huggingface/transformers` with ONNX, not Apple MLX.
Expand Down Expand Up @@ -727,10 +749,14 @@ Build and test locally:
```bash
bun install
bun run build
bun run typecheck
bun run format
bun test
bun run check
```

`bun run check` runs `format:check`, `lint` and `typecheck`; `bun run format` rewrites formatting.

The [docs](https://opencode-mem.zhafron.my.id/docs/) are generated from this README and the translations under `.github/i18n/`; the [landing page](https://opencode-mem.zhafron.my.id) lives in `site/src/`. Every README heading must be mapped to a docs page in `site/docs-map.json`, otherwise the site build fails. Build the site locally with `cd site && bun install && bun run build`.

This project is actively seeking contributions to become the definitive memory plugin for AI coding agents. Whether you are fixing bugs, adding features, improving documentation, or expanding embedding model support, your contributions are critical. The codebase is well-structured and ready for enhancement. Please open issues with the Issue or Feature request templates, and fill out the pull request template when you submit a PR — we review and merge contributions quickly.

**README translations:** `README.md` (English) is the source of truth. When you change its content, update the files under `.github/i18n/` (`README.de.md`, `README.zh.md`, `README.ar.md`, `README.tr.md`, and `README.nl.md`) to match.
Expand All @@ -739,8 +765,11 @@ This project is actively seeking contributions to become the definitive memory p

MIT License - see LICENSE file

- **Website**: https://opencode-mem.zhafron.my.id
- **Docs**: https://opencode-mem.zhafron.my.id/docs/
- **Repository**: https://github.com/tickernelz/opencode-mem
- **Issues**: https://github.com/tickernelz/opencode-mem/issues
- **npm**: https://www.npmjs.com/package/opencode-mem
- **OpenCode Platform**: https://opencode.ai

Inspired by [opencode-supermemory](https://github.com/supermemoryai/opencode-supermemory)
4 changes: 4 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@
"type": "git",
"url": "git+https://github.com/tickernelz/opencode-mem.git"
},
"homepage": "https://opencode-mem.zhafron.my.id",
"bugs": {
"url": "https://github.com/tickernelz/opencode-mem/issues"
},
"publishConfig": {
"access": "public"
},
Expand Down
5 changes: 5 additions & 0 deletions site/astro.config.mjs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { readFileSync } from "node:fs";
import starlight from "@astrojs/starlight";
import { defineConfig } from "astro/config";
import { en } from "./src/i18n/en.ts";

const map = JSON.parse(readFileSync(new URL("./docs-map.json", import.meta.url), "utf8"));
const groups = [...new Set(map.pages.map((page) => page.group))];
Expand Down Expand Up @@ -45,6 +46,10 @@ export default defineConfig({
tag: "meta",
attrs: { property: "og:image", content: "https://opencode-mem.zhafron.my.id/og.png" },
},
{ tag: "meta", attrs: { property: "og:image:width", content: "1200" } },
{ tag: "meta", attrs: { property: "og:image:height", content: "630" } },
{ tag: "meta", attrs: { property: "og:image:alt", content: en.meta.ogImageAlt } },
{ tag: "meta", attrs: { name: "twitter:image:alt", content: en.meta.ogImageAlt } },
],
}),
],
Expand Down
2 changes: 2 additions & 0 deletions site/src/i18n/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ export const en = {
title: "opencode-mem: your OpenCode agent finally remembers",
description:
"opencode-mem gives OpenCode a long-term memory. It writes down decisions, fixes, and preferences while you work, and brings them back next session. Free, open source, and stored on your machine.",
ogImageAlt:
"opencode-mem: Your agent finally remembers. Long-term memory for OpenCode. Free, open source, stored on your machine.",
},
nav: {
how: "How it works",
Expand Down
12 changes: 12 additions & 0 deletions site/src/layouts/Landing.astro
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,12 @@ const jsonLd = {
softwareVersion: numbers.version,
license: "https://opensource.org/licenses/MIT",
url: Astro.site?.href,
description: copy.meta.description,
image: new URL("/og.png", Astro.site).href,
downloadUrl: "https://www.npmjs.com/package/opencode-mem",
sameAs: ["https://github.com/tickernelz/opencode-mem", "https://www.npmjs.com/package/opencode-mem"],
author: { "@type": "Person", name: "Zhafron Adani Kautsar", url: "https://github.com/tickernelz" },
isAccessibleForFree: true,
offers: { "@type": "Offer", price: "0", priceCurrency: "USD" },
};
---
Expand All @@ -40,12 +45,19 @@ const jsonLd = {
<link rel="preload" href={displayFont} as="font" type="font/woff2" crossorigin />
<meta name="theme-color" content="#0a0a0a" media="(prefers-color-scheme: dark)" />
<meta name="theme-color" content="#f5f4f8" media="(prefers-color-scheme: light)" />
<link rel="sitemap" href="/sitemap-index.xml" />
<meta property="og:type" content="website" />
<meta property="og:site_name" content="opencode-mem" />
<meta property="og:locale" content={lang} />
<meta property="og:title" content={copy.meta.title} />
<meta property="og:description" content={copy.meta.description} />
<meta property="og:url" content={canonical} />
<meta property="og:image" content={new URL("/og.png", Astro.site)} />
<meta property="og:image:width" content="1200" />
<meta property="og:image:height" content="630" />
<meta property="og:image:alt" content={copy.meta.ogImageAlt} />
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:image:alt" content={copy.meta.ogImageAlt} />
<script is:inline>
(() => {
const stored = localStorage.getItem("starlight-theme");
Expand Down
Loading