Skip to content

Commit 28f7625

Browse files
committed
Add hybrid instance support with central/project isolation and scope enforcement
* .env.example: Added OPENCLAW_INSTANCE, OPENCLAW_DEFAULT_SCOPE, and OPENCLAW_ALLOWED_SCOPE_PREFIXES configuration options * .gitignore: Extended runtime DB patterns to cover nested instance directories (runtime/**/*.db, .db-shm, .db-wal) * README.md: Added Hybrid Mode section with dev:central/project-a/project-b commands, docker-compose.hybrid.yml reference, and new environment variable documentation * docker
1 parent 54f9d06 commit 28f7625

File tree

15 files changed

+595
-16
lines changed

15 files changed

+595
-16
lines changed

.env.example

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,20 @@ OPENCLAW_HOST=127.0.0.1
2121
# Default: 8787
2222
OPENCLAW_PORT=8787
2323

24+
# Instance name used for logging + health metadata.
25+
# Example: central | project-a | project-b
26+
OPENCLAW_INSTANCE=default
27+
28+
# Default scope used when memory updates omit "scope".
29+
# For project-specific instances, set this to "project".
30+
OPENCLAW_DEFAULT_SCOPE=general
31+
32+
# Optional comma-separated scope prefixes allowed on this instance.
33+
# If empty, all scopes are accepted.
34+
# Example for central: preferences,identity,facts
35+
# Example for project-only: project,project-a
36+
OPENCLAW_ALLOWED_SCOPE_PREFIXES=
37+
2438
# ── Security ──────────────────────────────────────────────────────────────────
2539

2640
# API key required on every request as the `x-api-key` header.

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55
__pycache__/
66
.venv/
77
runtime/*.db
8+
runtime/**/*.db
9+
runtime/**/*.db-shm
10+
runtime/**/*.db-wal
811
node_modules/
912
dist/
1013
*.tsbuildinfo

README.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,27 @@ npm run dev
4040

4141
Server starts at `http://localhost:8787` — Swagger docs at `http://localhost:8787/docs`
4242

43+
### Hybrid Mode (Central + Project Instances)
44+
45+
Run isolated instances with built-in presets:
46+
47+
```bash
48+
# central user memory (port 8787)
49+
npm run dev:central
50+
51+
# project memory instances (ports 8788, 8789)
52+
npm run dev:project-a
53+
npm run dev:project-b
54+
```
55+
56+
See full guide: [hybrid-setup.md](hybrid-setup.md)
57+
58+
Docker variant:
59+
60+
```bash
61+
docker compose -f docker-compose.hybrid.yml up -d
62+
```
63+
4364
### Try It Out
4465

