opencode-metis 0.1.4 → 0.1.6
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/README.md +148 -43
- package/dist/cli.cjs +19 -20
- package/dist/mcp-server.cjs +14 -14
- package/dist/plugin.cjs +4 -4
- package/dist/worker.cjs +153 -56
- package/package.json +5 -6
package/README.md
CHANGED
|
@@ -1,20 +1,28 @@
|
|
|
1
1
|
# opencode-metis
|
|
2
2
|
|
|
3
|
-
Persistent memory system for [OpenCode](https://opencode.ai) sessions. Captures observations, enables semantic search, and preserves context across compaction.
|
|
3
|
+
Persistent memory system for [OpenCode](https://opencode.ai) sessions. Captures observations, compresses them with AI, enables semantic search, and preserves context across compaction.
|
|
4
4
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
7
|
-
- **
|
|
8
|
-
- **Semantic search** — Find relevant memories by meaning, not just keywords
|
|
7
|
+
- **AI-compressed observations** — Tool outputs are distilled into structured knowledge by Gemini, OpenRouter, or Anthropic
|
|
8
|
+
- **Semantic search** — Find relevant memories by meaning via ChromaDB vector embeddings, not just keywords
|
|
9
|
+
- **Context injection** — Relevant past observations are automatically injected at session start
|
|
9
10
|
- **Compaction survival** — Saves and restores context when OpenCode compacts messages
|
|
11
|
+
- **Privacy protection** — `<private>` tag stripping and automatic secret detection (API keys, tokens, PEM keys) before storage
|
|
12
|
+
- **Crash recovery** — Pending message queue with at-least-once delivery ensures no observations are lost
|
|
10
13
|
- **Quality checks** — TDD enforcement and file-length warnings on every edit
|
|
11
14
|
- **Tool redirection** — Block or redirect specific tools via configuration
|
|
12
|
-
- **Local-only** — All data stays on your machine at `~/.config/opencode/memory
|
|
15
|
+
- **Local-only** — All data stays on your machine at `~/.config/opencode/memory/`; only AI compression calls leave the machine
|
|
13
16
|
|
|
14
17
|
## Prerequisites
|
|
15
18
|
|
|
16
|
-
|
|
17
|
-
|
|
19
|
+
| Tool | Version | Required | Purpose |
|
|
20
|
+
|------|---------|----------|---------|
|
|
21
|
+
| [Bun](https://bun.sh) | >= 1.0.0 | Yes | Runtime for the worker daemon, plugin, and build system |
|
|
22
|
+
| [uv](https://github.com/astral-sh/uv) | latest | No | Runs `chroma-mcp` for semantic vector search (installed automatically by `init`) |
|
|
23
|
+
| API key | — | No | One of `GEMINI_API_KEY`, `OPENROUTER_API_KEY`, or `ANTHROPIC_API_KEY` for AI observation compression |
|
|
24
|
+
|
|
25
|
+
ChromaDB is managed automatically via `chroma-mcp` (a Model Context Protocol server launched with `uvx`). If `uv` is not installed, the system falls back to SQLite FTS5 keyword search — no semantic search, but everything else works.
|
|
18
26
|
|
|
19
27
|
## Installation
|
|
20
28
|
|
|
@@ -32,67 +40,144 @@ Persistent memory system for [OpenCode](https://opencode.ai) sessions. Captures
|
|
|
32
40
|
|
|
33
41
|
This merges the required `plugin` and `mcp` entries into `~/.config/opencode/opencode.json`, copies framework files (agents, commands, skills) into `~/.config/opencode/`, and checks for ChromaDB availability. Existing config is backed up before modification.
|
|
34
42
|
|
|
43
|
+
3. (Optional) Set an AI provider for observation compression:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
# Pick one:
|
|
47
|
+
export GEMINI_API_KEY="your-key"
|
|
48
|
+
export OPENROUTER_API_KEY="your-key"
|
|
49
|
+
export ANTHROPIC_API_KEY="your-key"
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Without an API key, observations are stored with basic string truncation instead of AI compression.
|
|
53
|
+
|
|
35
54
|
## CLI
|
|
36
55
|
|
|
37
|
-
| Command
|
|
38
|
-
|
|
39
|
-
| `opencode-metis init`
|
|
40
|
-
| `opencode-metis start`
|
|
41
|
-
| `opencode-metis stop`
|
|
56
|
+
| Command | Description |
|
|
57
|
+
|---------|-------------|
|
|
58
|
+
| `opencode-metis init` | Configure `opencode.json` and copy framework files |
|
|
59
|
+
| `opencode-metis start` | Start the memory worker and launch opencode |
|
|
60
|
+
| `opencode-metis stop` | Stop the memory worker |
|
|
42
61
|
| `opencode-metis start-mcp` | Start the MCP server (used by opencode via `opencode.json` config) |
|
|
43
62
|
|
|
44
63
|
## Configuration
|
|
45
64
|
|
|
46
65
|
The memory system has its own optional config file at `~/.config/opencode/memory/settings.json` (separate from OpenCode's config). All fields have sensible defaults:
|
|
47
66
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
|
51
|
-
|
|
52
|
-
| `
|
|
53
|
-
| `
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
|
58
|
-
|
|
59
|
-
| `
|
|
67
|
+
### Worker
|
|
68
|
+
|
|
69
|
+
| Key | Type | Default | Description |
|
|
70
|
+
|-----|------|---------|-------------|
|
|
71
|
+
| `workerPort` | number | `41777` | HTTP port for the worker daemon |
|
|
72
|
+
| `workerBind` | string | `"127.0.0.1"` | Bind address for the worker |
|
|
73
|
+
|
|
74
|
+
### Storage
|
|
75
|
+
|
|
76
|
+
| Key | Type | Default | Description |
|
|
77
|
+
|-----|------|---------|-------------|
|
|
78
|
+
| `chromaDbUrl` | string | `"http://localhost:8000"` | ChromaDB server URL |
|
|
79
|
+
| `chromaDbEnabled` | boolean | `true` | Enable ChromaDB vector store |
|
|
80
|
+
|
|
81
|
+
### AI Compression
|
|
82
|
+
|
|
83
|
+
| Key | Type | Default | Description |
|
|
84
|
+
|-----|------|---------|-------------|
|
|
85
|
+
| `aiProvider` | string \| null | `null` | AI provider: `"gemini"`, `"openrouter"`, `"anthropic"`, or `null` (auto-detect from env) |
|
|
86
|
+
| `aiModel` | string \| null | `null` | Override the default model for the selected provider |
|
|
87
|
+
| `aiCompressionTimeoutMs` | number | `15000` | Timeout per AI compression call |
|
|
88
|
+
| `aiCompressionMaxRetries` | number | `3` | Max retries for failed compressions |
|
|
89
|
+
| `aiSkipTools` | string[] | `[]` | Tool names to skip during observation capture |
|
|
90
|
+
|
|
91
|
+
### Privacy
|
|
92
|
+
|
|
93
|
+
| Key | Type | Default | Description |
|
|
94
|
+
|-----|------|---------|-------------|
|
|
95
|
+
| `secretDetectionEnabled` | boolean | `true` | Detect and redact secrets before storage |
|
|
96
|
+
| `secretPatterns` | array | `[]` | Additional custom secret patterns `{ name, pattern }` |
|
|
97
|
+
|
|
98
|
+
### Retention & Context
|
|
99
|
+
|
|
100
|
+
| Key | Type | Default | Description |
|
|
101
|
+
|-----|------|---------|-------------|
|
|
102
|
+
| `recencyWindowDays` | number | `90` | Days to boost recent results |
|
|
103
|
+
| `retentionDays` | number | `365` | Days before observations expire |
|
|
104
|
+
| `contextTokenBudget` | number | `2000` | Max tokens for context injection at session start |
|
|
105
|
+
|
|
106
|
+
### Quality Checks
|
|
107
|
+
|
|
108
|
+
| Key | Type | Default | Description |
|
|
109
|
+
|-----|------|---------|-------------|
|
|
110
|
+
| `tddEnabled` | boolean | `true` | Enforce test-file checks on edit |
|
|
111
|
+
| `fileLengthWarn` | number | `300` | Line count warning threshold |
|
|
112
|
+
| `fileLengthCritical` | number | `500` | Line count critical threshold |
|
|
113
|
+
| `testFilePatterns` | string[] | `["*.test.ts", "*.spec.ts", "*_test.go", "test_*.py"]` | Glob patterns for test files |
|
|
114
|
+
| `toolRedirectRules` | array | `[]` | Rules to deny or redirect specific tools |
|
|
115
|
+
|
|
116
|
+
### Notifications
|
|
117
|
+
|
|
118
|
+
| Key | Type | Default | Description |
|
|
119
|
+
|-----|------|---------|-------------|
|
|
120
|
+
| `notificationsEnabled` | boolean | `false` | Enable macOS desktop notifications for session events |
|
|
60
121
|
|
|
61
122
|
## Architecture
|
|
62
123
|
|
|
63
124
|
The system has four components, each built as a separate bundle under `dist/`:
|
|
64
125
|
|
|
65
126
|
- **CLI** (`dist/cli.cjs`) — Orchestrates init, start, and stop commands
|
|
66
|
-
- **Plugin** (`dist/plugin.cjs`) — Hooks into OpenCode's lifecycle events to capture observations
|
|
67
|
-
- **Worker** (`dist/worker.cjs`) — HTTP daemon that stores observations in SQLite, manages ChromaDB
|
|
127
|
+
- **Plugin** (`dist/plugin.cjs`) — Hooks into OpenCode's lifecycle events to capture observations, enforce quality checks, and inject context
|
|
128
|
+
- **Worker** (`dist/worker.cjs`) — Bun HTTP daemon with bearer token auth that stores observations in SQLite (WAL mode), manages ChromaDB via chroma-mcp, runs AI compression, and serves search queries
|
|
68
129
|
- **MCP Server** (`dist/mcp-server.cjs`) — Exposes memory tools to the AI via the Model Context Protocol
|
|
69
130
|
|
|
131
|
+
### Data Flow
|
|
132
|
+
|
|
133
|
+
```
|
|
134
|
+
OpenCode Session
|
|
135
|
+
│
|
|
136
|
+
├─ session.created ──────► Worker /api/context/inject ──► SQLite + ChromaDB query ──► context injected
|
|
137
|
+
│
|
|
138
|
+
├─ tool.execute.after ───► Worker /api/memory/save ────► privacy strip ──► SQLite write
|
|
139
|
+
│ │
|
|
140
|
+
│ └──► AI compression queue ──► Gemini/OpenRouter/Anthropic
|
|
141
|
+
│ │
|
|
142
|
+
│ └──► update observation with structured data
|
|
143
|
+
│
|
|
144
|
+
├─ session.idle ─────────► Worker /api/memory/save ────► session summary stored
|
|
145
|
+
│
|
|
146
|
+
└─ session.compacted ───► Worker /api/context/inject ──► context restored after compaction
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### Security
|
|
150
|
+
|
|
151
|
+
- **Bearer token auth** — A cryptographically random token is generated per worker instance and stored in the PID file. All non-health endpoints require `Authorization: Bearer <token>`.
|
|
152
|
+
- **Privacy stripping** — `<private>` tags are removed at the hook layer before data leaves the plugin process. Secrets (AWS keys, GitHub tokens, API keys, PEM keys, JWTs) are detected via regex and redacted with `[REDACTED]`.
|
|
153
|
+
- **Localhost binding** — The worker binds to `127.0.0.1` by default.
|
|
154
|
+
|
|
70
155
|
## MCP Tools
|
|
71
156
|
|
|
72
157
|
Tools available to the AI through the MCP server:
|
|
73
158
|
|
|
74
|
-
| Tool
|
|
75
|
-
|
|
76
|
-
| `search`
|
|
77
|
-
| `timeline`
|
|
78
|
-
| `get_observations` | Fetch full details for specific observation IDs.
|
|
79
|
-
| `save_memory`
|
|
80
|
-
| `decisions`
|
|
81
|
-
| `changes`
|
|
159
|
+
| Tool | Description |
|
|
160
|
+
|------|-------------|
|
|
161
|
+
| `search` | Semantic or keyword search across observations. Accepts `query`, optional `limit`, `type`, and `project` filters. |
|
|
162
|
+
| `timeline` | Chronological context around an observation. Accepts `anchor` (ID, session ID, timestamp, or query) with `depth_before`/`depth_after`. |
|
|
163
|
+
| `get_observations` | Fetch full details for specific observation IDs. |
|
|
164
|
+
| `save_memory` | Save a new observation with `text`, optional `title` and `project`. |
|
|
165
|
+
| `decisions` | Search decision-type observations. Optional `query` and `project` filters. |
|
|
166
|
+
| `changes` | Get recent change-type observations. Optional `project` and `limit`. |
|
|
82
167
|
|
|
83
168
|
The plugin also registers `memory_search` and `memory_save` as custom tools directly in OpenCode.
|
|
84
169
|
|
|
85
170
|
## Plugin Hooks
|
|
86
171
|
|
|
87
|
-
| Hook
|
|
88
|
-
|
|
89
|
-
| `session.created`
|
|
90
|
-
| `tool.execute.before`
|
|
91
|
-
| `tool.execute.after`
|
|
92
|
-
| `session.idle`
|
|
93
|
-
| `experimental.session.compacting` | Saves active plan and task state before compaction
|
|
94
|
-
| `session.compacted`
|
|
95
|
-
| `file.edited`
|
|
172
|
+
| Hook | Purpose |
|
|
173
|
+
|------|---------|
|
|
174
|
+
| `session.created` | Injects relevant memory context at session start |
|
|
175
|
+
| `tool.execute.before` | Enforces tool redirect rules (deny/redirect) before execution |
|
|
176
|
+
| `tool.execute.after` | Captures tool executions as observations (with AI compression) |
|
|
177
|
+
| `session.idle` | Saves session summaries when the session goes idle |
|
|
178
|
+
| `experimental.session.compacting` | Saves active plan and task state before compaction |
|
|
179
|
+
| `session.compacted` | Restores memory context after compaction |
|
|
180
|
+
| `file.edited` | Checks for missing test files and warns on file length |
|
|
96
181
|
|
|
97
182
|
## Local Development
|
|
98
183
|
|
|
@@ -132,11 +217,31 @@ bun run unlink # unstow
|
|
|
132
217
|
```bash
|
|
133
218
|
bun test # Run tests
|
|
134
219
|
bun run build # Build all four bundles
|
|
135
|
-
bun run lint #
|
|
220
|
+
bun run lint # Lint and format with Biome
|
|
136
221
|
bun run typecheck # TypeScript type checking
|
|
137
222
|
bun run dev # Watch mode for worker
|
|
138
223
|
```
|
|
139
224
|
|
|
225
|
+
### Project Structure
|
|
226
|
+
|
|
227
|
+
```
|
|
228
|
+
src/
|
|
229
|
+
cli/ CLI commands (init, start, stop, start-mcp) and worker lifecycle
|
|
230
|
+
mcp/ MCP server and worker proxy
|
|
231
|
+
plugin/ OpenCode plugin hooks, privacy filters, and custom tools
|
|
232
|
+
hooks/ Hook handlers (session-start, tool-after, session-idle, etc.)
|
|
233
|
+
privacy/ Secret detection, <private> tag stripping, privacy filter
|
|
234
|
+
tools/ Custom MCP tools registered in OpenCode
|
|
235
|
+
services/ Business logic layer
|
|
236
|
+
ai-compression/ Multi-provider AI agents (Gemini, OpenRouter, Anthropic), queue processor
|
|
237
|
+
shared/ Configuration, types, constants
|
|
238
|
+
storage/
|
|
239
|
+
sqlite/ Database, migrations, FTS5 indexing
|
|
240
|
+
vector/ ChromaDB connection, chroma-mcp manager, vector sync
|
|
241
|
+
worker/ HTTP server, router, routes, SSE broadcaster, auth middleware
|
|
242
|
+
test/ Integration and E2E tests
|
|
243
|
+
```
|
|
244
|
+
|
|
140
245
|
## License
|
|
141
246
|
|
|
142
247
|
MIT
|