opencode-memoir 1.1.9 → 2.0.1

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 CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  OpenCode plugin for [Memoir](https://github.com/zhangfengcdt/memoir): git-versioned, taxonomy-structured memory for coding agents.
4
4
 
5
- The OpenCode counterpart to the Claude Code and Codex Memoir plugins. Derives a per-project store under `~/.memoir/<path-slug>`, resolves the `memoir` CLI with `uvx` fallback, and exposes commands/tools for status, recall, remember, and UI launch.
5
+ Dynamically loads the `memoir-mcp` MCP server via `uvx` — no manual CLI installation needed.
6
6
 
7
7
  ## Install
8
8
 
@@ -18,25 +18,14 @@ Add the package name to your OpenCode config (`~/.config/opencode/opencode.jsonc
18
18
 
19
19
  OpenCode downloads and resolves the package from npm automatically; no manual install or `npm:` prefix needed. To pin a version, append it: `"opencode-memoir@1.0.0"`.
20
20
 
21
- The `memoir` CLI is resolved automatically with no separate install — see [Memoir CLI resolution](#memoir-cli-resolution).
22
-
23
21
  ## Quick start
24
22
 
25
23
  1. Install the plugin (see above)
26
- 2. Run `/memoir:status` in any project to verify the store was created
27
- 3. Start saving memories with `/memoir:remember` or let the agent auto-capture
24
+ 2. Start coding — the agent can use `memoir_recall`, `memoir_remember`, `memoir_get` MCP tools automatically
28
25
 
29
26
  ## Store configuration
30
27
 
31
- The plugin uses the same environment variable as the Claude Code plugin:
32
-
33
- | Source | Description |
34
- |---|---|
35
- | plugin option `store` | Highest-priority override when the plugin is loaded from `plugin[]` |
36
- | `MEMOIR_STORE` | Portable global/project override |
37
- | auto-derived path | `~/.memoir/<slug>`, where slug = git root (or resolved cwd) with `/` and `.` replaced by `-`; all worktrees share one store |
38
-
39
- Example when loading through `plugin[]`:
28
+ The plugin delegates store path resolution to `memoir-mcp`. Override via `MEMOIR_STORE` env var or `store` plugin option:
40
29
 
41
30
  ```jsonc
42
31
  {
@@ -48,70 +37,35 @@ Example when loading through `plugin[]`:
48
37
 
49
38
  ## Environment variables
50
39
 
51
- All variables are optional. Capture and sanitization are on by default.
40
+ All optional:
52
41
 
53
42
  | Variable | Effect |
54
43
  |---|---|
55
- | `MEMOIR_STORE` | Override the derived store path (see above). |
56
- | `MEMOIR_DEBUG=1` | Emit diagnostic logs to stderr (prefixed `[memoir]`). All internal errors are logged here instead of failing silently. Off by default. |
57
- | `MEMOIR_NO_CAPTURE=1` | Disable all capture — no metrics, no code-change tracking, no branch auto-match flush. Superset switch. |
58
- | `MEMOIR_NO_METRICS=1` | Disable per-tool metrics only (`metrics.turn.<branch>`). Code-change tracking still runs. |
59
- | `MEMOIR_NO_CODE_SUMMARY=1` | Disable code-change tracking only (`metrics.code.<branch>`). Metrics still run. |
60
- | `MEMOIR_SANITIZE_SECRETS=0` | Disable the secret-pattern guard on `memoir_remember`. Sanitization is **on** by default; set to `0` only if the guard produces false positives you understand. |
61
-
62
- Capture guards are checked at the collection point (`tool.execute.after`) and the flush point (`chat.message`), so setting them mid-session takes effect on the next turn.
63
-
64
- ## Commands
65
-
66
- | Command | Description |
67
- |---|---|
68
- | `/memoir:status` | Show status for the current project store, including project git branch metadata |
69
- | `/memoir:ui` | Launch or reopen the Memoir web UI |
70
- | `/memoir:remember <memory>` | Ask the agent to save an explicit durable memory with a semantic path |
71
- | `/memoir:recall <topic>` | Ask the agent to list and use relevant stored memories |
72
- | `/memoir:onboard` | Populate or refresh the project onboarding snapshot |
73
- | `/memoir:unmerged` | List memoir branches that have diverged from `main` |
74
-
75
- ## Tools
76
-
77
- | Tool | Description |
78
- |---|---|
79
- | `memoir_status` | Run the status helper |
80
- | `memoir_remember` | Save explicit content to one or more semantic paths; refuses secret-like content |
81
- | `memoir_recall` | List memory keys via `summarize` for relevance selection |
82
- | `memoir_get` | Fetch selected exact keys after `memoir_recall` |
44
+ | `MEMOIR_STORE` | Override store path (passed to memoir-mcp as `--store`) |
45
+ | `MEMOIR_DEBUG=1` | Emit diagnostic logs to stderr (prefixed `[memoir]`) |
46
+ | `MEMOIR_AUTO_SAVE=1` | Auto-save session marker on dispose (default: disabled) |
47
+ | `MEMOIR_REMINDER_INTERVAL=N` | Periodic save/recall reminder every N messages (default: 5, 0 to disable) |
83
48
 
84
49
  ## Hooks
85
50
 
86
- The plugin registers eight OpenCode hooks, mirroring the Claude Code plugin's lifecycle:
87
-
88
51
  | Hook | Purpose |
89
52
  |---|---|
90
- | `config` | Registers slash commands |
91
- | `command.execute.before` | Handles `/memoir:status`, `/memoir:ui`, `/memoir:unmerged` |
92
- | `shell.env` | Injects `MEMOIR_STORE` into shell env |
93
- | `event` | On `session.created`, fetches the taxonomy overview in the background |
94
- | `tool.execute.after` | Accumulates per-tool metrics + file edits for code change audit |
95
- | `chat.message` | Auto-matches memoir branch to git branch, flushes capture, runs recall gate |
96
- | `experimental.chat.system.transform` | Injects taxonomy context + recall instruction |
97
- | `dispose` | Flushes remaining data, prunes session state |
98
-
99
- See the [Memoir docs](https://zhangfengcdt.github.io/memoir/) for detailed hook behaviour.
53
+ | `config` | Registers `memoir-mcp` as a dynamic MCP server; adds `/memoir:onboard` slash command |
54
+ | `shell.env` | Injects `MEMOIR_STORE` into shell environment |
55
+ | `chat.message` | Increments message counter; auto-matches memoir branch to current git branch |
56
+ | `experimental.chat.system.transform` | Startup hint (once/session); periodic save/recall reminder |
57
+ | `dispose` | Optionally saves session marker; clears all pending state |
100
58
 
101
- ## Memoir CLI resolution
59
+ ## How it works
102
60
 
103
- 1. `memoir` on `PATH`
104
- 2. `uvx --from memoir-ai==<pin> memoir` — ephemeral, pinned
105
- 3. `uv tool run --from memoir-ai==<pin> memoir` — pinned fallback
106
-
107
- Every command passes an explicit `-s <store>` to keep the project git and Memoir store separate.
61
+ Instead of wrapping the `memoir` CLI and re-implementing tools in TypeScript, this plugin registers `memoir-mcp` as a dynamic MCP server. OpenCode starts the server via `uvx --from memoir-ai[mcp] memoir-mcp`, and all memoir tools (`memoir_recall`, `memoir_remember`, `memoir_get`, etc.) are available natively to the LLM.
108
62
 
109
63
  ## Development
110
64
 
111
65
  ### Prerequisites
112
66
 
113
67
  - Node.js >= 20
114
- - `memoir` CLI somewhere accessible, OR `uv` installed (the plugin falls back to `uvx`)
68
+ - `uv` installed (for `uvx` to run memoir-mcp)
115
69
 
116
70
  ### Setup
117
71
 
@@ -125,28 +79,16 @@ npm test # run the test suite
125
79
 
126
80
  | File | Responsibility |
127
81
  |---|---|
128
- | `src/store.ts` | CLI resolution + runner, git/worktree helpers, store-path derivation, branch management |
129
- | `src/capture.ts` | Edit tracking, per-tool metrics, `flushCapture` (read-merge-write of `metrics.*`) |
130
- | `src/recall-gate.ts` | Secret pattern + sanitization toggle, recall-gate trigger logic |
131
- | `src/index.ts` | Plugin wiring — tool definitions, hooks, command registration |
132
- | `src/debug.ts` | Shared debug logger |
133
-
134
- ### Tests
135
-
136
- The suite runs with `tsx --test` (handles `.js` → `.ts` resolution under NodeNext).
137
-
138
- To debug hooks locally, run OpenCode with `MEMOIR_DEBUG=1` and watch stderr for `[memoir]` lines.
82
+ | `src/index.ts` | Plugin entry: MCP registration + all hooks + dispose |
83
+ | `src/store.ts` | Store path derivation, branch auto-match, `callMemoir` CLI helper |
84
+ | `src/memory-saver.ts` | Per-session message counter for periodic reminders |
85
+ | `src/debug.ts` | Conditional stderr logger (`MEMOIR_DEBUG=1`) |
139
86
 
140
87
  ## Publishing
141
88
 
142
89
  Releases are fully automated — no manual `npm version` or `npm publish`.
143
90
 
144
- 1. Land changes on `main` via PR using [Conventional Commits](https://www.conventionalcommits.org/) (`feat:`, `fix:`, `chore:`, etc.). The commit type determines the version bump.
145
- 2. On push to `main`, `.github/workflows/semantic.yaml` runs [semantic-release](https://semantic-release.gitbook.io/): it computes the next version, updates the changelog, commits `chore(release): x.y.z`, and pushes a matching `vx.y.z` git tag.
146
- 3. The new tag triggers `.github/workflows/publish-npm.yaml`, which builds and runs `npm publish --provenance` to npm via [Trusted Publishing](https://docs.npmjs.com/trusted-publishers) (OIDC — no tokens stored).
147
-
148
- Published files are limited to `dist/` and `README.md` (see `files` in `package.json`); the `prepublishOnly` script runs `build` + `test` as a safety net.
149
-
150
- ## License
91
+ 1. Land changes on `main` via PR using [Conventional Commits](https://www.conventionalcommits.org/) (`feat:`, `fix:`, etc.)
92
+ 2. On push to `main`, `.github/workflows/semantic.yaml` runs [semantic-release](https://semantic-release.gitbook.io/)
93
+ 3. The new tag triggers `.github/workflows/publish-npm.yaml`, which builds and runs `npm publish --provenance`
151
94
 
152
- Apache-2.0
package/dist/index.d.ts CHANGED
@@ -1,10 +1,4 @@
1
1
  import type { PluginModule } from "@opencode-ai/plugin";
2
- /**
3
- * V1 plugin module format: OpenCode's loader recognizes `{ id, server }` and
4
- * ignores any other module exports. The legacy format (default-exported
5
- * function) made the loader treat EVERY export as a plugin and fail on
6
- * non-function exports ("Plugin export is not a function").
7
- */
8
2
  declare const plugin: PluginModule;
9
3
  export default plugin;
10
4
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAU,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAwGhE;;;;;GAKG;AACH,QAAA,MAAM,MAAM,EAAE,YAGb,CAAC;AAEF,eAAe,MAAM,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAkB,YAAY,EAAE,MAAM,qBAAqB,CAAC;AA4IxE,QAAA,MAAM,MAAM,EAAE,YAGb,CAAC;AAEF,eAAe,MAAM,CAAC"}