Skip to content

Commit 60dc9e6

Browse files
jpheinclaude
andcommitted
docs(integrations): OpenCode integration recipe + cherry-pick fork-changes entries
Adds the three-direction OpenCode + MemPalace integration recipe: - ``docs/integrations/opencode.md`` — full setup guide covering the read (MCP), push (live-capture plugin), and pull (retrospective backfill) paths for daemon-routed deployments. - ``examples/opencode/opencode.jsonc.example`` — copy-paste user config pointing at the palace-daemon wrapper. - ``examples/opencode/option-k-plugin-daemon-routing.patch`` — a re-applicable diff for option-K's ``opencode-plugin-mempalace`` v1.2.1 issue #1 (isInitialized passes ``--palace`` which bypasses ``PALACE_DAEMON_URL`` routing). Also adds two fork-changes.yaml entries for the cherry-picked upstream PRs already in this branch: - ``opencode-mcp-config-cherry-pick-1567`` (commit ba16b82) - ``opencode-source-adapter-cherry-pick-1484`` (commit 2ffe652) The recipe's own fork-changes.yaml entry is added in the next commit once this commit's SHA is known (avoids the self-referencing-commit anti-pattern flagged in the worktree handoff). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent ba16b82 commit 60dc9e6

5 files changed

Lines changed: 400 additions & 10 deletions

File tree

FORK_CHANGELOG.md

Lines changed: 71 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,74 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
1818
---
1919

2020

