claude-phone-local 2.0.4 → 2.0.6

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.
@@ -1,6 +1,50 @@
1
1
  #!/usr/bin/env node
2
- // Friendly next-steps message after `npm install -g claude-phone-local`.
3
- // Never fails the install (package.json calls this with `|| true`).
2
+ // Post-install: installs host-side subpackage dependencies, then prints
3
+ // next-steps. Never fails the parent install (package.json calls this with
4
+ // `|| true`) - a failed subpackage install here just means `claude-phone
5
+ // start`/`claude-phone doctor` will report it later with the exact fix.
6
+ //
7
+ // claude-api-server and mcp-server run directly on the host (not in Docker,
8
+ // unlike voice-app), so npm doesn't install their deps automatically - `npm
9
+ // install -g` only installs the top-level package's own dependencies.
10
+ // Without this, users hit "Dependencies not installed" only when they later
11
+ // run `claude-phone start`, despite the message below promising zero manual
12
+ // steps.
13
+
14
+ import { execFileSync } from 'node:child_process';
15
+ import { existsSync } from 'node:fs';
16
+ import path from 'node:path';
17
+ import { fileURLToPath } from 'node:url';
18
+
19
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
20
+ const packageRoot = path.resolve(__dirname, '..', '..');
21
+
22
+ const HOST_SUBPACKAGES = ['claude-api-server', 'mcp-server'];
23
+
24
+ for (const dir of HOST_SUBPACKAGES) {
25
+ const dirPath = path.join(packageRoot, dir);
26
+ const nodeModulesPath = path.join(dirPath, 'node_modules');
27
+
28
+ if (!existsSync(path.join(dirPath, 'package.json'))) continue;
29
+ if (existsSync(nodeModulesPath)) continue;
30
+
31
+ try {
32
+ console.log(`Installing dependencies for ${dir}...`);
33
+ // npm resolves to npm.cmd (a shell shim) on Windows, so it needs
34
+ // shell:true there to run at all. Node warns when shell:true is combined
35
+ // with an args array (each element gets shell-interpolated); passing a
36
+ // single fixed command string instead avoids that, and there is no user
37
+ // input in this string to make interpolation a real risk.
38
+ execFileSync('npm install --omit=dev', {
39
+ cwd: dirPath,
40
+ stdio: 'inherit',
41
+ shell: true
42
+ });
43
+ } catch (error) {
44
+ console.log(`\x1b[33mWarning: could not install ${dir} dependencies automatically.\x1b[0m`);
45
+ console.log(` Run manually: cd ${dirPath} && npm install\n`);
46
+ }
47
+ }
4
48
 
5
49
  console.log(`
6
50
  \x1b[36m claude-phone-local installed \x1b[0m
package/cli/lib/utils.js CHANGED
@@ -51,11 +51,18 @@ export function getLocalIP() {
51
51
  * @returns {Promise<boolean>}
52
52
  */
53
53
  export async function isClaudeInstalled() {
54
+ // `which` doesn't exist on Windows (it's `where`), and a spawn ENOENT with
55
+ // no 'error' handler crashes the whole process rather than resolving false.
56
+ const lookupCmd = process.platform === 'win32' ? 'where' : 'which';
57
+
54
58
  return new Promise((resolve) => {
55
- const check = spawn('which', ['claude']);
59
+ const check = spawn(lookupCmd, ['claude']);
56
60
  check.on('close', (code) => {
57
61
  resolve(code === 0);
58
62
  });
63
+ check.on('error', () => {
64
+ resolve(false);
65
+ });
59
66
  });
60
67
  }
61
68
 
@@ -5,5 +5,8 @@
5
5
  "type": "module",
6
6
  "bin": {
7
7
  "claude-phone-mcp": "./index.js"
8
+ },
9
+ "dependencies": {
10
+ "@modelcontextprotocol/sdk": "^1.0.0"
8
11
  }
9
12
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-phone-local",
3
- "version": "2.0.4",
3
+ "version": "2.0.6",
4
4
  "description": "Local/offline fork of NetworkChuck's claude-phone: talk to Claude Code over 3CX/SIP with faster-whisper STT + Piper TTS in one Docker container.",
5
5
  "type": "module",
6
6
  "bin": {