4566
```bash
@@ -93,6 +114,8 @@ Add to your MCP config (e.g. `~/.cursor/mcp.json` or Claude Code settings):
93114

94115
Build first: `npm run build`
95116

117+
For hybrid central/project MCP wiring, see [hybrid-setup.md](hybrid-setup.md).
118+
96119
Available MCP tools:
97120
| Tool | Description |
98121
|------|-------------|
@@ -185,7 +208,10 @@ Copy `.env.example` to `.env` and adjust:
185208
|----------|---------|-------------|
186209
| `OPENCLAW_HOST` | `127.0.0.1` | Server bind address |
187210
| `OPENCLAW_PORT` | `8787` | Server port |
211+
| `OPENCLAW_INSTANCE` | `default` | Instance label (e.g. central, project-a) |
188212
| `OPENCLAW_DB_PATH` | `./runtime/openclaw.db` | SQLite database path |
213+
| `OPENCLAW_DEFAULT_SCOPE` | `general` | Scope used when update scope is omitted |
214+
| `OPENCLAW_ALLOWED_SCOPE_PREFIXES` | *(empty)* | Comma-separated allowed scope prefixes |
189215
| `OPENCLAW_API_KEY` | *(empty)* | API key for auth (set in production) |
190216
| `OPENCLAW_CORS_ORIGIN` | `*` | CORS allowed origin |
191217

docker-compose.hybrid.yml

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
services:
2+
memorycore-central:
3+
build: .
4+
container_name: memorycore-central
5+
restart: unless-stopped
6+
ports:
7+
- "8787:8787"
8+
environment:
9+
- NODE_ENV=production
10+
- OPENCLAW_HOST=0.0.0.0
11+
- OPENCLAW_PORT=8787
12+
- OPENCLAW_INSTANCE=central
13+
- OPENCLAW_RUNTIME_DIR=/app/runtime
14+
- OPENCLAW_DB_PATH=/app/runtime/openclaw.db
15+
- OPENCLAW_DEFAULT_SCOPE=preferences
16+
- OPENCLAW_ALLOWED_SCOPE_PREFIXES=preferences,identity,facts
17+
- OPENCLAW_API_KEY=${OPENCLAW_API_KEY}
18+
- OPENCLAW_CORS_ORIGIN=${OPENCLAW_CORS_ORIGIN:-*}
19+
volumes:
20+
- ./runtime/central:/app/runtime
21+
healthcheck:
22+
test: ["CMD", "wget", "-qO-", "http://localhost:8787/health"]
23+
interval: 30s
24+
timeout: 5s
25+
retries: 3
26+
start_period: 10s
27+
28+
memorycore-project-a:
29+
build: .
30+
container_name: memorycore-project-a
31+
restart: unless-stopped
32+
ports:
33+
- "8788:8787"
34+
environment:
35+
- NODE_ENV=production
36+
- OPENCLAW_HOST=0.0.0.0
37+
- OPENCLAW_PORT=8787
38+
- OPENCLAW_INSTANCE=project-a
39+
- OPENCLAW_RUNTIME_DIR=/app/runtime
40+
- OPENCLAW_DB_PATH=/app/runtime/openclaw.db
41+
- OPENCLAW_DEFAULT_SCOPE=project
42+
- OPENCLAW_ALLOWED_SCOPE_PREFIXES=project,project-a
43+
- OPENCLAW_API_KEY=${OPENCLAW_API_KEY}
44+
- OPENCLAW_CORS_ORIGIN=${OPENCLAW_CORS_ORIGIN:-*}
45+
volumes:
46+
- ./runtime/project-a:/app/runtime
47+
healthcheck:
48+
test: ["CMD", "wget", "-qO-", "http://localhost:8787/health"]
49+
interval: 30s
50+
timeout: 5s
51+
retries: 3
52+
start_period: 10s
53+
54+
memorycore-project-b:
55+
build: .
56+
container_name: memorycore-project-b
57+
restart: unless-stopped
58+
ports:
59+
- "8789:8787"
60+
environment:
61+
- NODE_ENV=production
62+
- OPENCLAW_HOST=0.0.0.0
63+
- OPENCLAW_PORT=8787
64+
- OPENCLAW_INSTANCE=project-b
65+
- OPENCLAW_RUNTIME_DIR=/app/runtime
66+
- OPENCLAW_DB_PATH=/app/runtime/openclaw.db
67+
- OPENCLAW_DEFAULT_SCOPE=project
68+
- OPENCLAW_ALLOWED_SCOPE_PREFIXES=project,project-b
69+
- OPENCLAW_API_KEY=${OPENCLAW_API_KEY}
70+
- OPENCLAW_CORS_ORIGIN=${OPENCLAW_CORS_ORIGIN:-*}
71+
volumes:
72+
- ./runtime/project-b:/app/runtime
73+
healthcheck:
74+
test: ["CMD", "wget", "-qO-", "http://localhost:8787/health"]
75+
interval: 30s
76+
timeout: 5s
77+
retries: 3
78+
start_period: 10s

hybrid-setup.md

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
# Hybrid Setup Guide (Central + Project Instances)
2+
3+
This setup gives you:
4+
- One central memory instance for user-level facts/preferences.
5+
- One isolated memory instance per project for project context.
6+
7+
## Topology
8+
9+
```bash
10+
~/memory-core/ # central instance on 8787 (preferences, identity, facts)
11+
project-a/ # project-specific instance on 8788 (project scopes only)
12+
project-b/ # project-specific instance on 8789 (project scopes only)
13+
```
14+
15+
## 1) Start the central memory instance
16+
17+
From this repository:
18+
19+
```bash
20+
npm run dev:central
21+
```
22+
23+
Central defaults:
24+
- `OPENCLAW_PORT=8787`
25+
- `OPENCLAW_RUNTIME_DIR=~/memory-core/runtime`
26+
- `OPENCLAW_ALLOWED_SCOPE_PREFIXES=preferences,identity,facts`
27+
28+
## 2) Start project instances
29+
30+
From this repository:
31+
32+
```bash
33+
npm run dev:project-a
34+
npm run dev:project-b
35+
```
36+
37+
Project defaults:
38+
- `project-a` runs on `8788` with runtime at `./runtime/project-a`
39+
- `project-b` runs on `8789` with runtime at `./runtime/project-b`
40+
- Both enforce project-only scopes via:
41+
- `OPENCLAW_DEFAULT_SCOPE=project`
42+
- `OPENCLAW_ALLOWED_SCOPE_PREFIXES=project,<project-name>`
43+
44+
### Docker alternative
45+
46+
```bash
47+
docker compose -f docker-compose.hybrid.yml up -d
48+
```
49+
50+
## 3) Verify each instance
51+
52+
```bash
53+
curl http://localhost:8787/health
54+
curl http://localhost:8788/health
55+
curl http://localhost:8789/health
56+
```
57+
58+
Each health response includes:
59+
- `instance_name`
60+
- `default_scope`
61+
- `allowed_scope_prefixes`
62+
63+
## 4) MCP configuration per project
64+
65+
Build once first:
66+
67+
```bash
68+
npm run build
69+
```
70+
71+
### Central MCP server
72+
73+
```json
74+
{
75+
"mcpServers": {
76+
"memorycore-central": {
77+
"command": "node",
78+
"args": ["dist/src/mcp.js"],
79+
"cwd": "/path/to/Project-AI-MemoryCore",
80+
"env": {
81+
"OPENCLAW_INSTANCE": "central",
82+
"OPENCLAW_RUNTIME_DIR": "/home/you/memory-core/runtime",
83+
"OPENCLAW_DB_PATH": "/home/you/memory-core/runtime/openclaw.db",
84+
"OPENCLAW_DEFAULT_SCOPE": "preferences",
85+
"OPENCLAW_ALLOWED_SCOPE_PREFIXES": "preferences,identity,facts"
86+
}
87+
}
88+
}
89+
}
90+
```
91+
92+
### Project A MCP server
93+
94+
```json
95+
{
96+
"mcpServers": {
97+
"memorycore-project-a": {
98+
"command": "node",
99+
"args": ["dist/src/mcp.js"],
100+
"cwd": "/path/to/Project-AI-MemoryCore",
101+
"env": {
102+
"OPENCLAW_INSTANCE": "project-a",
103+
"OPENCLAW_RUNTIME_DIR": "/path/to/project-a/.memorycore",
104+
"OPENCLAW_DB_PATH": "/path/to/project-a/.memorycore/openclaw.db",
105+
"OPENCLAW_DEFAULT_SCOPE": "project",
106+
"OPENCLAW_ALLOWED_SCOPE_PREFIXES": "project,project-a"
107+
}
108+
}
109+
}
110+
}
111+
```
112+
113+
### Project B MCP server
114+
115+
```json
116+
{
117+
"mcpServers": {
118+
"memorycore-project-b": {
119+
"command": "node",
120+
"args": ["dist/src/mcp.js"],
121+
"cwd": "/path/to/Project-AI-MemoryCore",
122+
"env": {
123+
"OPENCLAW_INSTANCE": "project-b",
124+
"OPENCLAW_RUNTIME_DIR": "/path/to/project-b/.memorycore",
125+
"OPENCLAW_DB_PATH": "/path/to/project-b/.memorycore/openclaw.db",
126+
"OPENCLAW_DEFAULT_SCOPE": "project",
127+
"OPENCLAW_ALLOWED_SCOPE_PREFIXES": "project,project-b"
128+
}
129+
}
130+
}
131+
}
132+
```
133+
134+
## Migration Strategy
135+
136+
1. Start central memory first and store user preferences/facts there.
137+
2. Add project-specific instances and keep project context in those DBs only.
138+
3. In each project workspace, point MCP to that project instance config.
139+
4. Keep central MCP available for cross-project personal memory.

package.json

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,14 @@
2424
"build": "tsc -p tsconfig.json",
2525
"start": "node dist/src/server.js",
2626
"dev": "tsx src/server.ts",
27+
"dev:central": "node scripts/run-instance.mjs --mode http --instance central",
28+
"dev:project-a": "node scripts/run-instance.mjs --mode http --instance project-a",
29+
"dev:project-b": "node scripts/run-instance.mjs --mode http --instance project-b",
2730
"cli": "tsx src/cli.ts",
2831
"mcp": "tsx src/mcp.ts",
32+
"mcp:central": "node scripts/run-instance.mjs --mode mcp --instance central",
33+
"mcp:project-a": "node scripts/run-instance.mjs --mode mcp --instance project-a",
34+
"mcp:project-b": "node scripts/run-instance.mjs --mode mcp --instance project-b",
2935
"test": "npm run build && node --test dist/tests/*.test.js",
3036
"clean": "if exist dist rmdir /s /q dist"
3137
},
@@ -44,4 +50,4 @@
4450
"tsx": "^4.20.6",
4551
"typescript": "^5.9.3"
4652
}
47-
}
53+
}

0 commit comments

Comments
 (0)