@bulletproof-sh/ctrl-daemon 0.0.7 → 0.0.8

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.
Files changed (3) hide show
  1. package/README.md +1 -0
  2. package/dist/index.js +16 -12
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -26,6 +26,7 @@ npx @bulletproof-sh/ctrl-daemon --port 3001 --host 127.0.0.1
26
26
  | `--port <number>` | `3001` | Port to listen on |
27
27
  | `--host <address>` | `0.0.0.0` | Host/address to bind to |
28
28
  | `--project-dir <path>` | — | Watch a single project; omit to watch all projects |
29
+ | `--idle-timeout <minutes>` | `15` | Agent idle timeout in minutes |
29
30
  | `--help`, `-h` | — | Print usage |
30
31
 
31
32
  Without `--project-dir`, the daemon scans `~/.claude/projects/` and watches every session it finds there.
package/dist/index.js CHANGED
@@ -4319,7 +4319,7 @@ var PROJECT_SCAN_INTERVAL_MS = 1000;
4319
4319
  var TOOL_DONE_DELAY_MS = 300;
4320
4320
  var PERMISSION_TIMER_DELAY_MS = 7000;
4321
4321
  var TEXT_IDLE_DELAY_MS = 5000;
4322
- var AGENT_IDLE_TIMEOUT_MS = 5 * 60 * 1000;
4322
+ var AGENT_IDLE_TIMEOUT_MS = 15 * 60 * 1000;
4323
4323
  var BASH_COMMAND_DISPLAY_MAX_LENGTH = 30;
4324
4324
  var TASK_DESCRIPTION_DISPLAY_MAX_LENGTH = 40;
4325
4325
 
@@ -4779,7 +4779,7 @@ function collectAllJsonlFiles(projectsRoot) {
4779
4779
  }
4780
4780
  return files;
4781
4781
  }
4782
- function startProjectScanner(rootDir, scanAll, agents, fileWatchers, pollingTimers, waitingTimers, permissionTimers, broadcast) {
4782
+ function startProjectScanner(rootDir, scanAll, agents, fileWatchers, pollingTimers, waitingTimers, permissionTimers, broadcast, idleTimeoutMs) {
4783
4783
  const knownJsonlFiles = new Set;
4784
4784
  let nextAgentId = 1;
4785
4785
  function scan() {
@@ -4788,9 +4788,9 @@ function startProjectScanner(rootDir, scanAll, agents, fileWatchers, pollingTime
4788
4788
  for (const { filePath, mtimeMs } of fileInfos) {
4789
4789
  if (knownJsonlFiles.has(filePath))
4790
4790
  continue;
4791
- knownJsonlFiles.add(filePath);
4792
- if (now - mtimeMs > AGENT_IDLE_TIMEOUT_MS)
4791
+ if (now - mtimeMs > idleTimeoutMs)
4793
4792
  continue;
4793
+ knownJsonlFiles.add(filePath);
4794
4794
  const id = nextAgentId++;
4795
4795
  const agentProjectDir = path2.dirname(filePath);
4796
4796
  const agent = {
@@ -4817,7 +4817,7 @@ function startProjectScanner(rootDir, scanAll, agents, fileWatchers, pollingTime
4817
4817
  }
4818
4818
  for (const [agentId, agent] of agents) {
4819
4819
  const lastActivity = agent.lastActivityAt || 0;
4820
- const idle = now - lastActivity > AGENT_IDLE_TIMEOUT_MS;
4820
+ const idle = now - lastActivity > idleTimeoutMs;
4821
4821
  const removed = !fs2.existsSync(agent.jsonlFile);
4822
4822
  if (removed || idle) {
4823
4823
  const reason = removed ? "JSONL removed" : "idle timeout";
@@ -4965,10 +4965,11 @@ function printUsage() {
4965
4965
  console.log(`Usage: ctrl-daemon [options]
4966
4966
 
4967
4967
  Options:
4968
- --port <number> Port to listen on (default: 3001)
4969
- --host <address> Host/address to bind to (default: 0.0.0.0)
4970
- --project-dir <path> Watch a single project directory
4971
- --help, -h Show this help message
4968
+ --port <number> Port to listen on (default: 3001)
4969
+ --host <address> Host/address to bind to (default: 0.0.0.0)
4970
+ --project-dir <path> Watch a single project directory
4971
+ --idle-timeout <minutes> Agent idle timeout in minutes (default: 15)
4972
+ --help, -h Show this help message
4972
4973
 
4973
4974
  Without --project-dir, watches ALL projects in ~/.claude/projects/.
4974
4975
  With --project-dir, watches only that specific project.`);
@@ -4978,6 +4979,7 @@ function parseArgs() {
4978
4979
  let projectDir;
4979
4980
  let port = 3001;
4980
4981
  let host = "0.0.0.0";
4982
+ let idleTimeoutMs = 15 * 60 * 1000;
4981
4983
  for (let i = 0;i < args.length; i++) {
4982
4984
  if (args[i] === "--help" || args[i] === "-h") {
4983
4985
  printUsage();
@@ -4988,9 +4990,11 @@ function parseArgs() {
4988
4990
  port = Number.parseInt(args[++i], 10);
4989
4991
  } else if (args[i] === "--host" && args[i + 1]) {
4990
4992
  host = args[++i];
4993
+ } else if (args[i] === "--idle-timeout" && args[i + 1]) {
4994
+ idleTimeoutMs = Number.parseInt(args[++i], 10) * 60 * 1000;
4991
4995
  }
4992
4996
  }
4993
- return { projectDir, port, host };
4997
+ return { projectDir, port, host, idleTimeoutMs };
4994
4998
  }
4995
4999
  function resolveProjectsRoot(claudeHome) {
4996
5000
  const home = claudeHome || path3.join(process.env.HOME || "~", ".claude");
@@ -5018,7 +5022,7 @@ async function main() {
5018
5022
  await shutdownAnalytics();
5019
5023
  process.exit(1);
5020
5024
  });
5021
- const { projectDir, port, host } = parseArgs();
5025
+ const { projectDir, port, host, idleTimeoutMs } = parseArgs();
5022
5026
  const claudeHome = process.env.CLAUDE_HOME;
5023
5027
  let scanDirs;
5024
5028
  if (projectDir) {
@@ -5044,7 +5048,7 @@ async function main() {
5044
5048
  ...analyticsConfig
5045
5049
  });
5046
5050
  const scanAll = !projectDir;
5047
- const scanner = startProjectScanner(scanDirs[0], scanAll, agents, fileWatchers, pollingTimers, waitingTimers, permissionTimers, server.broadcast);
5051
+ const scanner = startProjectScanner(scanDirs[0], scanAll, agents, fileWatchers, pollingTimers, waitingTimers, permissionTimers, server.broadcast, idleTimeoutMs);
5048
5052
  async function shutdown() {
5049
5053
  console.log(`
5050
5054
  [ctrl-daemon] Shutting down...`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bulletproof-sh/ctrl-daemon",
3
- "version": "0.0.7",
3
+ "version": "0.0.8",
4
4
  "description": "WebSocket daemon for ctrl — watches Claude Code sessions and broadcasts agent state",
5
5
  "type": "module",
6
6
  "license": "BUSL-1.1",