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 CHANGED
@@ -215,14 +215,23 @@ npm install -g metame-cli
215
215
  metame
216
216
  ```
217
217
 
218
- **3 minutes to full setup:**
219
-
220
- | Step | Command | What happens |
221
- |------|---------|-------------|
222
- | 1. Install & profile | `metame` | First run: cognitive interview builds `~/.claude_profile.yaml` |
223
- | 2. Connect phone | Follow the setup wizard | Bot token + app credentials `~/.metame/daemon.yaml` |
224
- | 3. Start daemon | `metame start` | Background daemon launches, bot goes online |
225
- | 4. Register with system | macOS: `metame daemon install-launchd` · Linux: see below | Always-on, crash recovery |
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("🔮 MetaMe: Link Established.");
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 = require('./package.json').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} 可用(当前 ${CURRENT_VERSION}),正在自动更新...`);
854
+ console.log(`📦 MetaMe ${latest} available (current ${CURRENT_VERSION}), updating...`);
831
855
  const { execSync } = require('child_process');
832
856
  try {
833
- execSync('npm update -g metame-cli', { stdio: 'pipe', timeout: 30000 });
834
- console.log(`✅ 已更新到 ${latest},下次启动生效。`);
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
- console.log(`⚠️ 自动更新失败,请手动执行: npm update -g metame-cli`);
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 = spawn('claude', resumeArgs, {
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 = spawn('claude', launchArgs, {
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "metame-cli",
3
- "version": "1.4.28",
3
+ "version": "1.4.30",
4
4
  "description": "The Cognitive Profile Layer for Claude Code. Knows how you think, not just what you said.",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -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
  });