zmemory 0.1.0
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/LICENSE +21 -0
- package/README.md +167 -0
- package/adapters/claude-code-adapter.sh +11 -0
- package/adapters/codex-adapter.sh +12 -0
- package/adapters/cursor-adapter.sh +14 -0
- package/adapters/opencode-adapter.sh +9 -0
- package/bin/zmemory.js +426 -0
- package/package.json +42 -0
- package/src/bus/server.js +51 -0
- package/src/commands/agent.js +42 -0
- package/src/commands/archive.js +32 -0
- package/src/commands/bootstrap.js +7 -0
- package/src/commands/bus.js +6 -0
- package/src/commands/claim.js +66 -0
- package/src/commands/config.js +29 -0
- package/src/commands/context.js +269 -0
- package/src/commands/daemon.js +6 -0
- package/src/commands/decision.js +12 -0
- package/src/commands/doctor.js +100 -0
- package/src/commands/event.js +149 -0
- package/src/commands/exec.js +25 -0
- package/src/commands/explain.js +68 -0
- package/src/commands/failure.js +12 -0
- package/src/commands/gitHook.js +22 -0
- package/src/commands/handoff.js +101 -0
- package/src/commands/health.js +18 -0
- package/src/commands/help.js +33 -0
- package/src/commands/index.js +21 -0
- package/src/commands/init.js +38 -0
- package/src/commands/install.js +28 -0
- package/src/commands/locks.js +9 -0
- package/src/commands/next.js +59 -0
- package/src/commands/orchestrator.js +6 -0
- package/src/commands/plan.js +30 -0
- package/src/commands/resume.js +79 -0
- package/src/commands/route.js +67 -0
- package/src/commands/runs.js +47 -0
- package/src/commands/search.js +159 -0
- package/src/commands/setup.js +148 -0
- package/src/commands/skill.js +103 -0
- package/src/commands/startRun.js +82 -0
- package/src/commands/state.js +68 -0
- package/src/commands/status.js +51 -0
- package/src/commands/stream.js +27 -0
- package/src/commands/summary.js +65 -0
- package/src/commands/sync.js +20 -0
- package/src/commands/tasks.js +89 -0
- package/src/commands/timeline.js +75 -0
- package/src/commands/upgrade.js +19 -0
- package/src/commands/version.js +12 -0
- package/src/commands/who.js +26 -0
- package/src/commands/worker.js +71 -0
- package/src/commands/workspaces.js +25 -0
- package/src/daemon/orchestrator.js +34 -0
- package/src/daemon/zmemoryd.js +17 -0
- package/src/dashboard/server.js +40 -0
- package/src/integrations/agent-hooks.md +39 -0
- package/src/integrations/auto-bootstrap.js +90 -0
- package/src/integrations/harness-adapter.md +39 -0
- package/src/lib/agents.js +36 -0
- package/src/lib/config.js +15 -0
- package/src/lib/coordination/agents.js +49 -0
- package/src/lib/coordination/claims.js +127 -0
- package/src/lib/coordination/who.js +49 -0
- package/src/lib/fileIndex.js +36 -0
- package/src/lib/fileLocks.js +44 -0
- package/src/lib/fs.js +140 -0
- package/src/lib/lock.js +103 -0
- package/src/lib/repoScan.js +19 -0
- package/src/lib/run.js +63 -0
- package/src/lib/sqlite.js +7 -0
- package/src/lib/tasks.js +77 -0
- package/src/lib/teamSync.js +36 -0
- package/src/lib/workspaces.js +29 -0
- package/src/mcp/autostart.js +12 -0
- package/src/mcp/server.js +420 -0
- package/src/mcp/tools.json +28 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 ZMemory contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
# ZMemory
|
|
2
|
+
|
|
3
|
+
**Shared project memory for AI agents.**
|
|
4
|
+
|
|
5
|
+
ZMemory is a lightweight coordination layer that allows multiple AI coding agents
|
|
6
|
+
(Codex, Claude Code, OpenCode, Cursor, Kilo, Kimi, etc.) to safely collaborate
|
|
7
|
+
inside the same repository.
|
|
8
|
+
|
|
9
|
+
It provides a shared operational memory where agents can:
|
|
10
|
+
|
|
11
|
+
- see who is working on which files
|
|
12
|
+
- coordinate edits
|
|
13
|
+
- track activity and decisions
|
|
14
|
+
- recover context across sessions
|
|
15
|
+
|
|
16
|
+
ZMemory stores all coordination state inside the project in a `.zmemory/` folder.
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
# Install
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
npm install -g zmemory
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Then run the interactive setup:
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
zmemory setup
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
This configures ZMemory for supported AI coding tools (Codex CLI, Claude Code,
|
|
33
|
+
OpenCode, Cursor, Kilo Code, etc.) and optionally initializes the repository.
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
# Initialize a Repository
|
|
38
|
+
|
|
39
|
+
Inside a project:
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
zmemory init
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
This creates:
|
|
46
|
+
|
|
47
|
+
```
|
|
48
|
+
.zmemory/
|
|
49
|
+
agents/
|
|
50
|
+
claims/
|
|
51
|
+
logs/
|
|
52
|
+
runs/
|
|
53
|
+
skills/
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
The `.zmemory` directory contains all coordination state for the project.
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
# Typical Agent Workflow
|
|
61
|
+
|
|
62
|
+
When an agent starts working in a repository:
|
|
63
|
+
|
|
64
|
+
```
|
|
65
|
+
zmemory resume
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
This returns:
|
|
69
|
+
|
|
70
|
+
- active agents
|
|
71
|
+
- open file claims
|
|
72
|
+
- recent activity
|
|
73
|
+
- current run state
|
|
74
|
+
|
|
75
|
+
Before editing files:
|
|
76
|
+
|
|
77
|
+
```
|
|
78
|
+
zmemory who <file>
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
When beginning work on a module:
|
|
82
|
+
|
|
83
|
+
```
|
|
84
|
+
zmemory claim src/auth/* --session <agent-session>
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Record meaningful work:
|
|
88
|
+
|
|
89
|
+
```
|
|
90
|
+
zmemory event --summary "implemented auth middleware" --files src/auth/middleware.js
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Release ownership when done:
|
|
94
|
+
|
|
95
|
+
```
|
|
96
|
+
zmemory release --session <agent-session>
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
# Debugging Coordination
|
|
102
|
+
|
|
103
|
+
To understand why a file is claimed:
|
|
104
|
+
|
|
105
|
+
```
|
|
106
|
+
zmemory explain <file>
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Example output:
|
|
110
|
+
|
|
111
|
+
```
|
|
112
|
+
Active claims
|
|
113
|
+
src/auth/*
|
|
114
|
+
codex‑a1 implement auth middleware (expires in: 7m)
|
|
115
|
+
|
|
116
|
+
Recent related activity
|
|
117
|
+
executor: implementing middleware
|
|
118
|
+
reviewer: reviewing middleware
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
# Diagnostics
|
|
124
|
+
|
|
125
|
+
Check system health:
|
|
126
|
+
|
|
127
|
+
```
|
|
128
|
+
zmemory doctor
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
# Updating
|
|
134
|
+
|
|
135
|
+
```
|
|
136
|
+
zmemory update
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
or
|
|
140
|
+
|
|
141
|
+
```
|
|
142
|
+
zmemory upgrade
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Both install the latest version and run diagnostics.
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
# Commands
|
|
150
|
+
|
|
151
|
+
```
|
|
152
|
+
zmemory setup
|
|
153
|
+
zmemory init
|
|
154
|
+
zmemory resume
|
|
155
|
+
zmemory claim
|
|
156
|
+
zmemory who
|
|
157
|
+
zmemory event
|
|
158
|
+
zmemory explain
|
|
159
|
+
zmemory doctor
|
|
160
|
+
zmemory update
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
---
|
|
164
|
+
|
|
165
|
+
# License
|
|
166
|
+
|
|
167
|
+
MIT
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
# Adapter for Claude Code harness
|
|
3
|
+
|
|
4
|
+
zmemory bootstrap >/dev/null 2>&1
|
|
5
|
+
if ! pgrep -f "zmemory daemon" >/dev/null 2>&1; then
|
|
6
|
+
(zmemory daemon >/dev/null 2>&1 &)
|
|
7
|
+
fi
|
|
8
|
+
zmemory resume
|
|
9
|
+
|
|
10
|
+
# Claude can call context before work
|
|
11
|
+
# zmemory context --role reviewer
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
# Minimal adapter so Codex sessions automatically use ZMemory
|
|
3
|
+
|
|
4
|
+
zmemory bootstrap >/dev/null 2>&1
|
|
5
|
+
# ensure daemon + MCP runtime are running
|
|
6
|
+
if ! pgrep -f "zmemory daemon" >/dev/null 2>&1; then
|
|
7
|
+
(zmemory daemon >/dev/null 2>&1 &)
|
|
8
|
+
fi
|
|
9
|
+
zmemory resume
|
|
10
|
+
|
|
11
|
+
# After Codex modifies files, user/automation can run:
|
|
12
|
+
# zmemory event --role executor --type file_changed --summary "codex update"
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
# Cursor adapter for ZMemory
|
|
3
|
+
|
|
4
|
+
# Ensure runtime exists
|
|
5
|
+
zmemory bootstrap >/dev/null 2>&1
|
|
6
|
+
|
|
7
|
+
# Start daemon if not running
|
|
8
|
+
if ! pgrep -f "zmemory daemon" >/dev/null 2>&1; then
|
|
9
|
+
(zmemory daemon >/dev/null 2>&1 &)
|
|
10
|
+
fi
|
|
11
|
+
|
|
12
|
+
# Load latest context
|
|
13
|
+
zmemory resume
|
|
14
|
+
|
package/bin/zmemory.js
ADDED
|
@@ -0,0 +1,426 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { initProject } from "../src/commands/init.js";
|
|
3
|
+
import { status } from "../src/commands/status.js";
|
|
4
|
+
import { startRun } from "../src/commands/startRun.js";
|
|
5
|
+
import { appendEvent } from "../src/commands/event.js";
|
|
6
|
+
import { nextAction } from "../src/commands/next.js";
|
|
7
|
+
import { decisionAdd } from "../src/commands/decision.js";
|
|
8
|
+
import { failureAdd } from "../src/commands/failure.js";
|
|
9
|
+
import { generateContext } from "../src/commands/context.js";
|
|
10
|
+
import { generateHandoff } from "../src/commands/handoff.js";
|
|
11
|
+
import { summary } from "../src/commands/summary.js";
|
|
12
|
+
import { updateState } from "../src/commands/state.js";
|
|
13
|
+
import { searchMemory } from "../src/commands/search.js";
|
|
14
|
+
import { generateSkill } from "../src/commands/skill.js";
|
|
15
|
+
import { archiveRun } from "../src/commands/archive.js";
|
|
16
|
+
import { doctor } from "../src/commands/doctor.js";
|
|
17
|
+
import { listRuns } from "../src/commands/runs.js";
|
|
18
|
+
import { resumeRun } from "../src/commands/resume.js";
|
|
19
|
+
import { routeRun } from "../src/commands/route.js";
|
|
20
|
+
import { agentCommand } from "../src/commands/agent.js";
|
|
21
|
+
import { claimCommand } from "../src/commands/claim.js";
|
|
22
|
+
import { whoCommand } from "../src/commands/who.js";
|
|
23
|
+
import { explainCommand } from "../src/commands/explain.js";
|
|
24
|
+
import { setupCommand } from "../src/commands/setup.js";
|
|
25
|
+
import { execCommand } from "../src/commands/exec.js";
|
|
26
|
+
import { tasksCommand } from "../src/commands/tasks.js";
|
|
27
|
+
import { locksCommand } from "../src/commands/locks.js";
|
|
28
|
+
import { bootstrapCommand } from "../src/commands/bootstrap.js";
|
|
29
|
+
import { streamEvents } from "../src/commands/stream.js";
|
|
30
|
+
import { installGitHook } from "../src/commands/gitHook.js";
|
|
31
|
+
import { startDashboard } from "../src/dashboard/server.js";
|
|
32
|
+
import { busCommand } from "../src/commands/bus.js";
|
|
33
|
+
import { workerCommand } from "../src/commands/worker.js";
|
|
34
|
+
import { planCommand } from "../src/commands/plan.js";
|
|
35
|
+
import { indexCommand } from "../src/commands/index.js";
|
|
36
|
+
import { syncCommand } from "../src/commands/sync.js";
|
|
37
|
+
import { configCommand } from "../src/commands/config.js";
|
|
38
|
+
import { healthCommand } from "../src/commands/health.js";
|
|
39
|
+
import { helpCommand } from "../src/commands/help.js";
|
|
40
|
+
import { upgradeCommand } from "../src/commands/upgrade.js";
|
|
41
|
+
import { ensureZMemory } from "../src/integrations/auto-bootstrap.js";
|
|
42
|
+
import { installCommand } from "../src/commands/install.js";
|
|
43
|
+
import { versionCommand } from "../src/commands/version.js";
|
|
44
|
+
import { orchestratorCommand } from "../src/commands/orchestrator.js";
|
|
45
|
+
import { workspacesCommand } from "../src/commands/workspaces.js";
|
|
46
|
+
import { isValidRunId } from "../src/lib/run.js";
|
|
47
|
+
|
|
48
|
+
const args = process.argv.slice(2);
|
|
49
|
+
const cmd = args[0];
|
|
50
|
+
|
|
51
|
+
// Global flags
|
|
52
|
+
if (args.includes("-v") || args.includes("--version")) {
|
|
53
|
+
await versionCommand();
|
|
54
|
+
process.exit(0);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (args.includes("-h") || args.includes("--help")) {
|
|
58
|
+
await helpCommand();
|
|
59
|
+
process.exit(0);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function getRunArg(args) {
|
|
63
|
+
const i = args.indexOf("--run");
|
|
64
|
+
if (i === -1) return { present: false, value: null };
|
|
65
|
+
const v = args[i + 1];
|
|
66
|
+
if (typeof v !== "string" || v.startsWith("--")) return { present: true, value: null };
|
|
67
|
+
return { present: true, value: v };
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function shouldBootstrap(cmd, args) {
|
|
71
|
+
if (!cmd) return false;
|
|
72
|
+
|
|
73
|
+
const readOnly = new Set([
|
|
74
|
+
"help",
|
|
75
|
+
"version",
|
|
76
|
+
"doctor",
|
|
77
|
+
"status",
|
|
78
|
+
"health",
|
|
79
|
+
"runs",
|
|
80
|
+
"search",
|
|
81
|
+
"locks",
|
|
82
|
+
"next",
|
|
83
|
+
"summary",
|
|
84
|
+
"route",
|
|
85
|
+
"stream",
|
|
86
|
+
"resume",
|
|
87
|
+
"who",
|
|
88
|
+
"claims"
|
|
89
|
+
]);
|
|
90
|
+
|
|
91
|
+
if (readOnly.has(cmd)) return false;
|
|
92
|
+
const stateful = new Set([
|
|
93
|
+
"bootstrap",
|
|
94
|
+
"mcp",
|
|
95
|
+
"daemon",
|
|
96
|
+
"init",
|
|
97
|
+
"start-run",
|
|
98
|
+
"event",
|
|
99
|
+
"decision",
|
|
100
|
+
"failure",
|
|
101
|
+
"context",
|
|
102
|
+
"handoff",
|
|
103
|
+
"skill",
|
|
104
|
+
"archive",
|
|
105
|
+
"exec",
|
|
106
|
+
"git-hook",
|
|
107
|
+
"dashboard",
|
|
108
|
+
"bus",
|
|
109
|
+
"worker",
|
|
110
|
+
"plan",
|
|
111
|
+
"install",
|
|
112
|
+
"orchestrator",
|
|
113
|
+
"workspaces"
|
|
114
|
+
]);
|
|
115
|
+
|
|
116
|
+
if (cmd === "config") {
|
|
117
|
+
if (args[1] !== "set") return false;
|
|
118
|
+
const key = args[2];
|
|
119
|
+
const value = args[3];
|
|
120
|
+
return (
|
|
121
|
+
typeof key === "string" && key.trim().length > 0 &&
|
|
122
|
+
typeof value === "string" && value.trim().length > 0
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
if (cmd === "tasks") {
|
|
127
|
+
const sub = args[1];
|
|
128
|
+
if (sub === "add") {
|
|
129
|
+
const rest = args.slice(2);
|
|
130
|
+
let titleParts = [];
|
|
131
|
+
let deps = [];
|
|
132
|
+
let files = [];
|
|
133
|
+
|
|
134
|
+
for (let i = 0; i < rest.length; i++) {
|
|
135
|
+
const a = rest[i];
|
|
136
|
+
if (a === "--after" || a === "--files") {
|
|
137
|
+
const val = rest[i + 1];
|
|
138
|
+
if (typeof val !== "string" || !val.trim() || val.startsWith("--")) return false;
|
|
139
|
+
const parts = val.split(",").map(s => s.trim()).filter(Boolean);
|
|
140
|
+
if (parts.length === 0) return false;
|
|
141
|
+
if (a === "--after") deps = parts;
|
|
142
|
+
else files = parts;
|
|
143
|
+
i++;
|
|
144
|
+
continue;
|
|
145
|
+
}
|
|
146
|
+
titleParts.push(a);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
const title = titleParts.join(" ").trim();
|
|
150
|
+
if (!title) return false;
|
|
151
|
+
return true;
|
|
152
|
+
}
|
|
153
|
+
if (sub === "claim" || sub === "done") {
|
|
154
|
+
const id = args[2];
|
|
155
|
+
return typeof id === "string" && id.trim().length > 0;
|
|
156
|
+
}
|
|
157
|
+
return false;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
if (cmd === "agent") {
|
|
161
|
+
const sub = args[1];
|
|
162
|
+
if (sub === "register") {
|
|
163
|
+
const name = args[2];
|
|
164
|
+
return typeof name === "string" && name.trim().length > 0;
|
|
165
|
+
}
|
|
166
|
+
if (sub === "heartbeat") {
|
|
167
|
+
const name = args[2];
|
|
168
|
+
return typeof name === "string" && name.trim().length > 0;
|
|
169
|
+
}
|
|
170
|
+
return false;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
if (cmd === "state") {
|
|
174
|
+
if (args[1] !== "update") return false;
|
|
175
|
+
const idx = args.indexOf("--run");
|
|
176
|
+
if (idx === -1) return false;
|
|
177
|
+
const runId = args[idx + 1];
|
|
178
|
+
if (!runId || typeof runId !== "string") return false;
|
|
179
|
+
if (!isValidRunId(runId)) return false;
|
|
180
|
+
return true;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
if (cmd === "context" || cmd === "handoff" || cmd === "archive") {
|
|
184
|
+
const r = getRunArg(args);
|
|
185
|
+
if (!r.present) return false;
|
|
186
|
+
if (!r.value) return false;
|
|
187
|
+
return isValidRunId(r.value);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
if (cmd === "event") {
|
|
191
|
+
const get = (flag) => {
|
|
192
|
+
const i = args.indexOf(flag);
|
|
193
|
+
if (i === -1) return { present: false, value: null };
|
|
194
|
+
const v = args[i + 1];
|
|
195
|
+
if (typeof v !== "string" || v.startsWith("--")) return { present: true, value: null };
|
|
196
|
+
return { present: true, value: v };
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
const role = get("--role");
|
|
200
|
+
const type = get("--type");
|
|
201
|
+
const summary = get("--summary");
|
|
202
|
+
if (!role.present || !type.present || !summary.present) return false;
|
|
203
|
+
if (!role.value || !role.value.trim()) return false;
|
|
204
|
+
if (!type.value || !type.value.trim()) return false;
|
|
205
|
+
if (!summary.value || !summary.value.trim()) return false;
|
|
206
|
+
|
|
207
|
+
const r = get("--run");
|
|
208
|
+
if (!r.present) return true; // valid global event
|
|
209
|
+
if (!r.value) return false;
|
|
210
|
+
return isValidRunId(r.value);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
if (cmd === "skill") {
|
|
214
|
+
return args[1] === "generate";
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
if (cmd === "plan") {
|
|
218
|
+
const goal = args.slice(1).join(" ").trim();
|
|
219
|
+
return goal.length > 0;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
if (cmd === "exec") {
|
|
223
|
+
const command = args.slice(1).join(" ").trim();
|
|
224
|
+
return command.length > 0;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
if (cmd === "decision") {
|
|
228
|
+
const text = args.slice(1).join(" ").trim();
|
|
229
|
+
return text.length > 0;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
if (cmd === "failure") {
|
|
233
|
+
const text = args.slice(1).join(" ").trim();
|
|
234
|
+
return text.length > 0;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
if (cmd === "workspaces") {
|
|
238
|
+
const sub = args[1];
|
|
239
|
+
if (sub === "add") {
|
|
240
|
+
const p = args[2];
|
|
241
|
+
return typeof p === "string" && p.trim().length > 0;
|
|
242
|
+
}
|
|
243
|
+
return false;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
if (cmd === "index") {
|
|
247
|
+
const sub = args[1];
|
|
248
|
+
return sub === "build";
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
if (cmd === "sync") {
|
|
252
|
+
const sub = args[1];
|
|
253
|
+
return sub === "push" || sub === "pull";
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
return stateful.has(cmd);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
async function main() {
|
|
260
|
+
if (shouldBootstrap(cmd, args)) {
|
|
261
|
+
try {
|
|
262
|
+
ensureZMemory();
|
|
263
|
+
} catch (err) {
|
|
264
|
+
console.error("ZMemory bootstrap failed:", err?.message || err);
|
|
265
|
+
process.exitCode = 1;
|
|
266
|
+
return;
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
switch (cmd) {
|
|
270
|
+
case "init":
|
|
271
|
+
await initProject();
|
|
272
|
+
break;
|
|
273
|
+
case "status":
|
|
274
|
+
await status();
|
|
275
|
+
break;
|
|
276
|
+
case "start-run":
|
|
277
|
+
await startRun(args.slice(1).join(" "));
|
|
278
|
+
break;
|
|
279
|
+
case "event":
|
|
280
|
+
await appendEvent(args.slice(1));
|
|
281
|
+
break;
|
|
282
|
+
case "next":
|
|
283
|
+
await nextAction(args.slice(1));
|
|
284
|
+
break;
|
|
285
|
+
case "decision":
|
|
286
|
+
await decisionAdd(args.slice(1));
|
|
287
|
+
break;
|
|
288
|
+
case "failure":
|
|
289
|
+
await failureAdd(args.slice(1));
|
|
290
|
+
break;
|
|
291
|
+
case "context":
|
|
292
|
+
await generateContext(args.slice(1));
|
|
293
|
+
break;
|
|
294
|
+
case "state":
|
|
295
|
+
if (args[1] === "update") {
|
|
296
|
+
await updateState(args.slice(2));
|
|
297
|
+
}
|
|
298
|
+
break;
|
|
299
|
+
case "handoff":
|
|
300
|
+
await generateHandoff(args.slice(1));
|
|
301
|
+
break;
|
|
302
|
+
case "summary":
|
|
303
|
+
await summary(args.slice(1));
|
|
304
|
+
break;
|
|
305
|
+
case "search":
|
|
306
|
+
await searchMemory(args.slice(1));
|
|
307
|
+
break;
|
|
308
|
+
case "skill":
|
|
309
|
+
if (args[1] === "generate") {
|
|
310
|
+
await generateSkill(args.slice(2));
|
|
311
|
+
}
|
|
312
|
+
break;
|
|
313
|
+
case "archive":
|
|
314
|
+
await archiveRun(args.slice(1));
|
|
315
|
+
break;
|
|
316
|
+
case "runs":
|
|
317
|
+
await listRuns();
|
|
318
|
+
break;
|
|
319
|
+
case "resume":
|
|
320
|
+
await resumeRun();
|
|
321
|
+
break;
|
|
322
|
+
case "route":
|
|
323
|
+
await routeRun(args.slice(1));
|
|
324
|
+
break;
|
|
325
|
+
case "agent":
|
|
326
|
+
await agentCommand(args.slice(1));
|
|
327
|
+
break;
|
|
328
|
+
case "claim":
|
|
329
|
+
await claimCommand(args.slice(1));
|
|
330
|
+
break;
|
|
331
|
+
case "claims":
|
|
332
|
+
await claimCommand(["claims"]);
|
|
333
|
+
break;
|
|
334
|
+
case "release":
|
|
335
|
+
await claimCommand(["release", ...args.slice(1)]);
|
|
336
|
+
break;
|
|
337
|
+
case "who":
|
|
338
|
+
await whoCommand(args.slice(1));
|
|
339
|
+
break;
|
|
340
|
+
case "explain":
|
|
341
|
+
await explainCommand(args.slice(1));
|
|
342
|
+
break;
|
|
343
|
+
case "setup":
|
|
344
|
+
await setupCommand();
|
|
345
|
+
break;
|
|
346
|
+
case "exec":
|
|
347
|
+
await execCommand(args.slice(1));
|
|
348
|
+
break;
|
|
349
|
+
case "tasks":
|
|
350
|
+
await tasksCommand(args.slice(1));
|
|
351
|
+
break;
|
|
352
|
+
case "locks":
|
|
353
|
+
await locksCommand();
|
|
354
|
+
break;
|
|
355
|
+
case "bootstrap":
|
|
356
|
+
await bootstrapCommand();
|
|
357
|
+
break;
|
|
358
|
+
case "stream":
|
|
359
|
+
await streamEvents();
|
|
360
|
+
break;
|
|
361
|
+
case "git-hook":
|
|
362
|
+
await installGitHook();
|
|
363
|
+
break;
|
|
364
|
+
case "dashboard":
|
|
365
|
+
startDashboard();
|
|
366
|
+
break;
|
|
367
|
+
case "bus":
|
|
368
|
+
await busCommand();
|
|
369
|
+
break;
|
|
370
|
+
case "worker":
|
|
371
|
+
await workerCommand(args.slice(1));
|
|
372
|
+
break;
|
|
373
|
+
case "plan":
|
|
374
|
+
await planCommand(args.slice(1));
|
|
375
|
+
break;
|
|
376
|
+
case "index":
|
|
377
|
+
await indexCommand(args.slice(1));
|
|
378
|
+
break;
|
|
379
|
+
case "sync":
|
|
380
|
+
await syncCommand(args.slice(1));
|
|
381
|
+
break;
|
|
382
|
+
case "config":
|
|
383
|
+
await configCommand(args.slice(1));
|
|
384
|
+
break;
|
|
385
|
+
case "health":
|
|
386
|
+
await healthCommand();
|
|
387
|
+
break;
|
|
388
|
+
case "help":
|
|
389
|
+
await helpCommand();
|
|
390
|
+
break;
|
|
391
|
+
case "install":
|
|
392
|
+
await installCommand();
|
|
393
|
+
break;
|
|
394
|
+
case "version":
|
|
395
|
+
await versionCommand();
|
|
396
|
+
break;
|
|
397
|
+
case "update":
|
|
398
|
+
case "upgrade":
|
|
399
|
+
await upgradeCommand();
|
|
400
|
+
break;
|
|
401
|
+
case "orchestrator":
|
|
402
|
+
await orchestratorCommand();
|
|
403
|
+
break;
|
|
404
|
+
case "daemon":
|
|
405
|
+
{
|
|
406
|
+
const mod = await import("../src/commands/daemon.js");
|
|
407
|
+
await mod.daemonCommand();
|
|
408
|
+
}
|
|
409
|
+
break;
|
|
410
|
+
case "workspaces":
|
|
411
|
+
await workspacesCommand(args.slice(1));
|
|
412
|
+
break;
|
|
413
|
+
case "doctor":
|
|
414
|
+
await doctor();
|
|
415
|
+
break;
|
|
416
|
+
case "mcp":
|
|
417
|
+
console.error("ZMemory MCP server started (stdio mode)");
|
|
418
|
+
await import("../src/mcp/server.js");
|
|
419
|
+
break;
|
|
420
|
+
default:
|
|
421
|
+
console.log("ZMemory CLI");
|
|
422
|
+
console.log("Commands: init status start-run context event handoff decision failure next summary");
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
main();
|
package/package.json
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "zmemory",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Local-first shared memory layer for AI coding agents",
|
|
5
|
+
"bin": {
|
|
6
|
+
"zmemory": "bin/zmemory.js"
|
|
7
|
+
},
|
|
8
|
+
"keywords": [
|
|
9
|
+
"ai",
|
|
10
|
+
"agents",
|
|
11
|
+
"coordination",
|
|
12
|
+
"developer-tools",
|
|
13
|
+
"workflow"
|
|
14
|
+
],
|
|
15
|
+
"license": "MIT",
|
|
16
|
+
"type": "module",
|
|
17
|
+
"engines": {
|
|
18
|
+
"node": ">=20"
|
|
19
|
+
},
|
|
20
|
+
"files": [
|
|
21
|
+
"bin/",
|
|
22
|
+
"src/",
|
|
23
|
+
"adapters/",
|
|
24
|
+
"README.md",
|
|
25
|
+
"LICENSE"
|
|
26
|
+
],
|
|
27
|
+
"scripts": {
|
|
28
|
+
"start": "node bin/zmemory.js",
|
|
29
|
+
"mcp": "node bin/zmemory.js mcp",
|
|
30
|
+
"check:syntax": "node scripts/check-syntax.js",
|
|
31
|
+
"test:cli": "node test/cli-smoke.js",
|
|
32
|
+
"test:scripts": "node test/script-cwd-smoke.js",
|
|
33
|
+
"test:mcp": "node test/mcp-contract-smoke.js",
|
|
34
|
+
"test:package": "node test/package-smoke.js",
|
|
35
|
+
"test": "npm run check:syntax && npm run test:cli && npm run test:scripts && npm run test:mcp && npm run test:package",
|
|
36
|
+
"prepare": "node scripts/prepare.js"
|
|
37
|
+
},
|
|
38
|
+
"dependencies": {
|
|
39
|
+
"picomatch": "^4.0.0",
|
|
40
|
+
"@clack/prompts": "^0.7.0"
|
|
41
|
+
}
|
|
42
|
+
}
|