metame-cli 1.4.28 → 1.4.30
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 +17 -8
- package/index.js +64 -10
- package/package.json +1 -1
- package/scripts/daemon-claude-engine.js +11 -3
- package/scripts/daemon-task-scheduler.js +10 -2
package/README.md
CHANGED
|
@@ -215,14 +215,23 @@ npm install -g metame-cli
|
|
|
215
215
|
metame
|
|
216
216
|
```
|
|
217
217
|
|
|
218
|
-
**3 minutes
|
|
219
|
-
|
|
220
|
-
| Step |
|
|
221
|
-
|
|
222
|
-
| 1.
|
|
223
|
-
| 2.
|
|
224
|
-
| 3.
|
|
225
|
-
| 4.
|
|
218
|
+
**Setup guide (3 minutes):**
|
|
219
|
+
|
|
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.
|
|
230
|
+
|
|
231
|
+
**Update MetaMe:**
|
|
232
|
+
```bash
|
|
233
|
+
npm install -g metame-cli
|
|
234
|
+
```
|
|
226
235
|
|
|
227
236
|
> **What does system registration mean?**
|
|
228
237
|
> 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
|
@@ -8,6 +8,30 @@ const path = require('path');
|
|
|
8
8
|
const os = require('os');
|
|
9
9
|
const { spawn, execSync } = require('child_process');
|
|
10
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
|
+
|
|
28
|
+
// Quick flags (before heavy init)
|
|
29
|
+
const pkgVersion = require('./package.json').version;
|
|
30
|
+
if (process.argv.includes('-V') || process.argv.includes('--version')) {
|
|
31
|
+
console.log(`metame/${pkgVersion}`);
|
|
32
|
+
process.exit(0);
|
|
33
|
+
}
|
|
34
|
+
|
|
11
35
|
// ---------------------------------------------------------
|
|
12
36
|
// 1. CONFIGURATION
|
|
13
37
|
// ---------------------------------------------------------
|
|
@@ -754,7 +778,7 @@ try {
|
|
|
754
778
|
|
|
755
779
|
|
|
756
780
|
|
|
757
|
-
console.log(
|
|
781
|
+
console.log(`🔮 MetaMe v${pkgVersion}: Link Established.`);
|
|
758
782
|
|
|
759
783
|
// Memory system status — show live stats without blocking launch
|
|
760
784
|
try {
|
|
@@ -810,7 +834,7 @@ try {
|
|
|
810
834
|
// ---------------------------------------------------------
|
|
811
835
|
// 4.9 AUTO-UPDATE CHECK (non-blocking)
|
|
812
836
|
// ---------------------------------------------------------
|
|
813
|
-
const CURRENT_VERSION =
|
|
837
|
+
const CURRENT_VERSION = pkgVersion;
|
|
814
838
|
|
|
815
839
|
// Fire-and-forget: check npm for newer version and auto-update
|
|
816
840
|
(async () => {
|
|
@@ -827,13 +851,18 @@ const CURRENT_VERSION = require('./package.json').version;
|
|
|
827
851
|
});
|
|
828
852
|
|
|
829
853
|
if (latest && latest !== CURRENT_VERSION) {
|
|
830
|
-
console.log(`📦 MetaMe ${latest}
|
|
854
|
+
console.log(`📦 MetaMe ${latest} available (current ${CURRENT_VERSION}), updating...`);
|
|
831
855
|
const { execSync } = require('child_process');
|
|
832
856
|
try {
|
|
833
|
-
execSync('npm
|
|
834
|
-
|
|
857
|
+
execSync('npm install -g metame-cli@latest', {
|
|
858
|
+
stdio: 'pipe',
|
|
859
|
+
timeout: 60000,
|
|
860
|
+
...(process.platform === 'win32' ? { shell: process.env.COMSPEC || true } : {}),
|
|
861
|
+
});
|
|
862
|
+
console.log(`✅ Updated to ${latest}. Restart metame to use the new version.`);
|
|
835
863
|
} catch (e) {
|
|
836
|
-
|
|
864
|
+
const msg = e.stderr ? e.stderr.toString().trim().split('\n').pop() : '';
|
|
865
|
+
console.log(`⚠️ Auto-update failed${msg ? ': ' + msg : ''}. Run manually: npm install -g metame-cli`);
|
|
837
866
|
}
|
|
838
867
|
}
|
|
839
868
|
} catch { /* network unavailable, skip silently */ }
|
|
@@ -1759,9 +1788,8 @@ if (isSync) {
|
|
|
1759
1788
|
const providerEnv = (() => { try { return require(path.join(__dirname, 'scripts', 'providers.js')).buildActiveEnv(); } catch { return {}; } })();
|
|
1760
1789
|
const resumeArgs = ['--resume', bestSession.id];
|
|
1761
1790
|
if (daemonCfg.dangerously_skip_permissions) resumeArgs.push('--dangerously-skip-permissions');
|
|
1762
|
-
const syncChild =
|
|
1791
|
+
const syncChild = spawnClaude(resumeArgs, {
|
|
1763
1792
|
stdio: 'inherit',
|
|
1764
|
-
shell: process.platform === 'win32',
|
|
1765
1793
|
env: { ...process.env, ...providerEnv, METAME_ACTIVE_SESSION: 'true' }
|
|
1766
1794
|
});
|
|
1767
1795
|
syncChild.on('error', () => {
|
|
@@ -1834,10 +1862,36 @@ try {
|
|
|
1834
1862
|
memory.close();
|
|
1835
1863
|
} catch { /* memory not available, non-fatal */ }
|
|
1836
1864
|
|
|
1865
|
+
// Auto-start daemon if config exists but daemon is not running
|
|
1866
|
+
try {
|
|
1867
|
+
if (fs.existsSync(DAEMON_CONFIG) && fs.existsSync(DAEMON_SCRIPT)) {
|
|
1868
|
+
let daemonRunning = false;
|
|
1869
|
+
if (fs.existsSync(DAEMON_PID)) {
|
|
1870
|
+
try {
|
|
1871
|
+
const pid = parseInt(fs.readFileSync(DAEMON_PID, 'utf8').trim(), 10);
|
|
1872
|
+
process.kill(pid, 0); // signal 0 = check if alive
|
|
1873
|
+
daemonRunning = true;
|
|
1874
|
+
} catch { /* PID file stale, daemon not running */ }
|
|
1875
|
+
}
|
|
1876
|
+
if (!daemonRunning) {
|
|
1877
|
+
const isNotWindows = process.platform !== 'win32';
|
|
1878
|
+
const dCmd = isNotWindows ? 'caffeinate' : process.execPath;
|
|
1879
|
+
const dArgs = isNotWindows ? ['-i', process.execPath, DAEMON_SCRIPT] : [DAEMON_SCRIPT];
|
|
1880
|
+
const bg = spawn(dCmd, dArgs, {
|
|
1881
|
+
detached: true,
|
|
1882
|
+
stdio: 'ignore',
|
|
1883
|
+
windowsHide: true,
|
|
1884
|
+
env: { ...process.env, HOME: HOME_DIR, METAME_ROOT: __dirname },
|
|
1885
|
+
});
|
|
1886
|
+
bg.unref();
|
|
1887
|
+
console.log(`🤖 Daemon auto-started (PID: ${bg.pid})`);
|
|
1888
|
+
}
|
|
1889
|
+
}
|
|
1890
|
+
} catch { /* non-fatal */ }
|
|
1891
|
+
|
|
1837
1892
|
// Spawn the official claude tool with our marker + provider env
|
|
1838
|
-
const child =
|
|
1893
|
+
const child = spawnClaude(launchArgs, {
|
|
1839
1894
|
stdio: 'inherit',
|
|
1840
|
-
shell: process.platform === 'win32',
|
|
1841
1895
|
env: { ...process.env, ...activeProviderEnv, METAME_ACTIVE_SESSION: 'true' }
|
|
1842
1896
|
});
|
|
1843
1897
|
|
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
|
|
|
@@ -242,7 +252,6 @@ Reply with ONLY the name, nothing else. Examples: 插件开发, API重构, Bug
|
|
|
242
252
|
const child = spawn(CLAUDE_BIN, args, {
|
|
243
253
|
cwd,
|
|
244
254
|
stdio: ['pipe', 'pipe', 'pipe'],
|
|
245
|
-
shell: process.platform === 'win32',
|
|
246
255
|
env: {
|
|
247
256
|
...process.env,
|
|
248
257
|
...getActiveProviderEnv(),
|
|
@@ -321,7 +330,6 @@ Reply with ONLY the name, nothing else. Examples: 插件开发, API重构, Bug
|
|
|
321
330
|
const child = spawn(CLAUDE_BIN, streamArgs, {
|
|
322
331
|
cwd,
|
|
323
332
|
stdio: ['pipe', 'pipe', 'pipe'],
|
|
324
|
-
shell: process.platform === 'win32',
|
|
325
333
|
detached: process.platform !== 'win32', // process groups are POSIX-only
|
|
326
334
|
env: {
|
|
327
335
|
...process.env,
|
|
@@ -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,6 @@ function createTaskScheduler(deps) {
|
|
|
403
412
|
const child = spawn(CLAUDE_BIN, asyncArgs, {
|
|
404
413
|
cwd: cwd || undefined,
|
|
405
414
|
stdio: ['pipe', 'pipe', 'pipe'],
|
|
406
|
-
shell: process.platform === 'win32',
|
|
407
415
|
detached: process.platform !== 'win32', // process groups are POSIX-only
|
|
408
416
|
env: asyncEnv,
|
|
409
417
|
});
|