@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.
- package/dist/commands/install.js +2 -2
- package/dist/commands/ui-server.js +1 -1
- package/dist/config.d.ts +6 -6
- package/dist/config.js +37 -42
- package/package.json +3 -2
- package/plugins/codex/.codex-plugin/plugin.json +44 -0
- package/plugins/codex/README.md +81 -0
- package/plugins/codex/skills/memforks-status/SKILL.md +86 -0
- package/plugins/codex/skills/memory-recall/SKILL.md +40 -0
- package/plugins/cursor/README.md +86 -0
- package/plugins/cursor/rules/memforks.mdc +103 -0
package/dist/commands/install.js
CHANGED
|
@@ -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 →
|
|
25
|
-
const PLUGIN_ROOT = path.resolve(__dirname, "..", "..", "
|
|
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 ?? "
|
|
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: "
|
|
28
|
+
readonly memforksPackageId: "0x185e765a4979fb9d9089374f822485c88b9d0b2f91f9b1313a73043d5ef2357f";
|
|
29
29
|
readonly registryId: "0xe80f2feec1c139616a86c9f71210152e2a7ca552b20841f2e192f99f75864437";
|
|
30
|
-
readonly relayer: "https://relayer
|
|
30
|
+
readonly relayer: "https://relayer-staging.memory.walrus.xyz";
|
|
31
31
|
};
|
|
32
32
|
readonly mainnet: {
|
|
33
33
|
readonly packageId: "0xcee7a6fd8de52ce645c38332bde23d4a30fd9426bc4681409733dd50958a24c6";
|
|
34
|
-
readonly memforksPackageId: "
|
|
34
|
+
readonly memforksPackageId: "0xc13cc014fb8084b3468f6e5ffdc272e64ef35b7a912332eba7a0d44dd66b3121";
|
|
35
35
|
readonly registryId: "0x0da982cefa26864ae834a8a0504b904233d49e20fcc17c373c8bed99c75a7edd";
|
|
36
|
-
readonly relayer: "https://relayer.
|
|
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?:
|
|
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:
|
|
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
|
|
26
|
-
import path from
|
|
27
|
-
import os from
|
|
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:
|
|
33
|
-
memforksPackageId:
|
|
34
|
-
registryId:
|
|
35
|
-
relayer:
|
|
32
|
+
packageId: '0xcf6ad755a1cdff7217865c796778fabe5aa399cb0cf2eba986f4b582047229c6',
|
|
33
|
+
memforksPackageId: '0x185e765a4979fb9d9089374f822485c88b9d0b2f91f9b1313a73043d5ef2357f',
|
|
34
|
+
registryId: '0xe80f2feec1c139616a86c9f71210152e2a7ca552b20841f2e192f99f75864437',
|
|
35
|
+
relayer: 'https://relayer-staging.memory.walrus.xyz',
|
|
36
36
|
},
|
|
37
37
|
mainnet: {
|
|
38
|
-
packageId:
|
|
39
|
-
memforksPackageId:
|
|
40
|
-
registryId:
|
|
41
|
-
relayer:
|
|
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
|
-
|
|
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,
|
|
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,
|
|
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(),
|
|
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,
|
|
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,
|
|
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,
|
|
97
|
+
const dir = path.join(root, '.memfork');
|
|
98
98
|
fs.mkdirSync(dir, { recursive: true });
|
|
99
|
-
fs.writeFileSync(path.join(root,
|
|
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,
|
|
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(),
|
|
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) +
|
|
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 =
|
|
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[
|
|
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(
|
|
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[
|
|
158
|
-
|
|
159
|
-
const
|
|
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[
|
|
167
|
+
const network = (env['MEMFORK_NETWORK'] ??
|
|
174
168
|
project?.network ??
|
|
175
|
-
|
|
169
|
+
'mainnet');
|
|
176
170
|
return {
|
|
177
171
|
treeId,
|
|
178
172
|
privateKey,
|
|
179
173
|
memwalAccountId,
|
|
180
174
|
memwalKey,
|
|
181
|
-
memwalRelayer: env[
|
|
175
|
+
memwalRelayer: env['MEMFORK_RELAYER_URL'] ??
|
|
182
176
|
stored?.memwalRelayer ??
|
|
183
177
|
defaultRelayer(network),
|
|
184
178
|
network,
|
|
185
|
-
defaultBranch: project?.defaultBranch ??
|
|
186
|
-
rpcUrl: env[
|
|
187
|
-
packageId: env[
|
|
188
|
-
sponsorUrl: env[
|
|
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.
|
|
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 |
|