metame-cli 1.4.33 → 1.4.34
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +50 -25
- package/package.json +1 -1
- package/scripts/daemon-claude-engine.js +6 -29
- package/scripts/daemon-task-scheduler.js +33 -4
package/README.md
CHANGED
|
@@ -24,7 +24,7 @@ No cloud. Your machine, your data.
|
|
|
24
24
|
curl -fsSL https://raw.githubusercontent.com/Yaron9/MetaMe/main/install.sh | bash
|
|
25
25
|
```
|
|
26
26
|
|
|
27
|
-
**Already have Node.js ≥
|
|
27
|
+
**Already have Node.js ≥ 22.5:**
|
|
28
28
|
```bash
|
|
29
29
|
npm install -g metame-cli
|
|
30
30
|
metame
|
|
@@ -38,13 +38,15 @@ metame
|
|
|
38
38
|
|
|
39
39
|
---
|
|
40
40
|
|
|
41
|
-
> ### 🚀 v1.4.
|
|
41
|
+
> ### 🚀 v1.4.33 — 6-Dimension Soul Schema + Nightly Reflection + Auto-Provisioning
|
|
42
42
|
>
|
|
43
|
-
> - **
|
|
44
|
-
> - **
|
|
45
|
-
> - **
|
|
46
|
-
> - **
|
|
47
|
-
> - **
|
|
43
|
+
> - **6-dimension soul schema**: cognitive profile upgraded from key-value pairs to a structured 67-field model covering Values, Drive, Cognition Style, Stress & Shadow, Relational, and Identity Narrative — with tier-based lock protection.
|
|
44
|
+
> - **Nightly reflection**: every night, hot-zone facts are distilled into searchable decision logs and lessons learned.
|
|
45
|
+
> - **Memory index**: auto-generated global index of all memory documents for instant retrieval.
|
|
46
|
+
> - **Auto-provisioning**: first run automatically deploys default CLAUDE.md, docs, and `dispatch_to` — zero manual setup.
|
|
47
|
+
> - **Token budget tracking**: daily token usage monitoring with per-category breakdown and 80% warning threshold.
|
|
48
|
+
> - **Multi-user ACL**: role-based permissions (admin / member / stranger) with binding protection.
|
|
49
|
+
> - **Windows native support**: cross-platform path handling, Named Pipes IPC, GBK-safe encoding.
|
|
48
50
|
>
|
|
49
51
|
> Zero configuration. It just works.
|
|
50
52
|
|
|
@@ -56,7 +58,9 @@ metame
|
|
|
56
58
|
|
|
57
59
|
Claude Code forgets you every time you switch folders. MetaMe doesn't.
|
|
58
60
|
|
|
59
|
-
A cognitive profile (`~/.claude_profile.yaml`) follows you everywhere — not just facts like "user prefers TypeScript", but *how you think
|
|
61
|
+
A cognitive profile (`~/.claude_profile.yaml`) follows you everywhere — not just facts like "user prefers TypeScript", but *how you think*. The profile is built on a **6-dimension soul schema**: Values, Drive, Cognition Style, Stress & Shadow, Relational, and Identity Narrative — 67 fields organized into 4 tiers (T1 locked identity → T5 system-managed evolution). First-time users go through a **Genesis Interview**: a structured deep conversation that builds your cognitive fingerprint from scratch.
|
|
62
|
+
|
|
63
|
+
Once established, the profile updates silently from your conversations via background distillation — no effort required.
|
|
60
64
|
|
|
61
65
|
```
|
|
62
66
|
$ metame
|
|
@@ -80,7 +84,7 @@ Start on your laptop, continue on the train. `/stop` to interrupt, `/undo` to ro
|
|
|
80
84
|
|
|
81
85
|
### 3. Layered Memory That Works While You Sleep
|
|
82
86
|
|
|
83
|
-
MetaMe's memory system runs automatically in the background — no prompts, no manual saves.
|
|
87
|
+
MetaMe's memory system runs automatically in the background — no prompts, no manual saves. Five layers, fully autonomous.
|
|
84
88
|
|
|
85
89
|
**Layer 1 — Long-term Facts**
|
|
86
90
|
When you go idle, MetaMe runs memory consolidation: extracts key decisions, patterns, and knowledge from your sessions into a persistent facts store. These are semantically recalled on every session start.
|
|
@@ -91,12 +95,20 @@ Resuming a conversation after 2+ hours? MetaMe injects a brief summary of what y
|
|
|
91
95
|
**Layer 3 — Session Index**
|
|
92
96
|
Every session gets tagged with topics and intent. This powers future session routing: when you reference "that thing we worked on last week", MetaMe knows where to look.
|
|
93
97
|
|
|
98
|
+
**Layer 4 — Nightly Reflection**
|
|
99
|
+
Every night at 01:00, MetaMe reviews your most-accessed facts from the past week and distills them into high-level decision logs and operational lessons — searchable documents that grow your personal knowledge base over time.
|
|
100
|
+
|
|
101
|
+
**Layer 5 — Memory Index**
|
|
102
|
+
At 01:30, an auto-generated global index (`INDEX.md`) maps every memory document across all categories. This serves as a fast lookup table so MetaMe always knows where to find relevant context.
|
|
103
|
+
|
|
94
104
|
```
|
|
95
105
|
[Background, while you sleep]
|
|
96
106
|
idle 30min → memory consolidation triggered
|
|
97
107
|
→ session_tags.json updated (topics indexed)
|
|
98
108
|
→ facts extracted → ~/.metame/memory.db
|
|
99
109
|
→ session summary cached → daemon_state.json
|
|
110
|
+
01:00 → nightly reflection: hot facts → decisions + lessons
|
|
111
|
+
01:30 → memory index regenerated
|
|
100
112
|
|
|
101
113
|
[Next morning, when you resume]
|
|
102
114
|
"continue from yesterday" →
|
|
@@ -117,12 +129,14 @@ Built into the daemon. Runs every 60 seconds regardless of what's in your config
|
|
|
117
129
|
- Detects when you go idle → generates session continuity summaries
|
|
118
130
|
|
|
119
131
|
**Layer 1 — System Evolution (built-in defaults)**
|
|
120
|
-
|
|
132
|
+
Five tasks shipped out of the box. They are precondition-gated and run only when useful:
|
|
121
133
|
|
|
122
134
|
```yaml
|
|
123
135
|
- cognitive-distill # 4h · has signals? → distill preferences into profile
|
|
124
136
|
- memory-extract # 4h · scan sessions → extract long-term facts + topic tags
|
|
125
137
|
- skill-evolve # 6h · has signals? → evolve skills from task outcomes
|
|
138
|
+
- nightly-reflect # 01:00 daily · hot facts → decision logs + lessons learned
|
|
139
|
+
- memory-index # 01:30 daily · regenerate global memory index
|
|
126
140
|
```
|
|
127
141
|
|
|
128
142
|
`precondition` guards mean zero tokens burned when there's nothing to process.
|
|
@@ -203,19 +217,21 @@ Task fails → skill-scout finds a skill → installs → retries → succeeds
|
|
|
203
217
|
curl -fsSL https://raw.githubusercontent.com/Yaron9/MetaMe/main/install.sh | bash
|
|
204
218
|
```
|
|
205
219
|
|
|
206
|
-
**Already have Node.js ≥
|
|
220
|
+
**Already have Node.js ≥ 22.5:**
|
|
207
221
|
```bash
|
|
208
222
|
npm install -g metame-cli
|
|
209
223
|
metame
|
|
210
224
|
```
|
|
211
225
|
|
|
226
|
+
> **First run auto-provisioning:** MetaMe automatically deploys a default `CLAUDE.md`, documentation files, and the `dispatch_to` tool to `~/.metame/`. No manual setup needed.
|
|
227
|
+
|
|
212
228
|
**Setup guide (3 minutes):**
|
|
213
229
|
|
|
214
230
|
| Step | What to do | What happens |
|
|
215
231
|
|------|-----------|-------------|
|
|
216
232
|
| 1. Log in to Claude | Run `claude` and complete the login (Anthropic account or API key) | Claude Code is ready to use |
|
|
217
233
|
| 2. Launch MetaMe | Run `metame` | Opens a Claude session with MetaMe loaded |
|
|
218
|
-
| 3.
|
|
234
|
+
| 3. Genesis Interview | Just chat — MetaMe will automatically start a deep soul interview on first run | Builds `~/.claude_profile.yaml` (6-dimension cognitive profile) |
|
|
219
235
|
| 4. Connect phone | Say "help me set up mobile access" or "connect my phone" | Interactive wizard for Telegram/Feishu bot setup → `~/.metame/daemon.yaml` |
|
|
220
236
|
| 5. Start daemon | `metame start` | Background daemon launches, bot goes online |
|
|
221
237
|
| 6. Register with system | macOS: `metame daemon install-launchd` · Windows: `metame daemon install-task-scheduler` · Linux: see below | Always-on, crash recovery |
|
|
@@ -281,11 +297,13 @@ systemctl --user start metame
|
|
|
281
297
|
|
|
282
298
|
| Capability | What It Does |
|
|
283
299
|
|-----------|-------------|
|
|
284
|
-
| **Cognitive Profile** |
|
|
285
|
-
| **Layered Memory** |
|
|
300
|
+
| **Cognitive Profile** | 6-dimension soul schema (Values, Drive, Cognition Style, Stress & Shadow, Relational, Identity Narrative). 67 fields, tier-locked, 800-token budget. First-time Genesis Interview builds your profile from scratch. |
|
|
301
|
+
| **Layered Memory** | Five-tier memory: long-term facts (semantic recall), session summaries (continuity bridge), session index (topic tags), nightly reflection (decision/lesson distillation), memory index (global lookup). All automatic. |
|
|
286
302
|
| **Mobile Bridge** | Full Claude Code via Telegram/Feishu. Stateful sessions, file transfer both ways, real-time streaming status. |
|
|
287
303
|
| **Skill Evolution** | Self-healing skill system. Auto-discovers missing skills, learns from browser recordings, evolves after every task. Skills get smarter over time. |
|
|
288
|
-
| **
|
|
304
|
+
| **Token Budget** | Daily token usage tracking with per-category breakdown. Configurable daily limit, automatic 80% warning threshold, usage history with rollover. |
|
|
305
|
+
| **Auto-Provisioning** | First run deploys default CLAUDE.md, documentation, and `dispatch_to` to `~/.metame/`. Subsequent runs sync scripts without overwriting user config. |
|
|
306
|
+
| **Heartbeat System** | Three-layer programmable nervous system. Layer 0 kernel always-on (zero config). Layer 1 system evolution built-in (5 tasks: distill + memory + skills + nightly reflection + memory index). Layer 2 your custom scheduled tasks with `require_idle`, `precondition`, `notify`, workflows. |
|
|
289
307
|
| **Multi-Agent** | Multiple projects with dedicated chat groups. `/agent bind` for one-tap setup. True parallel execution. |
|
|
290
308
|
| **Browser Automation** | Built-in Playwright MCP. Browser control out of the box for every user. |
|
|
291
309
|
| **Cross-Platform** | Native support for macOS and Windows. Platform abstraction layer handles spawn, IPC, process management, and terminal encoding automatically. |
|
|
@@ -429,27 +447,34 @@ All agents share your cognitive profile (`~/.claude_profile.yaml`) — they all
|
|
|
429
447
|
│ └──────────────┘ │
|
|
430
448
|
│ │
|
|
431
449
|
│ ~/.claude_profile │
|
|
432
|
-
│ (
|
|
450
|
+
│ (6-dim soul schema) │
|
|
433
451
|
│ │
|
|
434
452
|
│ ~/.metame/memory.db │
|
|
435
453
|
│ session_tags.json │
|
|
436
|
-
│ (memory
|
|
454
|
+
│ (5-layer memory) │
|
|
455
|
+
│ │
|
|
456
|
+
│ dispatch_to (auto-deployed)│
|
|
437
457
|
└──────────────────────────────┘
|
|
438
458
|
↑
|
|
439
|
-
idle
|
|
440
|
-
|
|
459
|
+
idle → summaries + memory tasks
|
|
460
|
+
01:00 → nightly reflection
|
|
461
|
+
01:30 → memory index rebuild
|
|
441
462
|
```
|
|
442
463
|
|
|
443
|
-
- **Profile** (`~/.claude_profile.yaml`):
|
|
444
|
-
- **Daemon
|
|
445
|
-
- **Distillation
|
|
446
|
-
- **Memory Extract
|
|
447
|
-
- **
|
|
464
|
+
- **Profile** (`~/.claude_profile.yaml`): 6-dimension soul schema. Injected into every Claude session via `CLAUDE.md`.
|
|
465
|
+
- **Daemon**: Background process handling Telegram/Feishu messages, heartbeat tasks, Unix socket dispatch, and idle/sleep transitions.
|
|
466
|
+
- **Distillation**: Heartbeat task (4h, signal-gated) that updates your cognitive profile.
|
|
467
|
+
- **Memory Extract**: Heartbeat task (4h, idle-gated) that extracts long-term facts and session topic tags.
|
|
468
|
+
- **Nightly Reflection**: Daily at 01:00. Distills hot-zone facts into decision logs and operational lessons.
|
|
469
|
+
- **Memory Index**: Daily at 01:30. Regenerates the global memory index for fast retrieval.
|
|
470
|
+
- **Session Summarize**: Generates a brief summary for idle sessions. Injected as context when resuming after a 2h+ gap.
|
|
448
471
|
|
|
449
472
|
## Security
|
|
450
473
|
|
|
451
474
|
- All data stays on your machine. No cloud, no telemetry.
|
|
452
475
|
- `allowed_chat_ids` whitelist — new groups get a smart prompt: if a pending agent activation exists, they're guided to send `/activate`; otherwise they receive setup instructions.
|
|
476
|
+
- **Multi-user ACL**: role-based permissions (admin / member / stranger). Admins manage access via `/user` commands with hot-reload config.
|
|
477
|
+
- **Binding protection**: each group can only be bound to one agent. Existing bindings cannot be overwritten without explicit `force:true`.
|
|
453
478
|
- `operator_ids` for shared groups — non-operators get read-only mode.
|
|
454
479
|
- `~/.metame/` directory is mode 700.
|
|
455
480
|
- Bot tokens stored locally, never transmitted.
|
|
@@ -460,7 +485,7 @@ All agents share your cognitive profile (`~/.claude_profile.yaml`) — they all
|
|
|
460
485
|
|--------|-------|
|
|
461
486
|
| Daemon memory (idle) | ~100 MB RSS — standard Node.js process baseline |
|
|
462
487
|
| Daemon CPU (idle, between heartbeats) | ~0% — event-loop sleeping |
|
|
463
|
-
| Cognitive profile injection | ~
|
|
488
|
+
| Cognitive profile injection | ~800 tokens/session (0.4% of 200k context) |
|
|
464
489
|
| Dispatch latency (Unix socket) | <100ms |
|
|
465
490
|
| Memory consolidation (per session) | ~1,500–2,000 tokens input + ~50–300 tokens output (Haiku) |
|
|
466
491
|
| Session summary (per session) | ~400–900 tokens input + ≤250 tokens output (Haiku) |
|
package/package.json
CHANGED
|
@@ -653,41 +653,18 @@ Reply with ONLY the name, nothing else. Examples: 插件开发, API重构, Bug
|
|
|
653
653
|
}
|
|
654
654
|
|
|
655
655
|
// Skill routing: detect skill first, then decide session
|
|
656
|
-
// BUT: if agent
|
|
657
|
-
|
|
656
|
+
// BUT: skip skill routing if agent addressed by nickname OR chat already has an active session
|
|
657
|
+
// (active conversation should never be hijacked by keyword-based skill matching)
|
|
658
|
+
let session = getSession(chatId);
|
|
659
|
+
const hasActiveSession = session && session.started;
|
|
660
|
+
const skill = (agentMatch || hasActiveSession) ? null : routeSkill(prompt);
|
|
658
661
|
const chatIdStr = String(chatId);
|
|
659
662
|
const chatAgentMap = { ...(config.telegram ? config.telegram.chat_agent_map : {}), ...(config.feishu ? config.feishu.chat_agent_map : {}) };
|
|
660
663
|
const boundProjectKey = chatAgentMap[chatIdStr] || projectKeyFromVirtualChatId(chatIdStr);
|
|
661
664
|
const boundProject = boundProjectKey && config.projects ? config.projects[boundProjectKey] : null;
|
|
662
665
|
const boundCwd = (boundProject && boundProject.cwd) ? normalizeCwd(boundProject.cwd) : null;
|
|
663
666
|
|
|
664
|
-
|
|
665
|
-
const PINNED_SKILL_SESSIONS = new Set(['skill-manager']);
|
|
666
|
-
const usePinnedSkillSession = !!(skill && PINNED_SKILL_SESSIONS.has(skill));
|
|
667
|
-
|
|
668
|
-
let session = getSession(chatId);
|
|
669
|
-
|
|
670
|
-
if (usePinnedSkillSession) {
|
|
671
|
-
// Use a dedicated long-lived session per skill
|
|
672
|
-
const state = loadState();
|
|
673
|
-
if (!state.pinned_sessions) state.pinned_sessions = {};
|
|
674
|
-
const pinned = state.pinned_sessions[skill];
|
|
675
|
-
if (pinned) {
|
|
676
|
-
// Reuse existing pinned session
|
|
677
|
-
state.sessions[chatId] = { id: pinned.id, cwd: pinned.cwd, started: true };
|
|
678
|
-
saveState(state);
|
|
679
|
-
session = state.sessions[chatId];
|
|
680
|
-
log('INFO', `Pinned session reused for skill ${skill}: ${pinned.id.slice(0, 8)}`);
|
|
681
|
-
} else {
|
|
682
|
-
// First time — create session and pin it
|
|
683
|
-
session = createSession(chatId, HOME, skill);
|
|
684
|
-
const st2 = loadState();
|
|
685
|
-
if (!st2.pinned_sessions) st2.pinned_sessions = {};
|
|
686
|
-
st2.pinned_sessions[skill] = { id: session.id, cwd: session.cwd };
|
|
687
|
-
saveState(st2);
|
|
688
|
-
log('INFO', `Pinned session created for skill ${skill}: ${session.id.slice(0, 8)}`);
|
|
689
|
-
}
|
|
690
|
-
} else if (!session) {
|
|
667
|
+
if (!session) {
|
|
691
668
|
if (boundCwd) {
|
|
692
669
|
// Agent-bound chats must stay in their own workspace: never attach to another project's session.
|
|
693
670
|
const recentInBound = listRecentSessions(1, boundCwd);
|
|
@@ -95,6 +95,23 @@ function nextClockRunAfter(schedule, fromMs) {
|
|
|
95
95
|
return baseMs + 24 * 60 * 60 * 1000;
|
|
96
96
|
}
|
|
97
97
|
|
|
98
|
+
// Map short aliases and full model IDs to what Claude CLI accepts.
|
|
99
|
+
// Claude CLI 2.x accepts both 'sonnet' and 'claude-sonnet-4-6'.
|
|
100
|
+
// This normalization keeps daemon.yaml configs forward-compatible.
|
|
101
|
+
const MODEL_ALIASES = {
|
|
102
|
+
haiku: 'claude-haiku-4-5-20251001',
|
|
103
|
+
sonnet: 'claude-sonnet-4-6',
|
|
104
|
+
opus: 'claude-opus-4-6',
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
function normalizeModel(raw) {
|
|
108
|
+
if (!raw || typeof raw !== 'string') return MODEL_ALIASES.haiku;
|
|
109
|
+
const lower = raw.trim().toLowerCase();
|
|
110
|
+
if (Object.prototype.hasOwnProperty.call(MODEL_ALIASES, lower)) return MODEL_ALIASES[lower];
|
|
111
|
+
// Already a full model ID (e.g. 'claude-sonnet-4-6') — pass through
|
|
112
|
+
return raw.trim();
|
|
113
|
+
}
|
|
114
|
+
|
|
98
115
|
function buildTaskSchedule(task, parseInterval) {
|
|
99
116
|
const atRaw = typeof task.at === 'string' ? task.at.trim() : '';
|
|
100
117
|
if (atRaw) {
|
|
@@ -358,7 +375,7 @@ function createTaskScheduler(deps) {
|
|
|
358
375
|
}
|
|
359
376
|
|
|
360
377
|
const preamble = buildProfilePreamble();
|
|
361
|
-
const model = task.model || 'haiku';
|
|
378
|
+
const model = normalizeModel(task.model || 'haiku');
|
|
362
379
|
// If precondition returned context data, append it to the prompt
|
|
363
380
|
let taskPrompt = task.prompt;
|
|
364
381
|
if (precheck.context) {
|
|
@@ -533,7 +550,7 @@ function createTaskScheduler(deps) {
|
|
|
533
550
|
const steps = task.steps || [];
|
|
534
551
|
if (steps.length === 0) return { success: false, error: 'No steps defined', output: '' };
|
|
535
552
|
|
|
536
|
-
const model = task.model || 'sonnet';
|
|
553
|
+
const model = normalizeModel(task.model || 'sonnet');
|
|
537
554
|
const cwd = task.cwd ? task.cwd.replace(/^~/, HOME) : HOME;
|
|
538
555
|
const sessionId = crypto.randomUUID();
|
|
539
556
|
const outputs = [];
|
|
@@ -686,12 +703,24 @@ function createTaskScheduler(deps) {
|
|
|
686
703
|
|
|
687
704
|
if (runningTasks.has(task.name)) {
|
|
688
705
|
// Task is still running; skip this cycle and keep full interval cadence.
|
|
689
|
-
|
|
706
|
+
try {
|
|
707
|
+
nextRun[task.name] = nextRunAfter(schedule, currentTime);
|
|
708
|
+
} catch (schedErr) {
|
|
709
|
+
nextRun[task.name] = currentTime + checkIntervalSec * 2 * 1000;
|
|
710
|
+
log('ERROR', `nextRunAfter (running guard) failed for "${task.name}": ${schedErr.message}`);
|
|
711
|
+
}
|
|
690
712
|
log('WARN', `Task ${task.name} still running — skipping this interval`);
|
|
691
713
|
continue;
|
|
692
714
|
}
|
|
693
715
|
|
|
694
|
-
|
|
716
|
+
try {
|
|
717
|
+
nextRun[task.name] = nextRunAfter(schedule, currentTime);
|
|
718
|
+
} catch (schedErr) {
|
|
719
|
+
// If next-run calculation fails, back off by at least 2 ticks to prevent infinite loop
|
|
720
|
+
nextRun[task.name] = currentTime + checkIntervalSec * 2 * 1000;
|
|
721
|
+
log('ERROR', `nextRunAfter failed for "${task.name}": ${schedErr.message} — backing off`);
|
|
722
|
+
continue;
|
|
723
|
+
}
|
|
695
724
|
runningTasks.add(task.name);
|
|
696
725
|
// executeTask now returns a Promise (async, non-blocking, process-group kill)
|
|
697
726
|
Promise.resolve(executeTask(task, config))
|