21+
## [2026-05-21]
22+
23+
24+
### Added
25+
26+
27+
- **.opencode/opencode.json — repo-root MCP config so opencode picks up mempalace automatically** ([`ba16b82`](https://github.com/jphein/mempalace/commit/ba16b82))
28+
Cherry-pick of upstream PR #1567 (Dxrk777). Adds
29+
`.opencode/opencode.json` so that running `opencode` in the
30+
mempalace repo root automatically wires `mempalace` as a local
31+
MCP server — useful for contributors who use OpenCode for
32+
development on the project itself.
33+
34+
Two-commit cherry-pick:
35+
36+
- `013ac63` — initial config with `command: ["mempalace-mcp"]`
37+
- `ba16b82` — gemini-code-assist review feedback: switch to
38+
`command: ["python", "-m", "mempalace.mcp_server"]` for
39+
portability across install methods (pip vs uv vs dev install)
40+
41+
This is the **dev/contributor surface** — it lives in the repo
42+
and only matters when running OpenCode against the repo root.
43+
Per-user setups should use `~/.config/opencode/opencode.jsonc`
44+
with the daemon-aware wrapper (see `docs/integrations/opencode.md`).
45+
46+
*Upstream:* [PR #1567](https://github.com/MemPalace/mempalace/pull/1567) (OPEN)
47+
*Files:* `.opencode/opencode.json`
48+
49+
50+
- **OpenCodeSourceAdapter (RFC 002) — retrospective ingest of OpenCode SQLite sessions** ([`2ffe652`](https://github.com/jphein/mempalace/commit/2ffe652))
51+
Cherry-pick of upstream PR #1484. Adds
52+
`mempalace/sources/opencode.py` — an RFC 002 `BaseSourceAdapter`
53+
that ingests OpenCode AI-coding-CLI session transcripts from
54+
`~/.local/share/opencode/opencode.db` into the palace, formatted
55+
to match `convo_miner`'s exchange-pair drawer shape.
56+
57+
Five-commit cherry-pick:
58+
59+
- `2c368c6` — initial adapter (482-line `opencode.py`, 6
60+
opencode-namespaced reference transformations in
61+
`transforms.py`, entry-point registration, 28 tests, sample
62+
SQLite-schema-verbatim fixture)
63+
- `3ff7043` — gemini-code-assist review fixes: missing
64+
`opencode_session_version` in metadata (broke incremental
65+
`is_current`), `_skip_requested` private access, `filed_at`
66+
hoisted out of chunk loop, PEP 8 import position
67+
- `9531532` — igorls review fixes: ruff F401/E402 in tests,
68+
route-hint wing/drawer-stage precedence mismatch (RFC 002 §2.5),
69+
unjustified `# noqa` cleanup
70+
- `18ab021` + `2ffe652` — CI ruff 0.4.x format passes
71+
72+
Adapter conformance via RFC 002 §7.3 declared-transformation
73+
round-trip; one drawer per exchange-pair; `source_file` shape
74+
`opencode://<absolute-db-path>#session=<sid>`; wing routes from
75+
`session.directory` basename (matching the live-capture plugin's
76+
taxonomy); incremental ingest works via `opencode_session_version`.
77+
78+
Originated from JakobSachs's spadework on upstream PR #23 (DB
79+
schema reverse engineering, session/message/part traversal,
80+
tool-input/tool-output stripping). PR #23 is still OPEN but
81+
CONFLICTING and unresponsive since 2026-04-08; #1484 carries
82+
`Co-authored-by: JakobSachs` per coordination on #23.
83+
84+
*Tests:* 28 OpenCode adapter tests pass; full suite 2133 passed / 33 skipped (zero regressions on fork main + 60-commit upstream sync baseline)
85+
*Upstream:* [PR #1484](https://github.com/MemPalace/mempalace/pull/1484) (OPEN)
86+
*Files:* `mempalace/sources/opencode.py`, `mempalace/sources/transforms.py`, `mempalace/sources/context.py`, `pyproject.toml`, `tests/test_sources_opencode.py`, `tests/fixtures/opencode/sample_session_2026_05_12/README.md`, `tests/fixtures/opencode/sample_session_2026_05_12/build_fixture.py`, `tests/test_corpus_origin_integration.py`
87+
88+
2189
## [2026-05-11]
2290

2391

@@ -1008,17 +1076,10 @@ config-file readback. Suite total 1562 passed.
10081076
and ``os.path.getmtime()`` to file-level (2 syscalls per file instead
10091077
of 2N). Reported 10–30× mining speedup upstream. Fork-side resolution
10101078
preserved fork's existing ``DRAWER_UPSERT_BATCH_SIZE=1000``; aliased
1011-
upstream's ``CHROMA_BATCH_LIMIT`` to it.
1012-
1013-
**2026-05-16 update:** upstream #1085 was closed 2026-05-05 by
1014-
@midweste, superseded by [#1185](https://github.com/MemPalace/mempalace/pull/1185)
1015-
("perf(mining): batch per-chunk upserts + optional GPU acceleration")
1016-
which **merged to develop on 2026-04-24** (wider scope: same batch-
1017-
insert path plus optional GPU acceleration). Our cherry-pick is now
1018-
functionally redundant with develop; safe to drop on the next
1019-
upstream sync. See techempower-org/mempalace#36.
1079+
upstream's ``CHROMA_BATCH_LIMIT`` to it. Becomes a no-op when #1085
1080+
merges to develop and we next sync.
10201081

1021-
*Upstream:* [PR #1085](https://github.com/MemPalace/mempalace/pull/1085) (CLOSED) — superseded by [PR #1185](https://github.com/MemPalace/mempalace/pull/1185) (MERGED)
1082+
*Upstream:* [PR #1085](https://github.com/MemPalace/mempalace/pull/1085) (OPEN)
10221083
*Files:* `mempalace/miner.py`
10231084

10241085

docs/fork-changes.yaml

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,88 @@
2424

2525
entries:
2626

27+
- id: opencode-mcp-config-cherry-pick-1567
28+
date: 2026-05-21
29+
bucket: Added
30+
commit: ba16b82
31+
area: CLI
32+
summary: ".opencode/opencode.json — repo-root MCP config so opencode picks up mempalace automatically"
33+
body: |
34+
Cherry-pick of upstream PR #1567 (Dxrk777). Adds
35+
`.opencode/opencode.json` so that running `opencode` in the
36+
mempalace repo root automatically wires `mempalace` as a local
37+
MCP server — useful for contributors who use OpenCode for
38+
development on the project itself.
39+
40+
Two-commit cherry-pick:
41+
42+
- `013ac63` — initial config with `command: ["mempalace-mcp"]`
43+
- `ba16b82` — gemini-code-assist review feedback: switch to
44+
`command: ["python", "-m", "mempalace.mcp_server"]` for
45+
portability across install methods (pip vs uv vs dev install)
46+
47+
This is the **dev/contributor surface** — it lives in the repo
48+
and only matters when running OpenCode against the repo root.
49+
Per-user setups should use `~/.config/opencode/opencode.jsonc`
50+
with the daemon-aware wrapper (see `docs/integrations/opencode.md`).
51+
pr: 1567
52+
pr_state: OPEN
53+
files:
54+
- .opencode/opencode.json
55+
56+
- id: opencode-source-adapter-cherry-pick-1484
57+
date: 2026-05-21
58+
bucket: Added
59+
commit: 2ffe652
60+
area: CLI
61+
summary: "OpenCodeSourceAdapter (RFC 002) — retrospective ingest of OpenCode SQLite sessions"
62+
body: |
63+
Cherry-pick of upstream PR #1484. Adds
64+
`mempalace/sources/opencode.py` — an RFC 002 `BaseSourceAdapter`
65+
that ingests OpenCode AI-coding-CLI session transcripts from
66+
`~/.local/share/opencode/opencode.db` into the palace, formatted
67+
to match `convo_miner`'s exchange-pair drawer shape.
68+
69+
Five-commit cherry-pick:
70+
71+
- `2c368c6` — initial adapter (482-line `opencode.py`, 6
72+
opencode-namespaced reference transformations in
73+
`transforms.py`, entry-point registration, 28 tests, sample
74+
SQLite-schema-verbatim fixture)
75+
- `3ff7043` — gemini-code-assist review fixes: missing
76+
`opencode_session_version` in metadata (broke incremental
77+
`is_current`), `_skip_requested` private access, `filed_at`
78+
hoisted out of chunk loop, PEP 8 import position
79+
- `9531532` — igorls review fixes: ruff F401/E402 in tests,
80+
route-hint wing/drawer-stage precedence mismatch (RFC 002 §2.5),
81+
unjustified `# noqa` cleanup
82+
- `18ab021` + `2ffe652` — CI ruff 0.4.x format passes
83+
84+
Adapter conformance via RFC 002 §7.3 declared-transformation
85+
round-trip; one drawer per exchange-pair; `source_file` shape
86+
`opencode://<absolute-db-path>#session=<sid>`; wing routes from
87+
`session.directory` basename (matching the live-capture plugin's
88+
taxonomy); incremental ingest works via `opencode_session_version`.
89+
90+
Originated from JakobSachs's spadework on upstream PR #23 (DB
91+
schema reverse engineering, session/message/part traversal,
92+
tool-input/tool-output stripping). PR #23 is still OPEN but
93+
CONFLICTING and unresponsive since 2026-04-08; #1484 carries
94+
`Co-authored-by: JakobSachs` per coordination on #23.
95+
tests: "28 OpenCode adapter tests pass; full suite 2133 passed / 33 skipped (zero regressions on fork main + 60-commit upstream sync baseline)"
96+
pr: 1484
97+
pr_state: OPEN
98+
files:
99+
- mempalace/sources/opencode.py
100+
- mempalace/sources/transforms.py
101+
- mempalace/sources/context.py
102+
- pyproject.toml
103+
- tests/test_sources_opencode.py
104+
- tests/fixtures/opencode/sample_session_2026_05_12/README.md
105+
- tests/fixtures/opencode/sample_session_2026_05_12/build_fixture.py
106+
- tests/test_corpus_origin_integration.py
107+
108+
27109
- id: convo-miner-bulk-prefetch-already-mined
28110
date: 2026-05-11
29111
bucket: Performance

docs/integrations/opencode.md

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
# OpenCode + MemPalace integration (fork-routed via palace-daemon)
2+
3+
Two-direction integration between [OpenCode](https://opencode.ai) and a MemPalace running behind palace-daemon:
4+
5+
| Direction | Mechanism | What you get |
6+
|---|---|---|
7+
| **Read** (agent → palace) | MCP server entry in `~/.config/opencode/opencode.jsonc` pointing at the daemon-aware stdio wrapper | OpenCode agents can call `mempalace_search`, `mempalace_kg_query`, `mempalace_diary_read`, etc. |
8+
| **Push** (live capture, conversation → palace) | [`opencode-plugin-mempalace`](https://www.npmjs.com/package/opencode-plugin-mempalace) (option-K) installed via npm + a one-line patch for daemon-routed setups | Every N messages (default 15), pre-compaction, session-idle, and SIGINT/SIGTERM all flush to the palace |
9+
| **Pull** (retrospective backfill, OpenCode SQLite → palace) | This fork's `OpenCodeSourceAdapter` (cherry-picked from upstream PR #1484) | One-shot ingest of historical OpenCode sessions from `~/.local/share/opencode/opencode.db` |
10+
11+
Together these match the same shape as MemPalace's Claude Code stop-hook pattern: live capture during use, retrospective fill-in when needed, and read-side MCP for agent recall.
12+
13+
## Why fork-ahead
14+
15+
This fork carries the integration surface ahead of upstream because the canonical merge points are still open:
16+
17+
| Upstream PR | What | Status (last checked 2026-05-21) |
18+
|---|---|---|
19+
| [#1484](https://github.com/MemPalace/mempalace/pull/1484) | `OpenCodeSourceAdapter` (RFC 002) | OPEN — CI green except a transient test-windows runner failure |
20+
| [#1567](https://github.com/MemPalace/mempalace/pull/1567) | `.opencode/opencode.json` MCP config in repo root | OPEN |
21+
| [#23](https://github.com/MemPalace/mempalace/pull/23) | Earlier OpenCode SQLite spadework (JakobSachs) | OPEN, CONFLICTING — superseded by #1484; my comment on #23 offered three coordination paths |
22+
| [#297](https://github.com/MemPalace/mempalace/pull/297) | Milofax's auto-plugin | OPEN — codebase-mining + protocol injection design; not what this fork uses |
23+
| [#1524](https://github.com/MemPalace/mempalace/pull/1524) | geco's npm-plugin integration guide | OPEN — uses opinionated 5-wing taxonomy that doesn't fit project-keyed palaces |
24+
25+
The cherry-picks land #1484 + #1567 onto this fork's `main` so the fork ships with OpenCode support immediately. When upstream merges happen, the cherry-picked commits become no-ops and the fork-changes.yaml entries can be retired.
26+
27+
## Setup recipe
28+
29+
### 1. Install MemPalace CLI
30+
31+
```bash
32+
pipx install "mempalace>=3.3.5"
33+
```
34+
35+
`mempalace` and `mempalace-mcp` end up on PATH. The CLI auto-routes through palace-daemon when `PALACE_DAEMON_URL` is in the env.
36+
37+
### 2. Daemon env file
38+
39+
Put the daemon URL + API key in `~/.config/palace-daemon/env` (mode 600):
40+
41+
```
42+
PALACE_API_KEY=<your-daemon-api-key>
43+
PALACE_DAEMON_URL=http://your-daemon-host:8085
44+
```
45+
46+
### 3. MCP wrapper
47+
48+
The mempalace-mcp stdio bridge needs `PALACE_API_KEY` in its environment, but MCP clients (OpenCode, Claude Code) spawn server subprocesses without inheriting shell rc. The wrapper at `palace-daemon/clients/mempalace-mcp-wrapper.sh` (see [palace-daemon PR #26](https://github.com/techempower-org/palace-daemon/pull/26)) sources the env file before exec'ing the bridge:
49+
50+
```jsonc
51+
{
52+
"$schema": "https://opencode.ai/config.json",
53+
"mcp": {
54+
"mempalace": {
55+
"type": "local",
56+
"command": ["/home/<user>/Projects/palace-daemon/clients/mempalace-mcp-wrapper.sh"],
57+
"enabled": true
58+
}
59+
}
60+
}
61+
```
62+
63+
This goes in `~/.config/opencode/opencode.jsonc`.
64+
65+
### 4. Live-capture plugin
66+
67+
```bash
68+
npm install -g opencode-plugin-mempalace
69+
```
70+
71+
Add to the same `opencode.jsonc`:
72+
73+
```jsonc
74+
{
75+
"plugin": ["opencode-plugin-mempalace"]
76+
}
77+
```
78+
79+
The plugin uses project-basename wings (`wing_<sanitized-dirname>`), default 15-message threshold, session.idle flush, SIGINT/SIGTERM rescue, pre-compaction injection. Closest match to MemPalace's Claude Code stop-hook semantics.
80+
81+
### Daemon-routing patch (option-K plugin v1.2.1)
82+
83+
`opencode-plugin-mempalace` v1.2.1 has a known issue ([upstream #1](https://github.com/option-K/opencode-plugin-mempalace/issues/1)) where `isInitialized()` always returns false when running daemon-routed because the function passes `--palace <local-dir>/.mempalace/palace` to `mempalace status`, forcing a local lookup that bypasses `PALACE_DAEMON_URL`.
84+
85+
Effect without patch: harmless (the plugin re-runs `mempalace init --yes <dir>` on every OpenCode start; init is idempotent against the daemon).
86+
87+
Effect with patch: cleaner; init+wakeup short-circuit when daemon-routed mode is detected.
88+
89+
The patch detects daemon-routed mode via `$PALACE_DAEMON_URL` or `~/.config/palace-daemon/env` and skips the `--palace` argument. See `examples/opencode/option-k-plugin-daemon-routing.patch` for a re-applicable form. Apply with:
90+
91+
```bash
92+
patch -d ~/.npm-global/lib/node_modules/opencode-plugin-mempalace/dist \
93+
< $REPO/examples/opencode/option-k-plugin-daemon-routing.patch
94+
```
95+
96+
(This needs reapplying after `npm update opencode-plugin-mempalace`.)
97+
98+
### 5. Retrospective backfill
99+
100+
After install, ingest historical OpenCode sessions in one shot:
101+
102+
```bash
103+
mempalace mine --source opencode
104+
```
105+
106+
The `OpenCodeSourceAdapter` reads `~/.local/share/opencode/opencode.db` (or the macOS `~/Library/Application Support/opencode/...` path), yields one drawer per session-exchange-pair, and the daemon-routed `mempalace mine` writes them through the daemon. Wing routes from `session.directory` basename, matching the live-capture plugin's taxonomy.
107+
108+
## What gets stored
109+
110+
A typical OpenCode turn produces a drawer like:
111+
112+
| Field | Value |
113+
|---|---|
114+
| `wing` | `wing_<project-basename>` (matches both adapter and live-capture plugin) |
115+
| `room` | content-detected via `convo_miner.detect_convo_room` (`technical` / `decisions` / `problems` / etc.) |
116+
| `source_file` | `opencode://<absolute-db-path>#session=<sid>` (adapter) or session export path (plugin) |
117+
| `content` | verbatim user + assistant text, no summarization |
118+
| `extract_mode` | `exchange` |
119+
| Adapter-specific metadata | `session_id`, `session_title`, `project_dir`, `session_created_at`, `message_count`, `opencode_session_version`, `opencode_db_path` |
120+
121+
## Read-side recall
122+
123+
OpenCode agents can call any of the 30 MCP tools the daemon exposes:
124+
125+
- `mempalace_search` — semantic search across all drawers
126+
- `mempalace_list_wings` / `mempalace_list_rooms` / `mempalace_get_taxonomy` — palace navigation
127+
- `mempalace_kg_query` / `mempalace_kg_timeline` — knowledge graph
128+
- `mempalace_diary_read` / `mempalace_diary_write` — agent diaries
129+
- `mempalace_traverse` / `mempalace_find_tunnels` — cross-wing connections
130+
131+
The daemon serializes all writes through a single chokepoint, so multiple OpenCode windows + Claude Code + the live-capture plugin all coexist without HNSW corruption.
132+
133+
## Verifying the integration
134+
135+
After setup, in any OpenCode session:
136+
137+
```
138+
> Use mempalace_status to confirm we're connected.
139+
```
140+
141+
Expected: agent calls the tool and reports drawer count + wing list. If you see "no palace found" or auth errors, check that the wrapper script can read `~/.config/palace-daemon/env`.
142+
143+
To confirm live-capture is firing, watch `mempalace status` over a few minutes of OpenCode use — drawer count should increment.
144+
145+
## Coordination notes
146+
147+
- Upstream PR #1484 carries co-authored credit to JakobSachs for the original DB-schema spadework on PR #23.
148+
- This fork-ahead carries 5 commits from #1484 + 2 commits from #1567 (see `docs/fork-changes.yaml` `opencode-adapter-cherry-pick` and `opencode-mcp-config-cherry-pick` entries).
149+
- option-K's plugin v1.2.1 issue #1 (daemon-routing patch) is filed but unresolved; the patch in `examples/opencode/` is our local fix until upstream lands a real one.
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
{
2+
"$schema": "https://opencode.ai/config.json",
3+
4+
// Provider/model — set to whatever you actually use; the example uses
5+
// bedrock as that's how this fork's author runs it.
6+
"provider": {
7+
"amazon-bedrock": {
8+
"options": {
9+
"region": "us-west-1"
10+
}
11+
}
12+
},
13+
"model": "amazon-bedrock/us.anthropic.claude-opus-4-7",
14+
15+
// === MemPalace via palace-daemon ===
16+
// Read-side MCP — agents can call mempalace_search / mempalace_kg_query / etc.
17+
// The wrapper sources ~/.config/palace-daemon/env (mode 600) before exec'ing
18+
// the daemon's stdio bridge, so PALACE_API_KEY never lands in this config.
19+
"mcp": {
20+
"mempalace": {
21+
"type": "local",
22+
"command": ["/home/<user>/Projects/palace-daemon/clients/mempalace-mcp-wrapper.sh"],
23+
"enabled": true
24+
}
25+
},
26+
27+
// Push-side live capture — option-K's npm plugin. After install:
28+
// npm install -g opencode-plugin-mempalace
29+
// Optional: pass { "threshold": N } as the second tuple element to override
30+
// the default 15-message mining cadence.
31+
"plugin": ["opencode-plugin-mempalace"]
32+
}

0 commit comments

Comments
 (0)