claude-code-watch 0.0.1 → 0.0.3

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/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "claude-code-watch",
3
- "version": "0.0.1",
3
+ "version": "0.0.3",
4
4
  "description": "Web-based real-time monitor for Claude Code.",
5
5
  "main": "./src/server/server.js",
6
6
  "bin": {
7
- "claude-watch": "./bin/claude-watch.js"
7
+ "claude-code-watch": "./bin/claude-watch.js"
8
8
  },
9
9
  "scripts": {
10
10
  "start": "node bin/claude-watch.js",
@@ -35,4 +35,4 @@
35
35
  "chokidar": "^4.0.3",
36
36
  "ws": "^8.20.0"
37
37
  }
38
- }
38
+ }
@@ -301,6 +301,34 @@ class DashboardServer {
301
301
  return w;
302
302
  }
303
303
 
304
+ async killExistingPort(port) {
305
+ let cmd;
306
+ if (process.platform === 'win32') {
307
+ cmd = `netstat -ano | findstr :${port} | findstr LISTENING`;
308
+ } else {
309
+ cmd = `lsof -ti:${port}`;
310
+ }
311
+ try {
312
+ const result = cp.execSync(cmd, { encoding: 'utf-8' }).trim();
313
+ if (!result) return false;
314
+ const pids = result.split('\n').map(s => s.trim()).filter(Boolean);
315
+ for (const pid of pids) {
316
+ try {
317
+ if (process.platform === 'win32') {
318
+ cp.execSync(`taskkill /PID ${pid} /F`, { encoding: 'utf-8' });
319
+ } else {
320
+ process.kill(parseInt(pid, 10), 'SIGKILL');
321
+ }
322
+ } catch {}
323
+ }
324
+ // Wait briefly for the port to be released
325
+ await new Promise(r => setTimeout(r, 500));
326
+ return true;
327
+ } catch {
328
+ return false;
329
+ }
330
+ }
331
+
304
332
  start(options = {}) {
305
333
  const skipHistory = options.skipHistory || false;
306
334
  const pollMs = options.pollMs || 500;
@@ -314,6 +342,35 @@ class DashboardServer {
314
342
  maxSessions,
315
343
  };
316
344
 
345
+ const doListen = () => {
346
+ this.server.listen(this.port, this.host, () => {
347
+ const url = `http://localhost:${this.port}`;
348
+ console.log(`\n claude-watch web server`);
349
+ console.log(` ───────────────────────────`);
350
+ console.log(` Local: ${url}`);
351
+ console.log(` Network: http://${this.host}:${this.port}`);
352
+ console.log(` Quit: Ctrl+C\n`);
353
+ });
354
+
355
+ this.server.on('error', async (err) => {
356
+ if (err.code === 'EADDRINUSE') {
357
+ console.log(`Port ${this.port} is in use, killing existing process...`);
358
+ const killed = await this.killExistingPort(this.port);
359
+ if (killed) {
360
+ console.log(`Existing process killed, restarting...`);
361
+ this.server.close();
362
+ doListen();
363
+ } else {
364
+ console.error(`Failed to free port ${this.port}, exiting.`);
365
+ process.exit(1);
366
+ }
367
+ } else {
368
+ console.error(`Server error: ${err.message}`);
369
+ process.exit(1);
370
+ }
371
+ });
372
+ };
373
+
317
374
  this.server = http.createServer((req, res) => {
318
375
  this.handleHTTP(req, res).catch(() => {
319
376
  if (!res.headersSent) {
@@ -347,14 +404,7 @@ class DashboardServer {
347
404
  process.exit(1);
348
405
  });
349
406
 
350
- this.server.listen(this.port, this.host, () => {
351
- const url = `http://localhost:${this.port}`;
352
- console.log(`\n claude-watch web server`);
353
- console.log(` ───────────────────────────`);
354
- console.log(` Local: ${url}`);
355
- console.log(` Network: http://${this.host}:${this.port}`);
356
- console.log(` Quit: Ctrl+C\n`);
357
- });
407
+ doListen();
358
408
 
359
409
  return { server: this.server, watcher: w };
360
410
  }