tabclaude-host 0.1.0 → 0.1.1

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/claude-client.js CHANGED
@@ -1,25 +1,37 @@
1
- import { execFile } from "node:child_process";
1
+ import { spawn } from "node:child_process";
2
2
  import { stderr } from "node:process";
3
3
 
4
4
  const claudeBin = process.env.CLAUDE_PATH || "claude";
5
- const CLAUDE_TIMEOUT = 30000;
5
+ const CLAUDE_TIMEOUT = 600000;
6
6
 
7
7
  function runClaude(prompt) {
8
8
  return new Promise((resolve, reject) => {
9
- const child = execFile(
10
- claudeBin,
11
- ["--print", "--", prompt],
12
- { timeout: CLAUDE_TIMEOUT, maxBuffer: 1024 * 1024 },
13
- (err, stdoutData, stderrData) => {
14
- if (err) {
15
- if (stderrData) stderr.write(`claude stderr: ${stderrData}\n`);
16
- reject(new Error(`Claude CLI failed: ${err.message}`));
17
- return;
18
- }
19
- resolve(stdoutData.trim());
20
- },
21
- );
22
- // Close stdin so claude CLI doesn't wait for input
9
+ const child = spawn(claudeBin, ["--print"], {
10
+ env: process.env,
11
+ timeout: CLAUDE_TIMEOUT,
12
+ });
13
+
14
+ let stdoutData = "";
15
+ let stderrData = "";
16
+
17
+ child.stdout.on("data", (data) => { stdoutData += data; });
18
+ child.stderr.on("data", (data) => { stderrData += data; });
19
+
20
+ child.on("error", (err) => {
21
+ reject(new Error(`Claude spawn error: ${err.message}`));
22
+ });
23
+
24
+ child.on("close", (code) => {
25
+ if (code !== 0) {
26
+ if (stderrData) stderr.write(`claude stderr: ${stderrData}\n`);
27
+ reject(new Error(`Claude CLI exited with code ${code}`));
28
+ return;
29
+ }
30
+ resolve(stdoutData.trim());
31
+ });
32
+
33
+ // Send prompt via stdin (not as CLI arg) — required for auth env to work
34
+ child.stdin.write(prompt);
23
35
  child.stdin.end();
24
36
  });
25
37
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tabclaude-host",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Tabclaude Native Messaging Host with Claude CLI integration",
5
5
  "author": "Brady",
6
6
  "license": "MIT",
package/scripts/setup.js CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import { writeFileSync, mkdirSync, chmodSync, existsSync } from "node:fs";
3
+ import { writeFileSync, mkdirSync, chmodSync, existsSync, realpathSync } from "node:fs";
4
4
  import { dirname, join, resolve } from "node:path";
5
5
  import { fileURLToPath } from "node:url";
6
6
  import { platform, homedir } from "node:os";
@@ -8,24 +8,42 @@ import { execSync } from "node:child_process";
8
8
 
9
9
  const HOST_NAME = "com.tabclaude.host";
10
10
 
11
+ // Returns true if the path resolves (via symlinks) to a .js file — not a real binary
12
+ function isJsWrapper(p) {
13
+ try {
14
+ return realpathSync(p).endsWith(".js");
15
+ } catch {
16
+ return false;
17
+ }
18
+ }
19
+
11
20
  function findClaude() {
21
+ const candidates = [];
22
+
12
23
  // 1. which claude
13
24
  try {
14
25
  const p = execSync("which claude", { encoding: "utf-8" }).trim();
15
- if (p) return p;
26
+ if (p) candidates.push(p);
16
27
  } catch {}
17
28
 
18
- // 2. sibling of node
19
- const sibling = join(dirname(process.execPath), "claude");
20
- if (existsSync(sibling)) return sibling;
29
+ // 2. sibling of node binary
30
+ candidates.push(join(dirname(process.execPath), "claude"));
21
31
 
22
- // 3. /usr/local/bin/claude
23
- if (existsSync("/usr/local/bin/claude")) return "/usr/local/bin/claude";
32
+ // 3. common paths
33
+ candidates.push(
34
+ "/usr/local/bin/claude",
35
+ "/opt/homebrew/bin/claude",
36
+ );
24
37
 
25
- // 4. /opt/homebrew/bin/claude
26
- if (existsSync("/opt/homebrew/bin/claude")) return "/opt/homebrew/bin/claude";
38
+ // Prefer real binaries over JS wrappers (e.g. npm-installed symlinks to cli.js)
39
+ for (const p of candidates) {
40
+ if (existsSync(p) && !isJsWrapper(p)) return p;
41
+ }
42
+ // Fall back to JS wrappers if no real binary found
43
+ for (const p of candidates) {
44
+ if (existsSync(p)) return p;
45
+ }
27
46
 
28
- // 5. fallback
29
47
  console.warn(
30
48
  `[${HOST_NAME}] WARNING: Claude CLI not found. Install it and ensure it's in PATH.`
31
49
  );