ztile-cli 0.2.2 → 0.3.0

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.
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env node
2
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
3
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
4
+ }) : x)(function(x) {
5
+ if (typeof require !== "undefined") return require.apply(this, arguments);
6
+ throw Error('Dynamic require of "' + x + '" is not supported');
7
+ });
8
+
9
+ export {
10
+ __require
11
+ };
@@ -0,0 +1,96 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ __require
4
+ } from "./chunk-PDX44BCA.js";
5
+
6
+ // src/lib/credentials.ts
7
+ import { existsSync, readFileSync, writeFileSync, mkdirSync } from "fs";
8
+ import { join } from "path";
9
+ function credentialsPath() {
10
+ const home = process.env["HOME"] ?? process.env["USERPROFILE"] ?? "/tmp";
11
+ return join(home, ".ztile", "credentials.json");
12
+ }
13
+ function loadCredentials() {
14
+ const path = credentialsPath();
15
+ if (!existsSync(path)) return null;
16
+ try {
17
+ return JSON.parse(readFileSync(path, "utf-8"));
18
+ } catch {
19
+ return null;
20
+ }
21
+ }
22
+ function saveCredentials(creds) {
23
+ const path = credentialsPath();
24
+ const dir = join(path, "..");
25
+ mkdirSync(dir, { recursive: true });
26
+ writeFileSync(path, JSON.stringify(creds, null, 2) + "\n", { mode: 384 });
27
+ }
28
+ function resolveApiKey() {
29
+ const envKey = process.env["ZTILE_API_KEY"];
30
+ if (envKey) return envKey;
31
+ const creds = loadCredentials();
32
+ if (creds?.apiKey) return creds.apiKey;
33
+ return "";
34
+ }
35
+ function resolveServerUrl() {
36
+ const envUrl = process.env["ZTILE_SERVER_URL"];
37
+ if (envUrl) return envUrl;
38
+ const creds = loadCredentials();
39
+ if (creds?.serverUrl) return creds.serverUrl;
40
+ return "https://ztile.dev";
41
+ }
42
+ function resolveMachineId() {
43
+ const envId = process.env["ZTILE_MACHINE_ID"];
44
+ if (envId) return envId;
45
+ const creds = loadCredentials();
46
+ if (creds?.machineId) return creds.machineId;
47
+ return "";
48
+ }
49
+ function pidFilePath() {
50
+ const home = process.env["HOME"] ?? process.env["USERPROFILE"] ?? "/tmp";
51
+ return join(home, ".ztile", "connect.pid");
52
+ }
53
+ function savePid(pid) {
54
+ const path = pidFilePath();
55
+ const dir = join(path, "..");
56
+ mkdirSync(dir, { recursive: true });
57
+ writeFileSync(path, String(pid));
58
+ }
59
+ function loadPid() {
60
+ const path = pidFilePath();
61
+ if (!existsSync(path)) return null;
62
+ try {
63
+ const pid = parseInt(readFileSync(path, "utf-8").trim(), 10);
64
+ return isNaN(pid) ? null : pid;
65
+ } catch {
66
+ return null;
67
+ }
68
+ }
69
+ function removePid() {
70
+ const path = pidFilePath();
71
+ try {
72
+ const { unlinkSync } = __require("fs");
73
+ unlinkSync(path);
74
+ } catch {
75
+ }
76
+ }
77
+ function isProcessRunning(pid) {
78
+ try {
79
+ process.kill(pid, 0);
80
+ return true;
81
+ } catch {
82
+ return false;
83
+ }
84
+ }
85
+
86
+ export {
87
+ loadCredentials,
88
+ saveCredentials,
89
+ resolveApiKey,
90
+ resolveServerUrl,
91
+ resolveMachineId,
92
+ savePid,
93
+ loadPid,
94
+ removePid,
95
+ isProcessRunning
96
+ };
package/dist/cli.js CHANGED
@@ -3,37 +3,53 @@
3
3
  // src/cli.ts
4
4
  var args = process.argv.slice(2);
5
5
  if (args[0] === "hook") {
6
- const { handleHook } = await import("./hook-SN73JWB3.js");
6
+ const { handleHook } = await import("./hook-ZR4EVEUT.js");
7
7
  await handleHook();
8
8
  process.exit(0);
9
9
  }
