@memfork/cli 0.1.18 → 0.1.20

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.
@@ -21,8 +21,8 @@ import path from "node:path";
21
21
  import { fileURLToPath } from "node:url";
22
22
  import { readCredentials, readProjectConfig, MEMWAL_CONSTANTS } from "../config.js";
23
23
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
24
- // dist/commands/install.js → packages/clipackages → repo root → plugins/
25
- const PLUGIN_ROOT = path.resolve(__dirname, "..", "..", "..", "..", "plugins");
24
+ // dist/commands/install.js → dist/ → package root → plugins/
25
+ const PLUGIN_ROOT = path.resolve(__dirname, "..", "..", "plugins");
26
26
  function ok(s) { return chalk.green("✓") + " " + s; }
27
27
  function warn(s) { return chalk.yellow("⚠") + " " + s; }
28
28
  function tip(s) { return chalk.cyan("→") + " " + s; }
@@ -49,7 +49,7 @@ async function handleApiConfig(res) {
49
49
  const stored = treeId ? creds.trees[treeId] : undefined;
50
50
  json(res, {
51
51
  treeId,
52
- packageId: project?.packageId ?? "0x7df9719d799386d34d657c49ae8cd6f5f03b39036f7c428b556095e42afd852f",
52
+ packageId: project?.packageId ?? "0xc13cc014fb8084b3468f6e5ffdc272e64ef35b7a912332eba7a0d44dd66b3121",
53
53
  network,
54
54
  rpcUrl: project?.rpcUrl ?? null,
55
55
  hasMemwal: !!(stored?.memwalKey && stored?.memwalAccountId),
package/dist/config.d.ts CHANGED
@@ -25,22 +25,22 @@
25
25
  export declare const MEMWAL_CONSTANTS: {
26
26
  readonly testnet: {
27
27
  readonly packageId: "0xcf6ad755a1cdff7217865c796778fabe5aa399cb0cf2eba986f4b582047229c6";
28
- readonly memforksPackageId: "0xc9f0a4964f810c794479bc5b66347998969d2c59d6797c313b8a96d2bdd6a914";
28
+ readonly memforksPackageId: "0x185e765a4979fb9d9089374f822485c88b9d0b2f91f9b1313a73043d5ef2357f";
29
29
  readonly registryId: "0xe80f2feec1c139616a86c9f71210152e2a7ca552b20841f2e192f99f75864437";
30
- readonly relayer: "https://relayer.staging.memwal.ai";
30
+ readonly relayer: "https://relayer-staging.memory.walrus.xyz";
31
31
  };
32
32
  readonly mainnet: {
33
33
  readonly packageId: "0xcee7a6fd8de52ce645c38332bde23d4a30fd9426bc4681409733dd50958a24c6";
34
- readonly memforksPackageId: "0x7df9719d799386d34d657c49ae8cd6f5f03b39036f7c428b556095e42afd852f";
34
+ readonly memforksPackageId: "0xc13cc014fb8084b3468f6e5ffdc272e64ef35b7a912332eba7a0d44dd66b3121";
35
35
  readonly registryId: "0x0da982cefa26864ae834a8a0504b904233d49e20fcc17c373c8bed99c75a7edd";
36
- readonly relayer: "https://relayer.memwal.ai";
36
+ readonly relayer: "https://relayer.memory.walrus.xyz";
37
37
  };
38
38
  };
39
39
  export interface ProjectConfig {
40
40
  /** Sui MemoryTree object ID. */
41
41
  treeId?: string;
42
42
  /** Sui network. Default: "mainnet". */
43
- network?: "testnet" | "mainnet" | "devnet" | "localnet";
43
+ network?: 'testnet' | 'mainnet' | 'devnet' | 'localnet';
44
44
  /** Default branch name. Default: "main". */
45
45
  defaultBranch?: string;
46
46
  /** Override Sui RPC URL. */
@@ -70,7 +70,7 @@ export interface ResolvedConfig {
70
70
  memwalAccountId: string;
71
71
  memwalKey: string;
72
72
  memwalRelayer: string;
73
- network: "testnet" | "mainnet" | "devnet" | "localnet";
73
+ network: 'testnet' | 'mainnet' | 'devnet' | 'localnet';
74
74
  defaultBranch: string;
75
75
  rpcUrl?: string;
76
76
  packageId?: string;
package/dist/config.js CHANGED
@@ -22,32 +22,32 @@
22
22
  *
23
23
  * Plugins and hooks call the CLI binary and never read credentials themselves.
24
24
  */
25
- import fs from "node:fs";
26
- import path from "node:path";
27
- import os from "node:os";
25
+ import fs from 'node:fs';
26
+ import path from 'node:path';
27
+ import os from 'node:os';
28
28
  // ─── Public network constants ─────────────────────────────────────────────────
29
29
  // Sources: https://docs.memwal.ai/contract/overview
30
30
  export const MEMWAL_CONSTANTS = {
31
31
  testnet: {
32
- packageId: "0xcf6ad755a1cdff7217865c796778fabe5aa399cb0cf2eba986f4b582047229c6",
33
- memforksPackageId: "0xc9f0a4964f810c794479bc5b66347998969d2c59d6797c313b8a96d2bdd6a914",
34
- registryId: "0xe80f2feec1c139616a86c9f71210152e2a7ca552b20841f2e192f99f75864437",
35
- relayer: "https://relayer.staging.memwal.ai",
32
+ packageId: '0xcf6ad755a1cdff7217865c796778fabe5aa399cb0cf2eba986f4b582047229c6',
33
+ memforksPackageId: '0x185e765a4979fb9d9089374f822485c88b9d0b2f91f9b1313a73043d5ef2357f',
34
+ registryId: '0xe80f2feec1c139616a86c9f71210152e2a7ca552b20841f2e192f99f75864437',
35
+ relayer: 'https://relayer-staging.memory.walrus.xyz',
36
36
  },
37
37
  mainnet: {
38
- packageId: "0xcee7a6fd8de52ce645c38332bde23d4a30fd9426bc4681409733dd50958a24c6",
39
- memforksPackageId: "0x7df9719d799386d34d657c49ae8cd6f5f03b39036f7c428b556095e42afd852f",
40
- registryId: "0x0da982cefa26864ae834a8a0504b904233d49e20fcc17c373c8bed99c75a7edd",
41
- relayer: "https://relayer.memwal.ai",
38
+ packageId: '0xcee7a6fd8de52ce645c38332bde23d4a30fd9426bc4681409733dd50958a24c6',
39
+ memforksPackageId: '0xc13cc014fb8084b3468f6e5ffdc272e64ef35b7a912332eba7a0d44dd66b3121',
40
+ registryId: '0x0da982cefa26864ae834a8a0504b904233d49e20fcc17c373c8bed99c75a7edd',
41
+ relayer: 'https://relayer.memory.walrus.xyz',
42
42
  },
43
43
  };
44
44
  // ─── Paths ────────────────────────────────────────────────────────────────────
45
45
  function defaultRelayer(network) {
46
- return MEMWAL_CONSTANTS[network]?.relayer
47
- ?? MEMWAL_CONSTANTS.mainnet.relayer;
46
+ return (MEMWAL_CONSTANTS[network]?.relayer ??
47
+ MEMWAL_CONSTANTS.mainnet.relayer);
48
48
  }
49
49
  export function projectConfigPath(cwd = process.cwd()) {
50
- return path.join(cwd, ".memfork", "config.json");
50
+ return path.join(cwd, '.memfork', 'config.json');
51
51
  }
52
52
  /**
53
53
  * Walk up the directory tree from `cwd` looking for a `.memfork/config.json`,
@@ -56,7 +56,7 @@ export function projectConfigPath(cwd = process.cwd()) {
56
56
  function findProjectConfigPath(cwd = process.cwd()) {
57
57
  let dir = cwd;
58
58
  while (true) {
59
- const candidate = path.join(dir, ".memfork", "config.json");
59
+ const candidate = path.join(dir, '.memfork', 'config.json');
60
60
  if (fs.existsSync(candidate))
61
61
  return candidate;
62
62
  const parent = path.dirname(dir);
@@ -66,7 +66,7 @@ function findProjectConfigPath(cwd = process.cwd()) {
66
66
  }
67
67
  }
68
68
  export function credentialsPath() {
69
- return path.join(os.homedir(), ".memfork", "credentials.json");
69
+ return path.join(os.homedir(), '.memfork', 'credentials.json');
70
70
  }
71
71
  // ─── Read helpers ─────────────────────────────────────────────────────────────
72
72
  export function readProjectConfig(cwd = process.cwd()) {
@@ -74,7 +74,7 @@ export function readProjectConfig(cwd = process.cwd()) {
74
74
  if (!p)
75
75
  return null;
76
76
  try {
77
- return JSON.parse(fs.readFileSync(p, "utf8"));
77
+ return JSON.parse(fs.readFileSync(p, 'utf8'));
78
78
  }
79
79
  catch {
80
80
  return null;
@@ -85,7 +85,7 @@ export function readCredentials() {
85
85
  if (!fs.existsSync(p))
86
86
  return { trees: {} };
87
87
  try {
88
- return JSON.parse(fs.readFileSync(p, "utf8"));
88
+ return JSON.parse(fs.readFileSync(p, 'utf8'));
89
89
  }
90
90
  catch {
91
91
  return { trees: {} };
@@ -94,14 +94,14 @@ export function readCredentials() {
94
94
  // ─── Write helpers ────────────────────────────────────────────────────────────
95
95
  export function writeProjectConfig(cfg, cwd = process.cwd()) {
96
96
  const root = findGitRoot(cwd) ?? cwd;
97
- const dir = path.join(root, ".memfork");
97
+ const dir = path.join(root, '.memfork');
98
98
  fs.mkdirSync(dir, { recursive: true });
99
- fs.writeFileSync(path.join(root, ".memfork", "config.json"), JSON.stringify(cfg, null, 2) + "\n", "utf8");
99
+ fs.writeFileSync(path.join(root, '.memfork', 'config.json'), JSON.stringify(cfg, null, 2) + '\n', 'utf8');
100
100
  }
101
101
  function findGitRoot(cwd) {
102
102
  let dir = cwd;
103
103
  while (true) {
104
- if (fs.existsSync(path.join(dir, ".git")))
104
+ if (fs.existsSync(path.join(dir, '.git')))
105
105
  return dir;
106
106
  const parent = path.dirname(dir);
107
107
  if (parent === dir)
@@ -110,10 +110,10 @@ function findGitRoot(cwd) {
110
110
  }
111
111
  }
112
112
  export function writeCredentials(creds) {
113
- const dir = path.join(os.homedir(), ".memfork");
113
+ const dir = path.join(os.homedir(), '.memfork');
114
114
  fs.mkdirSync(dir, { recursive: true });
115
115
  const p = credentialsPath();
116
- fs.writeFileSync(p, JSON.stringify(creds, null, 2) + "\n", "utf8");
116
+ fs.writeFileSync(p, JSON.stringify(creds, null, 2) + '\n', 'utf8');
117
117
  // 600: owner read+write only — no other users can read private keys.
118
118
  fs.chmodSync(p, 0o600);
119
119
  }
@@ -133,7 +133,7 @@ export function setDefaultTree(treeId) {
133
133
  export class ConfigError extends Error {
134
134
  constructor(message) {
135
135
  super(message);
136
- this.name = "ConfigError";
136
+ this.name = 'ConfigError';
137
137
  }
138
138
  }
139
139
  /**
@@ -145,21 +145,15 @@ export function resolveConfig(opts = {}) {
145
145
  const creds = readCredentials();
146
146
  const env = process.env;
147
147
  // ── Resolve treeId ──────────────────────────────────────────────────────────
148
- const treeId = env["MEMFORK_TREE_ID"] ??
149
- opts.treeId ??
150
- project?.treeId ??
151
- creds.default;
148
+ const treeId = env['MEMFORK_TREE_ID'] ?? opts.treeId ?? project?.treeId ?? creds.default;
152
149
  if (!treeId) {
153
- throw new ConfigError("No MemoryTree found. Run `memfork init` to create or link one.");
150
+ throw new ConfigError('No MemoryTree found. Run `memfork init` to create or link one.');
154
151
  }
155
152
  // ── Resolve credentials ────────────────────────────────────────────────────
156
153
  const stored = creds.trees[treeId];
157
- const privateKey = env["MEMFORK_PRIVATE_KEY"] ??
158
- stored?.privateKey;
159
- const memwalAccountId = env["MEMFORK_MEMWAL_ACCOUNT"] ??
160
- stored?.memwalAccountId;
161
- const memwalKey = env["MEMFORK_MEMWAL_KEY"] ??
162
- stored?.memwalKey;
154
+ const privateKey = env['MEMFORK_PRIVATE_KEY'] ?? stored?.privateKey;
155
+ const memwalAccountId = env['MEMFORK_MEMWAL_ACCOUNT'] ?? stored?.memwalAccountId;
156
+ const memwalKey = env['MEMFORK_MEMWAL_KEY'] ?? stored?.memwalKey;
163
157
  if (!privateKey) {
164
158
  throw new ConfigError(`No private key for tree ${treeId}. Run \`memfork init\` or set MEMFORK_PRIVATE_KEY.`);
165
159
  }
@@ -170,22 +164,23 @@ export function resolveConfig(opts = {}) {
170
164
  throw new ConfigError(`No MemWal delegate key for tree ${treeId}. Run \`memfork init\` or set MEMFORK_MEMWAL_KEY.`);
171
165
  }
172
166
  // ── Merge non-secret config ────────────────────────────────────────────────
173
- const network = (env["MEMFORK_NETWORK"] ??
167
+ const network = (env['MEMFORK_NETWORK'] ??
174
168
  project?.network ??
175
- "mainnet");
169
+ 'mainnet');
176
170
  return {
177
171
  treeId,
178
172
  privateKey,
179
173
  memwalAccountId,
180
174
  memwalKey,
181
- memwalRelayer: env["MEMFORK_RELAYER_URL"] ??
175
+ memwalRelayer: env['MEMFORK_RELAYER_URL'] ??
182
176
  stored?.memwalRelayer ??
183
177
  defaultRelayer(network),
184
178
  network,
185
- defaultBranch: project?.defaultBranch ?? "main",
186
- rpcUrl: env["MEMFORK_RPC_URL"] ?? project?.rpcUrl,
187
- packageId: env["MEMFORK_PACKAGE_ID"] ?? project?.packageId,
188
- sponsorUrl: env["MEMFORK_SPONSOR_URL"] ?? project?.["sponsorUrl"],
179
+ defaultBranch: project?.defaultBranch ?? 'main',
180
+ rpcUrl: env['MEMFORK_RPC_URL'] ?? project?.rpcUrl,
181
+ packageId: env['MEMFORK_PACKAGE_ID'] ?? project?.packageId,
182
+ sponsorUrl: env['MEMFORK_SPONSOR_URL'] ??
183
+ project?.['sponsorUrl'],
189
184
  };
190
185
  }
191
186
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@memfork/cli",
3
- "version": "0.1.18",
3
+ "version": "0.1.20",
4
4
  "description": "MemForks CLI — init, commit, recall, merge, install plugins",
5
5
  "repository": {
6
6
  "type": "git",
@@ -29,7 +29,8 @@
29
29
  "access": "public"
30
30
  },
31
31
  "files": [
32
- "dist"
32
+ "dist",
33
+ "plugins"
33
34
  ],
34
35
  "dependencies": {
35
36
  "@inquirer/prompts": "^8.5.2",
@@ -0,0 +1,44 @@
1
+ {
2
+ "name": "memforks",
3
+ "version": "0.2.0",
4
+ "description": "On-chain, branch-aware memory DAG for Codex. MemForks anchors decisions to Sui and proposes cross-branch merges — memory storage is handled by the MemWal MCP server.",
5
+ "author": {
6
+ "name": "MemForks",
7
+ "email": "team@memforks.dev"
8
+ },
9
+ "homepage": "https://github.com/memforks/memforks",
10
+ "repository": "https://github.com/memforks/memforks",
11
+ "license": "Apache-2.0",
12
+ "keywords": [
13
+ "memory",
14
+ "sui",
15
+ "blockchain",
16
+ "provenance",
17
+ "branching",
18
+ "codex",
19
+ "agent-memory",
20
+ "memwal"
21
+ ],
22
+ "skills": "./skills/",
23
+ "interface": {
24
+ "displayName": "MemForks",
25
+ "shortDescription": "On-chain, branch-aware memory DAG",
26
+ "longDescription": "MemForks gives Codex a tamper-proof, branch-synced memory DAG anchored on Sui. Memory recall and storage are handled natively by the MemWal MCP server. MemForks adds the version-control layer: immutable on-chain commits, Git branch-scoped history, and conflict-free cross-branch merges via an on-chain resolver.",
27
+ "developerName": "MemForks",
28
+ "category": "Productivity",
29
+ "capabilities": [
30
+ "Read",
31
+ "Write"
32
+ ],
33
+ "websiteURL": "https://github.com/memforks/memforks",
34
+ "privacyPolicyURL": "https://github.com/memforks/memforks",
35
+ "termsOfServiceURL": "https://github.com/memforks/memforks/blob/main/LICENSE",
36
+ "defaultPrompt": [
37
+ "Recall any relevant context for this branch",
38
+ "Show my MemForks memory status",
39
+ "Commit the decisions we made today"
40
+ ],
41
+ "brandColor": "#1f9d72",
42
+ "screenshots": []
43
+ }
44
+ }
@@ -0,0 +1,81 @@
1
+ # MemForks — Codex Plugin
2
+
3
+ On-chain, branch-aware memory DAG for Codex.
4
+
5
+ **Memory storage** is handled by the MemWal MCP server — the agent calls
6
+ `memwal_recall` and `memwal_remember` natively as tool calls.
7
+
8
+ **On-chain versioning** is handled by the `memfork` CLI — decisions get
9
+ cryptographically anchored to Sui with branch context and a full commit DAG.
10
+
11
+ ## Setup (one time, per machine)
12
+
13
+ ```bash
14
+ npm install -g @memfork/cli
15
+
16
+ # Recommended — zero copy-paste, ~30 seconds on testnet:
17
+ memfork init --quick
18
+
19
+ # Or manual if you already have a Sui key + MemWal account:
20
+ memfork init
21
+ ```
22
+
23
+ ## Install the plugin
24
+
25
+ ```bash
26
+ memfork install codex
27
+ ```
28
+
29
+ This does two things:
30
+
31
+ 1. **Writes `~/.codex/config.toml`** — adds a `[mcp_servers.memwal]` entry using
32
+ the delegate key provisioned by `memfork init`. No browser login needed.
33
+
34
+ 2. **Copies `.codex-plugin/`** — installs the plugin skills into the current project.
35
+
36
+ Then register with Codex:
37
+
38
+ ```bash
39
+ codex plugin add .codex-plugin
40
+ ```
41
+
42
+ ## Verify
43
+
44
+ ```bash
45
+ memfork doctor
46
+ ```
47
+
48
+ ## What the agent can do
49
+
50
+ | Tool / Command | What it does |
51
+ |----------------|-------------|
52
+ | `memwal_recall(query, namespace)` | Semantic search over branch memory (MCP tool) |
53
+ | `memwal_remember(text, namespace)` | Save a fact to branch memory (MCP tool) |
54
+ | `memwal_analyze(text)` | Extract and save multiple facts at once (MCP tool) |
55
+ | `memfork commit --facts …` | Anchor a decision on-chain with full provenance |
56
+ | `memfork merge <src> <dst>` | Propose a cross-branch memory merge |
57
+ | `memfork status / log / proposals` | Inspect the on-chain DAG |
58
+
59
+ Memory is namespaced by Git branch — `namespace="branch/<branch-name>"`.
60
+
61
+ ## What gets installed
62
+
63
+ ```
64
+ ~/.codex/config.toml ← MemWal MCP server entry (auto-configured)
65
+ .codex-plugin/
66
+ plugin.json ← plugin metadata
67
+ skills/
68
+ memory-recall/ ← when/how to use memwal_recall
69
+ memforks-status/ ← when/how to use memfork commit/merge/status
70
+ ```
71
+
72
+ No shell hooks. The MCP server is the transport.
73
+
74
+ ## Override for CI / headless use
75
+
76
+ ```bash
77
+ MEMFORK_TREE_ID=0x…
78
+ MEMFORK_PRIVATE_KEY=suiprivkey1…
79
+ MEMFORK_MEMWAL_ACCOUNT=0x…
80
+ MEMFORK_MEMWAL_KEY=<hex>
81
+ ```
@@ -0,0 +1,86 @@
1
+ ---
2
+ name: memforks-status
3
+ description: >-
4
+ Show MemForks on-chain status: branch DAG, open merge proposals, recent commits.
5
+ Use when the user asks about memory status, proposals, or the commit log.
6
+ Also use when committing decisions or proposing a merge.
7
+ ---
8
+
9
+ # MemForks On-Chain Operations
10
+
11
+ MemForks is the version-control layer on top of MemWal. Use the `memfork` CLI for
12
+ DAG operations — not for routine recall/remember (that's the MCP server's job).
13
+
14
+ ## Check status
15
+
16
+ ```bash
17
+ memfork status # current tree, branch, signer, head commit
18
+ memfork log --branch <branch> # recent on-chain commits
19
+ memfork proposals # open merge proposals
20
+ memfork ui # open the DAG visualizer
21
+ ```
22
+
23
+ ## Commit a decision on-chain
24
+
25
+ Use this after significant architectural decisions — not for routine facts.
26
+ (Routine facts go through `memwal_remember` via MCP.)
27
+
28
+ ```bash
29
+ memfork commit \
30
+ --branch $(git rev-parse --abbrev-ref HEAD) \
31
+ --message "decided: <one-line summary>" \
32
+ --facts "<fact 1>" "<fact 2>"
33
+ ```
34
+
35
+ ## Merge branches
36
+
37
+ When two branches need to reconcile their memory:
38
+
39
+ ```bash
40
+ # Zero-config — LastWriteWins, self-finalizes immediately
41
+ memfork merge <from-branch> <into-branch>
42
+
43
+ # Governed — jury / LLM resolver (requires MEMFORK_RESOLVER_ID env var or --resolver flag)
44
+ memfork merge <from-branch> <into-branch> --resolver <resolver-id>
45
+ ```
46
+
47
+ With no `--resolver` flag and no `MEMFORK_RESOLVER_ID` set, the merge uses
48
+ LastWriteWins and finalizes immediately — no resolver service required.
49
+
50
+ When a resolver is configured, the command waits for the on-chain resolver service
51
+ to collect attestations and finalize before returning.
52
+
53
+ ---
54
+
55
+ ## Suggesting a merge — proactive but not autonomous
56
+
57
+ You may **suggest** a merge when you notice the current branch has accumulated
58
+ durable facts not yet on `main`. Phrase it as an offer:
59
+
60
+ > "This branch has several facts that aren't on main yet — want me to merge them?
61
+ > I'll run `memfork merge <branch> main`."
62
+
63
+ **Never run `memfork merge` without the user explicitly confirming.** Merging
64
+ changes shared team memory and creates an on-chain anchor — it is a governance
65
+ act, not a routine commit.
66
+
67
+ Suggest a merge when:
68
+ - The user says "we're done with this branch" or "I'm about to open a PR"
69
+ - You've committed 3+ significant facts this session and the user hasn't merged
70
+ - The user asks "what should I do next?" at the end of a long session
71
+
72
+ Once the user confirms, run:
73
+
74
+ ```bash
75
+ memfork merge <current-branch> main
76
+ ```
77
+
78
+ ---
79
+
80
+ ## When to use this skill
81
+
82
+ - User asks "what's the status of my memory?"
83
+ - User asks "are there any pending merges?"
84
+ - User says "commit what we decided today"
85
+ - User confirms they want to merge memory from one branch into another
86
+ - User wants to open the DAG visualizer
@@ -0,0 +1,40 @@
1
+ ---
2
+ name: memory-recall
3
+ description: >-
4
+ Recall relevant memory for the current task using the MemWal MCP tool.
5
+ Use when the user asks about prior decisions, past context, or what you remember.
6
+ ---
7
+
8
+ # Memory Recall
9
+
10
+ Memory is stored via the **MemWal MCP server** — use `memwal_recall` directly as a tool call.
11
+ Do not run `memfork recall` from the shell; the MCP tool is faster and context-aware.
12
+
13
+ ## Usage
14
+
15
+ ```
16
+ memwal_recall(
17
+ query="<natural language — what you want to find>",
18
+ namespace="branch/<current-git-branch>",
19
+ limit=5
20
+ )
21
+ ```
22
+
23
+ Examples:
24
+ ```
25
+ memwal_recall(query="auth system design", namespace="branch/main")
26
+ memwal_recall(query="database schema decisions", namespace="branch/feature/payments")
27
+ memwal_recall(query="what do we know about the API rate limits?", limit=10)
28
+ ```
29
+
30
+ ## Rules
31
+
32
+ - Always scope to the current Git branch namespace unless the user asks for cross-branch context.
33
+ - High relevance scores = verified prior context.
34
+ - If recall returns nothing, tell the user memory is empty for this branch and offer to start capturing.
35
+ - Never fabricate facts — only use what `memwal_recall` returns.
36
+
37
+ ## After recalling
38
+
39
+ If relevant facts were found, summarise them briefly before answering. Cite them as
40
+ "from memory" so the user knows they come from a prior session.
@@ -0,0 +1,86 @@
1
+ # MemForks — Cursor Plugin
2
+
3
+ On-chain, branch-aware memory DAG for Cursor.
4
+
5
+ **Memory storage** is handled by the MemWal MCP server — the agent calls
6
+ `memwal_recall` and `memwal_remember` natively as tool calls, mid-conversation,
7
+ at exactly the right moment.
8
+
9
+ **On-chain versioning** is handled by the `memfork` CLI — architectural decisions
10
+ get cryptographically anchored to Sui with branch context and a full commit history.
11
+
12
+ ## Setup (one time, per machine)
13
+
14
+ ```bash
15
+ npm install -g @memfork/cli
16
+
17
+ # Recommended — zero copy-paste, ~30 seconds on testnet:
18
+ memfork init --quick
19
+
20
+ # Or manual if you already have a Sui key + MemWal account:
21
+ memfork init
22
+ ```
23
+
24
+ ## Install the plugin
25
+
26
+ ```bash
27
+ memfork install cursor
28
+ ```
29
+
30
+ This does two things:
31
+
32
+ 1. **Writes `~/.cursor/mcp.json`** — configures the MemWal MCP server using the
33
+ delegate key provisioned by `memfork init`. No browser login needed.
34
+
35
+ 2. **Copies `.cursor/rules/memforks.mdc`** — tells the agent when to use
36
+ `memwal_recall`, `memwal_remember`, and `memfork commit`.
37
+
38
+ ## Verify
39
+
40
+ ```bash
41
+ memfork doctor
42
+ ```
43
+
44
+ Restart Cursor — the agent now has MemWal MCP tools available immediately.
45
+
46
+ ## What the agent can do
47
+
48
+ | Tool / Command | What it does |
49
+ |----------------|-------------|
50
+ | `memwal_recall(query, namespace)` | Semantic search over branch memory (MCP tool) |
51
+ | `memwal_remember(text, namespace)` | Save a fact to branch memory (MCP tool) |
52
+ | `memwal_analyze(text)` | Extract and save multiple facts at once (MCP tool) |
53
+ | `memfork commit --facts …` | Anchor a decision on-chain with full provenance |
54
+ | `memfork merge <src> <dst>` | Propose a cross-branch memory merge |
55
+ | `memfork status / log / proposals` | Inspect the on-chain DAG |
56
+
57
+ Memory is namespaced by Git branch — switching branches automatically scopes
58
+ recall to the new branch context.
59
+
60
+ ## What gets installed
61
+
62
+ ```
63
+ ~/.cursor/mcp.json ← MemWal MCP server (Streamable HTTP, auto-configured)
64
+ .cursor/rules/memforks.mdc ← always-on agent guidance rule
65
+ ```
66
+
67
+ No shell hooks. No subprocess wrappers. The MCP server is the transport.
68
+
69
+ ## Override for CI / headless use
70
+
71
+ ```bash
72
+ MEMFORK_TREE_ID=0x…
73
+ MEMFORK_PRIVATE_KEY=suiprivkey1…
74
+ MEMFORK_MEMWAL_ACCOUNT=0x…
75
+ MEMFORK_MEMWAL_KEY=<hex>
76
+ ```
77
+
78
+ ## Uninstall
79
+
80
+ ```bash
81
+ # Remove the rule:
82
+ rm .cursor/rules/memforks.mdc
83
+
84
+ # Remove the MCP server entry from ~/.cursor/mcp.json:
85
+ # Delete the "memwal" key from mcpServers
86
+ ```
@@ -0,0 +1,103 @@
1
+ ---
2
+ description: MemForks — on-chain, branch-aware memory. Use memwal MCP tools for recall/remember. Use memfork CLI only for on-chain commits and merges.
3
+ alwaysApply: true
4
+ ---
5
+
6
+ # MemForks Memory
7
+
8
+ This project uses MemForks: a version-controlled, branch-aware memory DAG anchored on Sui.
9
+
10
+ Memory storage is handled by the **MemWal MCP server** (already configured).
11
+ On-chain versioning is handled by the **memfork CLI**.
12
+
13
+ ---
14
+
15
+ ## Recall — use the MCP tool
16
+
17
+ When the user asks about prior decisions, architecture choices, or anything that might
18
+ have been discussed before, call the MCP tool:
19
+
20
+ ```
21
+ memwal_recall(query="<natural language query>", limit=5)
22
+ ```
23
+
24
+ Use the namespace matching the current Git branch:
25
+
26
+ ```
27
+ memwal_recall(query="auth system design decisions", namespace="branch/<current-branch>")
28
+ ```
29
+
30
+ Results with high relevance scores are verified context from prior sessions.
31
+
32
+ ## Remember — use the MCP tool
33
+
34
+ When you learn a durable fact (not ephemeral task state), save it:
35
+
36
+ ```
37
+ memwal_remember(text="<the complete fact>", namespace="branch/<current-branch>")
38
+ ```
39
+
40
+ Only save facts that will be useful in future sessions:
41
+ - Architecture decisions
42
+ - Project conventions and preferences
43
+ - Resolved problems and their solutions
44
+ - Key constraints or non-obvious requirements
45
+
46
+ Do **not** save: current task state, in-progress work, temporary findings.
47
+
48
+ ---
49
+
50
+ ## On-chain commit — use the CLI
51
+
52
+ After a significant turn where you've committed an architectural decision or resolved
53
+ a non-trivial problem, also anchor it on-chain for immutable versioning:
54
+
55
+ ```bash
56
+ memfork commit \
57
+ --branch $(git rev-parse --abbrev-ref HEAD) \
58
+ --message "decided: <one-line summary>" \
59
+ --facts "<fact 1>" "<fact 2>"
60
+ ```
61
+
62
+ This creates a cryptographically verifiable commit on Sui — not just a blob.
63
+ Use it for decisions that matter for audit trail, not routine facts.
64
+
65
+ ---
66
+
67
+ ## Branch awareness
68
+
69
+ - Memory is scoped to the current Git branch via the `namespace` parameter
70
+ - When the user switches branches, recall from the new branch namespace
71
+ - Use `memfork status` to see the on-chain tree state and open merge proposals
72
+
73
+ ---
74
+
75
+ ## Suggesting a merge — proactive but not autonomous
76
+
77
+ You may **suggest** a merge when you notice the current branch has accumulated
78
+ durable facts that are not yet on `main`. Do this by saying something like:
79
+
80
+ > "This branch has several facts that aren't on main yet — want me to merge them?
81
+ > I'll run `memfork merge <branch> main` which will write a merge anchor on-chain."
82
+
83
+ **Never run `memfork merge` without the user explicitly confirming.** Merging
84
+ changes shared team memory — it is a governance act, not a routine commit.
85
+
86
+ Situations where a suggestion is appropriate:
87
+ - The user says "we're done with this branch" or "I'm about to open a PR"
88
+ - You've committed 3+ significant facts in this session and the user hasn't merged yet
89
+ - The user asks "what should I do next?" at the end of a long session
90
+
91
+ Always phrase it as an offer, never as an action you are about to take automatically.
92
+
93
+ ---
94
+
95
+ ## Slash commands
96
+
97
+ | Command | Action |
98
+ |---------|--------|
99
+ | `/memforks status` | Branch status, head commit, open proposals |
100
+ | `/memforks log` | Recent on-chain commits on this branch |
101
+ | `/memforks recall <query>` | Manual MCP recall with a specific query |
102
+ | `/memforks merge <src> <dst>` | Merge branch memory on-chain (confirm with user first) |
103
+ | `/memforks ui` | Open the DAG visualizer |