metame-cli 1.4.27 → 1.4.29
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 +15 -9
- package/index.js +52 -5
- package/package.json +1 -1
- package/scripts/daemon-claude-engine.js +12 -2
- package/scripts/daemon-task-scheduler.js +11 -2
- package/scripts/daemon.js +3 -0
package/README.md
CHANGED
|
@@ -32,7 +32,8 @@ irm https://raw.githubusercontent.com/Yaron9/MetaMe/main/install.ps1 | iex
|
|
|
32
32
|
|
|
33
33
|
**Already have Node.js ≥ 18 (any platform):**
|
|
34
34
|
```bash
|
|
35
|
-
npm install -g metame-cli
|
|
35
|
+
npm install -g metame-cli
|
|
36
|
+
metame
|
|
36
37
|
```
|
|
37
38
|
|
|
38
39
|
---
|
|
@@ -210,17 +211,22 @@ irm https://raw.githubusercontent.com/Yaron9/MetaMe/main/install.ps1 | iex
|
|
|
210
211
|
|
|
211
212
|
**Already have Node.js ≥ 18 (any platform):**
|
|
212
213
|
```bash
|
|
213
|
-
npm install -g metame-cli
|
|
214
|
+
npm install -g metame-cli
|
|
215
|
+
metame
|
|
214
216
|
```
|
|
215
217
|
|
|
216
|
-
**3 minutes
|
|
218
|
+
**Setup guide (3 minutes):**
|
|
217
219
|
|
|
218
|
-
| Step |
|
|
219
|
-
|
|
220
|
-
| 1.
|
|
221
|
-
| 2.
|
|
222
|
-
| 3.
|
|
223
|
-
| 4.
|
|
220
|
+
| Step | What to do | What happens |
|
|
221
|
+
|------|-----------|-------------|
|
|
222
|
+
| 1. Log in to Claude | Run `claude` and complete the login (Anthropic account or API key) | Claude Code is ready to use |
|
|
223
|
+
| 2. Launch MetaMe | Run `metame` | Opens a Claude session with MetaMe loaded |
|
|
224
|
+
| 3. Cognitive interview | Just chat — MetaMe will automatically start a deep interview on first run | Builds `~/.claude_profile.yaml` (your digital twin's brain) |
|
|
225
|
+
| 4. Connect phone | Say "help me set up mobile access" or "connect my phone" | Interactive wizard for Telegram/Feishu bot setup → `~/.metame/daemon.yaml` |
|
|
226
|
+
| 5. Start daemon | `metame start` | Background daemon launches, bot goes online |
|
|
227
|
+
| 6. Register with system | macOS: `metame daemon install-launchd` · Linux: see below | Always-on, crash recovery |
|
|
228
|
+
|
|
229
|
+
> **First time?** Just run `metame` and talk naturally. The interview and setup are conversational — no commands to memorize.
|
|
224
230
|
|
|
225
231
|
> **What does system registration mean?**
|
|
226
232
|
> Once registered, MetaMe runs in the background automatically — screen locked, lid closed, woken from sleep — as long as the machine is on. Scheduled tasks fire on time. No terminal window needed.
|
package/index.js
CHANGED
|
@@ -1,10 +1,30 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
+
// Suppress Node.js experimental warnings (e.g. SQLite)
|
|
4
|
+
process.removeAllListeners('warning');
|
|
5
|
+
|
|
3
6
|
const fs = require('fs');
|
|
4
7
|
const path = require('path');
|
|
5
8
|
const os = require('os');
|
|
6
9
|
const { spawn, execSync } = require('child_process');
|
|
7
10
|
|
|
11
|
+
// On Windows, resolve the full path to claude.cmd so we can spawn it
|
|
12
|
+
// via cmd.exe (using COMSPEC) without relying on shell:true finding cmd.exe in PATH
|
|
13
|
+
function resolveClaudeBin() {
|
|
14
|
+
if (process.platform !== 'win32') return 'claude';
|
|
15
|
+
try {
|
|
16
|
+
return execSync('where claude', { encoding: 'utf8' }).trim().split('\n')[0];
|
|
17
|
+
} catch { return 'claude'; }
|
|
18
|
+
}
|
|
19
|
+
function spawnClaude(args, options) {
|
|
20
|
+
if (process.platform === 'win32') {
|
|
21
|
+
const claudePath = resolveClaudeBin();
|
|
22
|
+
const comspec = process.env.COMSPEC || 'C:\\WINDOWS\\system32\\cmd.exe';
|
|
23
|
+
return spawn(comspec, ['/c', `"${claudePath}"`, ...args], options);
|
|
24
|
+
}
|
|
25
|
+
return spawn('claude', args, options);
|
|
26
|
+
}
|
|
27
|
+
|
|
8
28
|
// ---------------------------------------------------------
|
|
9
29
|
// 1. CONFIGURATION
|
|
10
30
|
// ---------------------------------------------------------
|
|
@@ -751,7 +771,8 @@ try {
|
|
|
751
771
|
|
|
752
772
|
|
|
753
773
|
|
|
754
|
-
|
|
774
|
+
const pkgVersion = require('./package.json').version;
|
|
775
|
+
console.log(`🔮 MetaMe v${pkgVersion}: Link Established.`);
|
|
755
776
|
|
|
756
777
|
// Memory system status — show live stats without blocking launch
|
|
757
778
|
try {
|
|
@@ -1574,6 +1595,7 @@ WantedBy=default.target
|
|
|
1574
1595
|
const bg = spawn(cmd, args, {
|
|
1575
1596
|
detached: true,
|
|
1576
1597
|
stdio: 'ignore',
|
|
1598
|
+
windowsHide: true,
|
|
1577
1599
|
env: { ...process.env, HOME: HOME_DIR, METAME_ROOT: __dirname },
|
|
1578
1600
|
});
|
|
1579
1601
|
bg.unref();
|
|
@@ -1755,9 +1777,8 @@ if (isSync) {
|
|
|
1755
1777
|
const providerEnv = (() => { try { return require(path.join(__dirname, 'scripts', 'providers.js')).buildActiveEnv(); } catch { return {}; } })();
|
|
1756
1778
|
const resumeArgs = ['--resume', bestSession.id];
|
|
1757
1779
|
if (daemonCfg.dangerously_skip_permissions) resumeArgs.push('--dangerously-skip-permissions');
|
|
1758
|
-
const syncChild =
|
|
1780
|
+
const syncChild = spawnClaude(resumeArgs, {
|
|
1759
1781
|
stdio: 'inherit',
|
|
1760
|
-
shell: process.platform === 'win32',
|
|
1761
1782
|
env: { ...process.env, ...providerEnv, METAME_ACTIVE_SESSION: 'true' }
|
|
1762
1783
|
});
|
|
1763
1784
|
syncChild.on('error', () => {
|
|
@@ -1830,10 +1851,36 @@ try {
|
|
|
1830
1851
|
memory.close();
|
|
1831
1852
|
} catch { /* memory not available, non-fatal */ }
|
|
1832
1853
|
|
|
1854
|
+
// Auto-start daemon if config exists but daemon is not running
|
|
1855
|
+
try {
|
|
1856
|
+
if (fs.existsSync(DAEMON_CONFIG) && fs.existsSync(DAEMON_SCRIPT)) {
|
|
1857
|
+
let daemonRunning = false;
|
|
1858
|
+
if (fs.existsSync(DAEMON_PID)) {
|
|
1859
|
+
try {
|
|
1860
|
+
const pid = parseInt(fs.readFileSync(DAEMON_PID, 'utf8').trim(), 10);
|
|
1861
|
+
process.kill(pid, 0); // signal 0 = check if alive
|
|
1862
|
+
daemonRunning = true;
|
|
1863
|
+
} catch { /* PID file stale, daemon not running */ }
|
|
1864
|
+
}
|
|
1865
|
+
if (!daemonRunning) {
|
|
1866
|
+
const isNotWindows = process.platform !== 'win32';
|
|
1867
|
+
const dCmd = isNotWindows ? 'caffeinate' : process.execPath;
|
|
1868
|
+
const dArgs = isNotWindows ? ['-i', process.execPath, DAEMON_SCRIPT] : [DAEMON_SCRIPT];
|
|
1869
|
+
const bg = spawn(dCmd, dArgs, {
|
|
1870
|
+
detached: true,
|
|
1871
|
+
stdio: 'ignore',
|
|
1872
|
+
windowsHide: true,
|
|
1873
|
+
env: { ...process.env, HOME: HOME_DIR, METAME_ROOT: __dirname },
|
|
1874
|
+
});
|
|
1875
|
+
bg.unref();
|
|
1876
|
+
console.log(`🤖 Daemon auto-started (PID: ${bg.pid})`);
|
|
1877
|
+
}
|
|
1878
|
+
}
|
|
1879
|
+
} catch { /* non-fatal */ }
|
|
1880
|
+
|
|
1833
1881
|
// Spawn the official claude tool with our marker + provider env
|
|
1834
|
-
const child =
|
|
1882
|
+
const child = spawnClaude(launchArgs, {
|
|
1835
1883
|
stdio: 'inherit',
|
|
1836
|
-
shell: process.platform === 'win32',
|
|
1837
1884
|
env: { ...process.env, ...activeProviderEnv, METAME_ACTIVE_SESSION: 'true' }
|
|
1838
1885
|
});
|
|
1839
1886
|
|
package/package.json
CHANGED
|
@@ -6,7 +6,7 @@ function createClaudeEngine(deps) {
|
|
|
6
6
|
const {
|
|
7
7
|
fs,
|
|
8
8
|
path,
|
|
9
|
-
spawn,
|
|
9
|
+
spawn: _spawn,
|
|
10
10
|
CLAUDE_BIN,
|
|
11
11
|
HOME,
|
|
12
12
|
CONFIG_FILE,
|
|
@@ -41,6 +41,16 @@ function createClaudeEngine(deps) {
|
|
|
41
41
|
statusThrottleMs = 3000,
|
|
42
42
|
fallbackThrottleMs = 8000,
|
|
43
43
|
} = deps;
|
|
44
|
+
|
|
45
|
+
// On Windows, spawn claude.cmd via COMSPEC instead of shell:true
|
|
46
|
+
function spawn(cmd, args, options) {
|
|
47
|
+
if (process.platform === 'win32' && cmd === CLAUDE_BIN) {
|
|
48
|
+
const comspec = process.env.COMSPEC || 'C:\\WINDOWS\\system32\\cmd.exe';
|
|
49
|
+
return _spawn(comspec, ['/c', `"${cmd}"`, ...args], options);
|
|
50
|
+
}
|
|
51
|
+
return _spawn(cmd, args, options);
|
|
52
|
+
}
|
|
53
|
+
|
|
44
54
|
const SESSION_CWD_VALIDATION_TTL_MS = 30 * 1000;
|
|
45
55
|
const _sessionCwdValidationCache = new Map(); // key: `${sessionId}@@${cwd}` -> { inCwd, ts }
|
|
46
56
|
|
|
@@ -320,7 +330,7 @@ Reply with ONLY the name, nothing else. Examples: 插件开发, API重构, Bug
|
|
|
320
330
|
const child = spawn(CLAUDE_BIN, streamArgs, {
|
|
321
331
|
cwd,
|
|
322
332
|
stdio: ['pipe', 'pipe', 'pipe'],
|
|
323
|
-
detached:
|
|
333
|
+
detached: process.platform !== 'win32', // process groups are POSIX-only
|
|
324
334
|
env: {
|
|
325
335
|
...process.env,
|
|
326
336
|
...getActiveProviderEnv(),
|
|
@@ -161,7 +161,7 @@ function createTaskScheduler(deps) {
|
|
|
161
161
|
path,
|
|
162
162
|
HOME,
|
|
163
163
|
CLAUDE_BIN,
|
|
164
|
-
spawn,
|
|
164
|
+
spawn: _spawn,
|
|
165
165
|
execSync,
|
|
166
166
|
execFileSync,
|
|
167
167
|
parseInterval,
|
|
@@ -180,6 +180,15 @@ function createTaskScheduler(deps) {
|
|
|
180
180
|
skillEvolution,
|
|
181
181
|
} = deps;
|
|
182
182
|
|
|
183
|
+
// On Windows, spawn claude.cmd via COMSPEC instead of shell:true
|
|
184
|
+
function spawn(cmd, args, options) {
|
|
185
|
+
if (process.platform === 'win32' && cmd === CLAUDE_BIN) {
|
|
186
|
+
const comspec = process.env.COMSPEC || 'C:\\WINDOWS\\system32\\cmd.exe';
|
|
187
|
+
return _spawn(comspec, ['/c', `"${cmd}"`, ...args], options);
|
|
188
|
+
}
|
|
189
|
+
return _spawn(cmd, args, options);
|
|
190
|
+
}
|
|
191
|
+
|
|
183
192
|
function checkPrecondition(task) {
|
|
184
193
|
if (!task.precondition) return { pass: true, context: '' };
|
|
185
194
|
|
|
@@ -403,7 +412,7 @@ function createTaskScheduler(deps) {
|
|
|
403
412
|
const child = spawn(CLAUDE_BIN, asyncArgs, {
|
|
404
413
|
cwd: cwd || undefined,
|
|
405
414
|
stdio: ['pipe', 'pipe', 'pipe'],
|
|
406
|
-
detached:
|
|
415
|
+
detached: process.platform !== 'win32', // process groups are POSIX-only
|
|
407
416
|
env: asyncEnv,
|
|
408
417
|
});
|
|
409
418
|
|