metame-cli 1.4.28 → 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 CHANGED
@@ -215,14 +215,18 @@ 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.
226
230
 
227
231
  > **What does system registration mean?**
228
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
@@ -8,6 +8,23 @@ 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
+
11
28
  // ---------------------------------------------------------
12
29
  // 1. CONFIGURATION
13
30
  // ---------------------------------------------------------
@@ -754,7 +771,8 @@ try {
754
771
 
755
772
 
756
773
 
757
- console.log("🔮 MetaMe: Link Established.");
774
+ const pkgVersion = require('./package.json').version;
775
+ console.log(`🔮 MetaMe v${pkgVersion}: Link Established.`);
758
776
 
759
777
  // Memory system status — show live stats without blocking launch
760
778
  try {
@@ -1759,9 +1777,8 @@ if (isSync) {
1759
1777
  const providerEnv = (() => { try { return require(path.join(__dirname, 'scripts', 'providers.js')).buildActiveEnv(); } catch { return {}; } })();
1760
1778
  const resumeArgs = ['--resume', bestSession.id];
1761
1779
  if (daemonCfg.dangerously_skip_permissions) resumeArgs.push('--dangerously-skip-permissions');
1762
- const syncChild = spawn('claude', resumeArgs, {
1780
+ const syncChild = spawnClaude(resumeArgs, {
1763
1781
  stdio: 'inherit',
1764
- shell: process.platform === 'win32',
1765
1782
  env: { ...process.env, ...providerEnv, METAME_ACTIVE_SESSION: 'true' }
1766
1783
  });
1767
1784
  syncChild.on('error', () => {
@@ -1834,10 +1851,36 @@ try {
1834
1851
  memory.close();
1835
1852
  } catch { /* memory not available, non-fatal */ }
1836
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
+
1837
1881
  // Spawn the official claude tool with our marker + provider env
1838
- const child = spawn('claude', launchArgs, {
1882
+ const child = spawnClaude(launchArgs, {
1839
1883
  stdio: 'inherit',
1840
- shell: process.platform === 'win32',
1841
1884
  env: { ...process.env, ...activeProviderEnv, METAME_ACTIVE_SESSION: 'true' }
1842
1885
  });
1843
1886
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "metame-cli",
3
- "version": "1.4.28",
3
+ "version": "1.4.29",
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
  });