10
- if (args[0] === "setup") {
11
- const { setupClaudeCode } = await import("./setup-6PUWCUFR.js");
12
- const apiKey = process.env["ZTILE_API_KEY"] ?? findArg(args, "--api-key");
10
+ if (args[0] === "login") {
11
+ const { login } = await import("./login-3IOCLQWW.js");
12
+ await login({
13
+ apiKey: findArg(args, "--api-key"),
14
+ serverUrl: findArg(args, "--server-url"),
15
+ machineId: findArg(args, "--machine-id")
16
+ });
17
+ process.exit(0);
18
+ }
19
+ if (args[0] === "install") {
20
+ const { resolveApiKey } = await import("./credentials-OO2RZFLG.js");
21
+ const apiKey = resolveApiKey();
13
22
  if (!apiKey) {
14
- console.error("Error: API key is required.");
15
- console.error(" Set ZTILE_API_KEY env var, or pass --api-key <key>");
23
+ console.error("Error: Not logged in.");
24
+ console.error(" Run `ztile login` first.");
16
25
  process.exit(1);
17
26
  }
18
- await setupClaudeCode({
19
- apiKey,
20
- serverUrl: process.env["ZTILE_SERVER_URL"] ?? findArg(args, "--server-url"),
21
- machineId: process.env["ZTILE_MACHINE_ID"] ?? findArg(args, "--machine-id"),
22
- project: process.env["ZTILE_PROJECT"] ?? findArg(args, "--project")
23
- });
27
+ const { setupClaudeCode } = await import("./setup-VFHRFRZH.js");
28
+ await setupClaudeCode();
24
29
  process.exit(0);
25
30
  }
26
- if (args[0] === "daemon") {
27
- const { runDaemon } = await import("./daemon-KSDSRNAZ.js");
31
+ if (args[0] === "connect") {
32
+ const { runConnect } = await import("./connect-ZGETP6WZ.js");
28
33
  const projectDir = findArg(args, "--project") ?? process.env["ZTILE_PROJECT"] ?? process.cwd();
29
- await runDaemon(projectDir);
34
+ const daemon = args.includes("--daemon") || args.includes("-d");
35
+ await runConnect({ projectDir, daemon });
36
+ }
37
+ if (args[0] === "disconnect") {
38
+ const { disconnect } = await import("./disconnect-TZ3MQUZS.js");
39
+ disconnect();
40
+ process.exit(0);
30
41
  }
31
- if (args.length === 0 || !["hook", "setup", "daemon"].includes(args[0])) {
42
+ if (args.length === 0 || !["hook", "install", "connect", "disconnect", "login"].includes(args[0])) {
32
43
  if (args.length > 0) console.error(`Unknown command: ${args[0]}`);
33
44
  console.log("Usage:");
34
- console.log(" ztile hook Handle Claude Code hook (stdin \u2192 transcript diff \u2192 server)");
35
- console.log(" ztile setup Configure Claude Code hooks");
36
- console.log(" ztile daemon Start daemon for remote control (poll server for commands)");
45
+ console.log(" ztile login Save API key and server config");
46
+ console.log(" ztile install Configure Claude Code hooks");
47
+ console.log(" ztile connect Connect to dashboard for remote control");
48
+ console.log(" ztile disconnect Stop background connection");
49
+ console.log(" ztile hook Handle Claude Code hook (internal)");
50
+ console.log("");
51
+ console.log("Options:");
52
+ console.log(" ztile connect -d Run in background (daemon mode)");
37
53
  process.exit(args.length > 0 ? 1 : 0);
38
54
  }
39
55
  function findArg(args2, name) {
@@ -1,6 +1,15 @@
1
1
  #!/usr/bin/env node
2
+ import {
3
+ isProcessRunning,
4
+ loadPid,
5
+ removePid,
6
+ resolveApiKey,
7
+ resolveServerUrl,
8
+ savePid
9
+ } from "./chunk-XSAVKZSF.js";
10
+ import "./chunk-PDX44BCA.js";
2
11
 
3
- // src/commands/daemon.ts
12
+ // src/commands/connect.ts
4
13
  import { hostname } from "os";
5
14
 
6
15
  // src/lib/workspace.ts
@@ -49,11 +58,10 @@ function getWorkspaceId(projectDir) {
49
58
  }
50
59
 
51
60
  // src/lib/server-client.ts
52
- var DEFAULT_SERVER_URL = "https://ztile.dev";
53
61
  function getConfig() {
54
62
  return {
55
- serverUrl: process.env["ZTILE_SERVER_URL"] ?? DEFAULT_SERVER_URL,
56
- apiKey: process.env["ZTILE_API_KEY"] ?? ""
63
+ serverUrl: resolveServerUrl(),
64
+ apiKey: resolveApiKey()
57
65
  };
58
66
  }
59
67
  async function request(method, path, body) {
@@ -228,77 +236,128 @@ function getSessionList() {
228
236
  return result;
229
237
  }
230
238
 
231
- // src/commands/daemon.ts
239
+ // src/commands/connect.ts
232
240
  var POLL_INTERVAL_MS = 5e3;
233
241
  var HEARTBEAT_INTERVAL_MS = 15e3;
234
- function log2(msg) {
235
- console.log(`[daemon] ${msg}`);
242
+ var DIM = "\x1B[2m";
243
+ var RESET = "\x1B[0m";
244
+ var GREEN = "\x1B[32m";
245
+ var YELLOW = "\x1B[33m";
246
+ var CYAN = "\x1B[36m";
247
+ var RED = "\x1B[31m";
248
+ var BOLD = "\x1B[1m";
249
+ function timestamp() {
250
+ return (/* @__PURE__ */ new Date()).toLocaleTimeString("en-US", { hour12: false });
251
+ }
252
+ function log2(icon, msg, color = "") {
253
+ console.log(`${DIM}${timestamp()}${RESET} ${color}${icon}${RESET} ${msg}`);
236
254
  }
237
255
  async function handleCommand(cmd, workspaceId, projectDir) {
238
- log2(`command: ${cmd.type} (${cmd.id})`);
239
- await updateCommand(cmd.id, "processing");
240
256
  switch (cmd.type) {
241
257
  case "spawn": {
242
258
  const prompt = cmd.payload.prompt;
243
259
  const workdir = cmd.payload.workdir ?? projectDir;
244
260
  const allowedTools = cmd.payload.allowedTools;
261
+ log2("\u26A1", `Spawn session: "${prompt.slice(0, 60)}${prompt.length > 60 ? "..." : ""}"`, CYAN);
262
+ await updateCommand(cmd.id, "processing");
245
263
  spawnSession(cmd.id, workspaceId, prompt, workdir, allowedTools);
246
264
  break;
247
265
  }
248
266
  case "prompt": {
249
267
  if (!cmd.sessionId) {
268
+ log2("\u2717", `Command failed: missing sessionId`, RED);
250
269
  await updateCommand(cmd.id, "failed", { error: "Missing sessionId" });
251
270
  return;
252
271
  }
253
272
  const prompt = cmd.payload.prompt;
273
+ log2("\u2192", `Prompt sent: "${prompt.slice(0, 60)}${prompt.length > 60 ? "..." : ""}"`, GREEN);
274
+ await updateCommand(cmd.id, "processing");
254
275
  sendPrompt(cmd.id, workspaceId, cmd.sessionId, prompt);
255
276
  break;
256
277
  }
257
278
  default:
258
- log2(`unknown command type: ${cmd.type}`);
279
+ log2("?", `Unknown command: ${cmd.type}`, YELLOW);
259
280
  await updateCommand(cmd.id, "failed", { error: `Unknown command type: ${cmd.type}` });
260
281
  }
261
282
  }
262
- async function runDaemon(projectDir) {
263
- const apiKey = process.env["ZTILE_API_KEY"];
283
+ async function runConnect(options) {
284
+ const apiKey = resolveApiKey();
264
285
  if (!apiKey) {
265
- console.error("Error: ZTILE_API_KEY is required.");
286
+ console.error("Error: Not logged in. Run `ztile login` first.");
266
287
  process.exit(1);
267
288
  }
289
+ const { projectDir, daemon } = options;
268
290
  const workspaceId = getWorkspaceId(projectDir);
269
291
  const host = hostname();
270
- log2(`starting daemon`);
271
- log2(` workspace: ${workspaceId}`);
272
- log2(` hostname: ${host}`);
273
- log2(` project: ${projectDir}`);
274
- log2(` server: ${process.env["ZTILE_SERVER_URL"] ?? "https://ztile.dev"}`);
275
- log2(` poll interval: ${POLL_INTERVAL_MS}ms`);
292
+ const serverUrl = resolveServerUrl();
293
+ const existingPid = loadPid();
294
+ if (existingPid && isProcessRunning(existingPid)) {
295
+ console.error(`Error: Already connected (PID: ${existingPid})`);
296
+ console.error(" Run `ztile disconnect` first.");
297
+ process.exit(1);
298
+ }
299
+ if (daemon) {
300
+ const { spawn } = await import("child_process");
301
+ const child = spawn(process.argv[0], [...process.argv.slice(1).filter((a) => a !== "--daemon" && a !== "-d")], {
302
+ detached: true,
303
+ stdio: "ignore"
304
+ });
305
+ child.unref();
306
+ savePid(child.pid);
307
+ console.log(`Ztile daemon started (PID: ${child.pid})`);
308
+ console.log(` Workspace: ${workspaceId}`);
309
+ console.log(` Server: ${serverUrl}`);
310
+ console.log("");
311
+ console.log("Run `ztile disconnect` to stop.");
312
+ process.exit(0);
313
+ }
314
+ savePid(process.pid);
315
+ console.log("");
316
+ console.log(`${BOLD}Ztile Connect${RESET}`);
317
+ console.log(`${DIM}\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500${RESET}`);
318
+ console.log(` Server: ${serverUrl}`);
319
+ console.log(` Workspace: ${workspaceId}`);
320
+ console.log(` Hostname: ${host}`);
321
+ console.log(` Project: ${projectDir}`);
322
+ console.log(`${DIM}\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500${RESET}`);
323
+ console.log("");
276
324
  const ok = await sendHeartbeat(workspaceId, host, []);
277
325
  if (ok) {
278
- log2(`registered with server`);
326
+ log2("\u25CF", `Connected to ${serverUrl}`, GREEN);
279
327
  } else {
280
- log2(`failed to register with server (will retry)`);
328
+ log2("\u25CF", `Failed to connect (will retry)`, RED);
281
329
  }
330
+ log2("\u25CE", `Waiting for commands...`, DIM);
331
+ let lastSessionCount = 0;
282
332
  const heartbeatTimer = setInterval(async () => {
283
333
  const sessions2 = getSessionList();
284
- await sendHeartbeat(workspaceId, host, sessions2).catch(() => {
285
- });
334
+ const ok2 = await sendHeartbeat(workspaceId, host, sessions2).catch(() => false);
335
+ if (sessions2.length !== lastSessionCount) {
336
+ log2("\u25CE", `${sessions2.length} active session${sessions2.length !== 1 ? "s" : ""}`, DIM);
337
+ lastSessionCount = sessions2.length;
338
+ }
339
+ if (!ok2) {
340
+ log2("!", `Heartbeat failed, retrying...`, YELLOW);
341
+ }
286
342
  }, HEARTBEAT_INTERVAL_MS);
287
- log2(`polling for commands...`);
343
+ let commandCount = 0;
288
344
  const pollTimer = setInterval(async () => {
289
345
  try {
290
346
  const commands = await pollCommands(workspaceId);
291
347
  for (const cmd of commands) {
348
+ commandCount++;
292
349
  await handleCommand(cmd, workspaceId, projectDir);
293
350
  }
294
351
  } catch (err) {
295
- log2(`poll error: ${err instanceof Error ? err.message : err}`);
352
+ log2("!", `Poll error: ${err instanceof Error ? err.message : err}`, RED);
296
353
  }
297
354
  }, POLL_INTERVAL_MS);
298
355
  const shutdown = () => {
299
- log2(`shutting down...`);
356
+ console.log("");
357
+ log2("\u25CF", `Disconnected (${commandCount} command${commandCount !== 1 ? "s" : ""} processed)`, DIM);
300
358
  clearInterval(heartbeatTimer);
301
359
  clearInterval(pollTimer);
360
+ removePid();
302
361
  process.exit(0);
303
362
  };
304
363
  process.on("SIGINT", shutdown);
@@ -307,5 +366,5 @@ async function runDaemon(projectDir) {
307
366
  });
308
367
  }
309
368
  export {
310
- runDaemon
369
+ runConnect
311
370
  };
@@ -0,0 +1,24 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ isProcessRunning,
4
+ loadCredentials,
5
+ loadPid,
6
+ removePid,
7
+ resolveApiKey,
8
+ resolveMachineId,
9
+ resolveServerUrl,
10
+ saveCredentials,
11
+ savePid
12
+ } from "./chunk-XSAVKZSF.js";
13
+ import "./chunk-PDX44BCA.js";
14
+ export {
15
+ isProcessRunning,
16
+ loadCredentials,
17
+ loadPid,
18
+ removePid,
19
+ resolveApiKey,
20
+ resolveMachineId,
21
+ resolveServerUrl,
22
+ saveCredentials,
23
+ savePid
24
+ };
@@ -0,0 +1,32 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ isProcessRunning,
4
+ loadPid,
5
+ removePid
6
+ } from "./chunk-XSAVKZSF.js";
7
+ import "./chunk-PDX44BCA.js";
8
+
9
+ // src/commands/disconnect.ts
10
+ function disconnect() {
11
+ const pid = loadPid();
12
+ if (!pid) {
13
+ console.log("No active connection found.");
14
+ return;
15
+ }
16
+ if (!isProcessRunning(pid)) {
17
+ console.log(`Stale PID file (process ${pid} not running). Cleaning up.`);
18
+ removePid();
19
+ return;
20
+ }
21
+ try {
22
+ process.kill(pid, "SIGTERM");
23
+ removePid();
24
+ console.log(`Disconnected (PID: ${pid})`);
25
+ } catch (err) {
26
+ console.error(`Error stopping process ${pid}: ${err instanceof Error ? err.message : err}`);
27
+ removePid();
28
+ }
29
+ }
30
+ export {
31
+ disconnect
32
+ };
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env node
2
+ import "./chunk-PDX44BCA.js";
2
3
 
3
4
  // src/commands/hook.ts
4
5
  import { readFile as readFile2, stat } from "fs/promises";
@@ -0,0 +1,102 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ loadCredentials,
4
+ saveCredentials
5
+ } from "./chunk-XSAVKZSF.js";
6
+ import {
7
+ __require
8
+ } from "./chunk-PDX44BCA.js";
9
+
10
+ // src/commands/login.ts
11
+ import { createInterface } from "readline";
12
+ import { hostname } from "os";
13
+ async function prompt(question) {
14
+ const rl = createInterface({ input: process.stdin, output: process.stderr });
15
+ return new Promise((resolve) => {
16
+ rl.question(question, (answer) => {
17
+ rl.close();
18
+ resolve(answer.trim());
19
+ });
20
+ });
21
+ }
22
+ function openBrowser(url) {
23
+ const { execSync } = __require("child_process");
24
+ try {
25
+ const platform = process.platform;
26
+ if (platform === "darwin") execSync(`open "${url}"`);
27
+ else if (platform === "win32") execSync(`start "${url}"`);
28
+ else execSync(`xdg-open "${url}" 2>/dev/null || echo ""`);
29
+ } catch {
30
+ }
31
+ }
32
+ async function login(options) {
33
+ const existing = loadCredentials();
34
+ const defaultServer = existing?.serverUrl ?? "https://ztile.dev";
35
+ const defaultMachine = existing?.machineId ?? hostname();
36
+ let apiKey = options.apiKey;
37
+ let serverUrl = options.serverUrl ?? defaultServer;
38
+ const machineId = options.machineId ?? defaultMachine;
39
+ if (apiKey) {
40
+ await verifyAndSave(apiKey, serverUrl, machineId);
41
+ return;
42
+ }
43
+ console.log("");
44
+ console.log("How would you like to authenticate?");
45
+ console.log("");
46
+ console.log(" 1) Open browser to get API key (recommended)");
47
+ console.log(" 2) Enter API key directly");
48
+ console.log("");
49
+ const choice = await prompt("Choice [1]: ");
50
+ const method = choice === "2" ? "direct" : "browser";
51
+ if (method === "browser") {
52
+ const settingsUrl = `${serverUrl}/settings`;
53
+ console.log("");
54
+ console.log(`Opening ${settingsUrl} ...`);
55
+ console.log("Copy your API key from the Settings page and paste it below.");
56
+ console.log("");
57
+ openBrowser(settingsUrl);
58
+ apiKey = await prompt("API Key: ");
59
+ } else {
60
+ apiKey = await prompt("API Key: ");
61
+ }
62
+ if (!apiKey) {
63
+ console.error("Error: API key is required.");
64
+ process.exit(1);
65
+ }
66
+ if (!options.serverUrl) {
67
+ const input = await prompt(`Server URL [${defaultServer}]: `);
68
+ if (input) serverUrl = input;
69
+ }
70
+ await verifyAndSave(apiKey, serverUrl, machineId);
71
+ }
72
+ async function verifyAndSave(apiKey, serverUrl, machineId) {
73
+ process.stderr.write("Verifying... ");
74
+ try {
75
+ const res = await fetch(`${serverUrl}/api/hooks/ingest`, {
76
+ method: "POST",
77
+ headers: { "Content-Type": "application/json", "x-api-key": apiKey },
78
+ body: JSON.stringify({})
79
+ });
80
+ if (res.status === 401) {
81
+ console.error("failed");
82
+ console.error("Error: Invalid API key.");
83
+ process.exit(1);
84
+ }
85
+ } catch {
86
+ console.error("failed");
87
+ console.error(`Error: Could not connect to ${serverUrl}`);
88
+ process.exit(1);
89
+ }
90
+ console.error("ok");
91
+ saveCredentials({ apiKey, serverUrl, machineId });
92
+ console.log("");
93
+ console.log("Logged in successfully!");
94
+ console.log(` Server: ${serverUrl}`);
95
+ console.log(` Machine ID: ${machineId}`);
96
+ console.log(` Saved to: ~/.ztile/credentials.json`);
97
+ console.log("");
98
+ console.log("Next: run `ztile install` to configure Claude Code hooks.");
99
+ }
100
+ export {
101
+ login
102
+ };
@@ -1,12 +1,11 @@
1
1
  #!/usr/bin/env node
2
+ import "./chunk-PDX44BCA.js";
2
3
 
3
4
  // src/commands/setup.ts
4
5
  import { readFile, writeFile } from "fs/promises";
5
6
  import { join } from "path";
6
7
  import { existsSync } from "fs";
7
- import { hostname } from "os";
8
8
  import { execSync } from "child_process";
9
- var DEFAULT_SERVER_URL = "https://ztile.dev";
10
9
  var HOOK_EVENTS = [
11
10
  "UserPromptSubmit",
12
11
  "PreToolUse",
@@ -20,7 +19,7 @@ var HOOK_EVENTS = [
20
19
  "Notification",
21
20
  "SessionEnd"
22
21
  ];
23
- async function setupClaudeCode(options) {
22
+ async function setupClaudeCode(_options) {
24
23
  const ztileBin = findGlobalBin();
25
24
  if (!ztileBin) {
26
25
  console.error("Error: ztile is not globally installed.");
@@ -46,14 +45,7 @@ async function setupClaudeCode(options) {
46
45
  } catch {
47
46
  }
48
47
  const hooks = settings["hooks"] ?? {};
49
- const serverUrl = options.serverUrl ?? DEFAULT_SERVER_URL;
50
- const envPrefix = [
51
- `ZTILE_API_KEY=${options.apiKey}`,
52
- `ZTILE_SERVER_URL=${serverUrl}`,
53
- `ZTILE_MACHINE_ID=${options.machineId ?? hostname()}`,
54
- ...options.project ? [`ZTILE_PROJECT=${options.project}`] : []
55
- ].join(" ");
56
- const hookCommand = `${envPrefix} ${ztileBin} hook`;
48
+ const hookCommand = `${ztileBin} hook`;
57
49
  const ztileHook = { type: "command", command: hookCommand };
58
50
  for (const event of Object.keys(hooks)) {
59
51
  const existing = hooks[event] ?? [];
@@ -75,14 +67,12 @@ async function setupClaudeCode(options) {
75
67
  settings["hooks"] = hooks;
76
68
  await writeFile(settingsPath, JSON.stringify(settings, null, 2) + "\n");
77
69
  console.log(`Claude Code: configured ${addedCount} hook(s) in ${settingsPath}`);
78
- console.log(` Mode: command (transcript-based)`);
79
- console.log(` Server: ${serverUrl}`);
80
- console.log(` Machine ID: ${options.machineId ?? hostname()}`);
81
- if (options.project) console.log(` Project: ${options.project}`);
82
- console.log(` Binary: ${ztileBin}`);
83
- console.log(` Events: ${HOOK_EVENTS.join(", ")}`);
70
+ console.log(` Binary: ${ztileBin}`);
71
+ console.log(` Events: ${HOOK_EVENTS.join(", ")}`);
84
72
  console.log();
85
- console.log("Note: Restart Claude Code sessions for hooks to take effect.");
73
+ console.log("Next steps:");
74
+ console.log(" \u2022 Restart Claude Code for hooks to take effect");
75
+ console.log(" \u2022 Run `ztile connect` to enable remote control from the dashboard");
86
76
  }
87
77
  function findGlobalBin() {
88
78
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ztile-cli",
3
- "version": "0.2.2",
3
+ "version": "0.3.0",
4
4
  "description": "Mission control for autonomous coding agents (Claude Code, Codex, Gemini CLI)",
5
5
  "bin": {
6
6
  "ztile": "dist/cli.js"
@@ -39,6 +39,6 @@
39
39
  "type": "module",
40
40
  "repository": {
41
41
  "type": "git",
42
- "url": "git+https://github.com/newdefs/ztile.git"
42
+ "url": "git+https://github.com/shunyooo/ztile.git"
43
43
  }
44
44
  }