@autoclawd/autoclawd 1.1.2 → 1.1.4

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/dist/index.js CHANGED
@@ -712,120 +712,16 @@ import { PassThrough } from "stream";
712
712
  import { homedir as homedir3, platform } from "os";
713
713
  import { join as join4 } from "path";
714
714
  import { existsSync as existsSync3, readFileSync as readFileSync2 } from "fs";
715
- import { execSync as execSync2 } from "child_process";
716
715
  var docker = new Docker();
717
- function sleep2(ms) {
718
- return new Promise((r) => setTimeout(r, ms));
719
- }
720
- async function tryStartDocker() {
721
- const os = platform();
722
- if (os === "darwin") {
723
- if (existsSync3("/Applications/Docker.app")) {
724
- log.info("Docker not running \u2014 starting Docker Desktop...");
725
- try {
726
- execSync2("open -a Docker", { stdio: "pipe" });
727
- } catch {
728
- return false;
729
- }
730
- } else {
731
- return false;
732
- }
733
- } else if (os === "linux") {
734
- log.info("Docker not running \u2014 attempting to start...");
735
- try {
736
- execSync2("sudo systemctl start docker 2>/dev/null || sudo service docker start 2>/dev/null", {
737
- stdio: "pipe",
738
- timeout: 3e4
739
- });
740
- } catch {
741
- return false;
742
- }
743
- } else {
744
- return false;
745
- }
746
- for (let i = 0; i < 30; i++) {
747
- await sleep2(1e3);
748
- try {
749
- await docker.ping();
750
- log.success("Docker started");
751
- return true;
752
- } catch {
753
- }
754
- if (i > 0 && i % 5 === 0) {
755
- log.info(`Waiting for Docker daemon... (${i}s)`);
756
- }
757
- }
758
- return false;
759
- }
760
- async function tryInstallDocker() {
761
- const os = platform();
762
- if (os === "darwin") {
763
- try {
764
- execSync2("which brew", { stdio: "pipe" });
765
- } catch {
766
- log.warn("Docker not installed and Homebrew not found \u2014 cannot auto-install");
767
- return false;
768
- }
769
- log.info("Docker not installed \u2014 installing via Homebrew (this may take a few minutes)...");
770
- try {
771
- execSync2("brew install --cask docker", { stdio: "inherit", timeout: 6e5 });
772
- log.success("Docker Desktop installed");
773
- return true;
774
- } catch {
775
- log.warn("Docker install via Homebrew failed");
776
- return false;
777
- }
778
- } else if (os === "linux") {
779
- const cmds = [
780
- { check: "apt-get", install: "sudo apt-get update -qq && sudo apt-get install -y docker.io && sudo systemctl enable docker" },
781
- { check: "dnf", install: "sudo dnf install -y docker && sudo systemctl enable docker" },
782
- { check: "yum", install: "sudo yum install -y docker && sudo systemctl enable docker" },
783
- { check: "pacman", install: "sudo pacman -Sy --noconfirm docker && sudo systemctl enable docker" }
784
- ];
785
- for (const { check, install } of cmds) {
786
- try {
787
- execSync2(`which ${check}`, { stdio: "pipe" });
788
- log.info(`Docker not installed \u2014 installing via ${check}...`);
789
- execSync2(install, { stdio: "inherit", timeout: 3e5 });
790
- log.success("Docker installed");
791
- return true;
792
- } catch {
793
- }
794
- }
795
- return false;
796
- }
797
- return false;
798
- }
799
716
  async function checkDockerAvailable() {
800
717
  try {
801
718
  await docker.ping();
802
- return;
803
719
  } catch {
804
- }
805
- const started = await tryStartDocker();
806
- if (started) return;
807
- let installed = false;
808
- try {
809
- execSync2("which docker", { stdio: "pipe" });
810
- installed = true;
811
- } catch {
812
- }
813
- if (installed) {
720
+ const isMac = platform() === "darwin";
814
721
  throw new Error(
815
- "Docker is installed but the daemon is not running and could not be started automatically.\nStart it manually:\n" + (platform() === "darwin" ? " open -a Docker\n" : " sudo systemctl start docker\n")
722
+ "Cannot connect to Docker daemon.\n\n" + (isMac ? "Install: brew install --cask docker\nStart: open -a Docker\n" : "Install: https://docs.docker.com/get-docker/\nStart: sudo systemctl start docker\n")
816
723
  );
817
724
  }
818
- const didInstall = await tryInstallDocker();
819
- if (didInstall) {
820
- const started2 = await tryStartDocker();
821
- if (started2) return;
822
- throw new Error(
823
- "Docker was installed but could not be started.\n" + (platform() === "darwin" ? "Open Docker Desktop from Applications and try again.\n" : "Run: sudo systemctl start docker\n")
824
- );
825
- }
826
- throw new Error(
827
- "Docker is not installed and could not be auto-installed.\n" + (platform() === "darwin" ? "Install manually: brew install --cask docker\n" : "Install manually: https://docs.docker.com/get-docker/\n")
828
- );
829
725
  }
830
726
  async function ensureImage(image) {
831
727
  try {
@@ -1218,7 +1114,7 @@ async function runAgentLoop(opts) {
1218
1114
  }
1219
1115
  const waitMs = estimateResetMs(combined);
1220
1116
  log.ticket(ticketId, `Rate limited (${rateLimitRetries}/${MAX_RATE_LIMIT_RETRIES}) \u2014 pausing ${Math.round(waitMs / 1e3)}s`);
1221
- await sleep3(waitMs);
1117
+ await sleep2(waitMs);
1222
1118
  i--;
1223
1119
  continue;
1224
1120
  }
@@ -1229,7 +1125,7 @@ async function runAgentLoop(opts) {
1229
1125
  log.ticket(ticketId, `Max iterations (${agentConfig.maxIterations}) reached`);
1230
1126
  return { iterations: agentConfig.maxIterations, success: false, lastOutput };
1231
1127
  }
1232
- function sleep3(ms) {
1128
+ function sleep2(ms) {
1233
1129
  return new Promise((resolve) => setTimeout(resolve, ms));
1234
1130
  }
1235
1131
 
@@ -1303,7 +1199,7 @@ async function commitAndPush(container, opts) {
1303
1199
  import { mkdtempSync as mkdtempSync2, rmSync as rmSync2, writeFileSync as writeFileSync2 } from "fs";
1304
1200
  import { join as join6 } from "path";
1305
1201
  import { tmpdir as tmpdir2 } from "os";
1306
- import { execSync as execSync3 } from "child_process";
1202
+ import { execSync as execSync2 } from "child_process";
1307
1203
 
1308
1204
  // src/db.ts
1309
1205
  import Database from "better-sqlite3";
@@ -1491,7 +1387,7 @@ function detectDefaultBranch2(repoUrl, githubToken) {
1491
1387
  const askpass = createAskpass2(githubToken);
1492
1388
  const authedUrl = repoUrl.replace("https://", "https://x-access-token@");
1493
1389
  try {
1494
- const output = execSync3(
1390
+ const output = execSync2(
1495
1391
  `git ls-remote --symref -- ${authedUrl} HEAD`,
1496
1392
  { stdio: "pipe", timeout: 3e4, env: gitEnv2(askpass.path), encoding: "utf-8" }
1497
1393
  );
@@ -1515,14 +1411,14 @@ async function pushScaffold(opts) {
1515
1411
  }
1516
1412
  writeFileSync2(join6(scaffoldDir, "README.md"), readmeLines.join("\n") + "\n");
1517
1413
  writeFileSync2(join6(scaffoldDir, ".autoclawd.yaml"), "base: main\n");
1518
- execSync3("git init", { cwd: scaffoldDir, stdio: "pipe", env });
1519
- execSync3("git checkout -b main", { cwd: scaffoldDir, stdio: "pipe", env });
1520
- execSync3('git config user.email "autoclawd@users.noreply.github.com"', { cwd: scaffoldDir, stdio: "pipe", env });
1521
- execSync3('git config user.name "autoclawd"', { cwd: scaffoldDir, stdio: "pipe", env });
1522
- execSync3("git add .", { cwd: scaffoldDir, stdio: "pipe", env });
1523
- execSync3('git commit -m "chore: initial scaffold"', { cwd: scaffoldDir, stdio: "pipe", env });
1524
- execSync3(`git remote add origin ${authedUrl}`, { cwd: scaffoldDir, stdio: "pipe", env });
1525
- execSync3("git push -u origin main", { cwd: scaffoldDir, stdio: "pipe", timeout: 6e4, env });
1414
+ execSync2("git init", { cwd: scaffoldDir, stdio: "pipe", env });
1415
+ execSync2("git checkout -b main", { cwd: scaffoldDir, stdio: "pipe", env });
1416
+ execSync2('git config user.email "autoclawd@users.noreply.github.com"', { cwd: scaffoldDir, stdio: "pipe", env });
1417
+ execSync2('git config user.name "autoclawd"', { cwd: scaffoldDir, stdio: "pipe", env });
1418
+ execSync2("git add .", { cwd: scaffoldDir, stdio: "pipe", env });
1419
+ execSync2('git commit -m "chore: initial scaffold"', { cwd: scaffoldDir, stdio: "pipe", env });
1420
+ execSync2(`git remote add origin ${authedUrl}`, { cwd: scaffoldDir, stdio: "pipe", env });
1421
+ execSync2("git push -u origin main", { cwd: scaffoldDir, stdio: "pipe", timeout: 6e4, env });
1526
1422
  } finally {
1527
1423
  rmSync2(scaffoldDir, { recursive: true, force: true });
1528
1424
  rmSync2(askpass.dir, { recursive: true, force: true });
@@ -1535,7 +1431,7 @@ async function cloneToTemp(repoUrl, baseBranch, githubToken) {
1535
1431
  const askpass = createAskpass2(githubToken);
1536
1432
  const authedUrl = repoUrl.replace("https://", "https://x-access-token@");
1537
1433
  try {
1538
- execSync3(`git clone --depth=50 -b ${baseBranch} -- ${authedUrl} ${workDir}`, {
1434
+ execSync2(`git clone --depth=50 -b ${baseBranch} -- ${authedUrl} ${workDir}`, {
1539
1435
  stdio: "pipe",
1540
1436
  timeout: 12e4,
1541
1437
  env: gitEnv2(askpass.path)
@@ -1712,7 +1608,7 @@ async function executeTicket(opts) {
1712
1608
  throw err;
1713
1609
  }
1714
1610
  }
1715
- execSync3(`git checkout -B ${branchName} --`, { cwd: workDir, stdio: "pipe" });
1611
+ execSync2(`git checkout -B ${branchName} --`, { cwd: workDir, stdio: "pipe" });
1716
1612
  container = await createContainer({
1717
1613
  dockerConfig: docker2,
1718
1614
  workspacePath: workDir,
@@ -2501,131 +2397,51 @@ function printHistoryTable(records) {
2501
2397
  }
2502
2398
 
2503
2399
  // src/deps.ts
2504
- import { execSync as execSync4 } from "child_process";
2400
+ import { execSync as execSync3 } from "child_process";
2505
2401
  import { existsSync as existsSync6 } from "fs";
2506
2402
  import { join as join8 } from "path";
2507
2403
  import { homedir as homedir5 } from "os";
2508
- function detectPackageManager() {
2509
- const checks = [
2510
- ["apt", "apt-get"],
2511
- ["dnf", "dnf"],
2512
- ["yum", "yum"],
2513
- ["pacman", "pacman"],
2514
- ["apk", "apk"],
2515
- ["brew", "brew"]
2516
- ];
2517
- for (const [name, cmd] of checks) {
2518
- try {
2519
- execSync4(`which ${cmd}`, { stdio: "pipe" });
2520
- return name;
2521
- } catch {
2522
- }
2523
- }
2524
- return "unknown";
2525
- }
2526
- var DOCKER_INSTALL = {
2527
- apt: [
2528
- "apt-get update -qq",
2529
- "apt-get install -y docker.io",
2530
- "systemctl enable docker",
2531
- "systemctl start docker"
2532
- ],
2533
- dnf: [
2534
- "dnf install -y docker",
2535
- "systemctl enable docker",
2536
- "systemctl start docker"
2537
- ],
2538
- yum: [
2539
- "yum install -y docker",
2540
- "systemctl enable docker",
2541
- "systemctl start docker"
2542
- ],
2543
- pacman: [
2544
- "pacman -Sy --noconfirm docker",
2545
- "systemctl enable docker",
2546
- "systemctl start docker"
2547
- ],
2548
- apk: [
2549
- "apk add docker",
2550
- "rc-update add docker boot",
2551
- "service docker start"
2552
- ],
2553
- brew: [
2554
- "brew install --cask docker"
2555
- ],
2556
- unknown: []
2557
- };
2558
- var CLOUDFLARED_INSTALL = {
2559
- apt: [
2560
- "apt-get update -qq",
2561
- 'apt-get install -y cloudflared || (curl -fsSL https://pkg.cloudflare.com/cloudflare-main.gpg | tee /usr/share/keyrings/cloudflare-main.gpg >/dev/null && echo "deb [signed-by=/usr/share/keyrings/cloudflare-main.gpg] https://pkg.cloudflare.com/cloudflared $(lsb_release -cs) main" | tee /etc/apt/sources.list.d/cloudflared.list && apt-get update -qq && apt-get install -y cloudflared)'
2562
- ],
2563
- dnf: ["dnf install -y cloudflared || npm install -g cloudflared"],
2564
- yum: ["yum install -y cloudflared || npm install -g cloudflared"],
2565
- pacman: ["pacman -Sy --noconfirm cloudflared"],
2566
- apk: ["apk add cloudflared"],
2567
- brew: ["brew install cloudflared"],
2568
- unknown: []
2569
- };
2570
2404
  function checkDeps() {
2571
- const pm = detectPackageManager();
2572
- const needsSudo = pm !== "brew" && pm !== "unknown" && process.getuid?.() !== 0;
2573
- const sudo = needsSudo ? "sudo " : "";
2574
2405
  return [
2575
2406
  {
2576
2407
  name: "Docker",
2577
2408
  installed: commandExists("docker"),
2578
2409
  running: isDockerRunning(),
2579
- installable: pm !== "unknown",
2580
- installCommands: DOCKER_INSTALL[pm].map((c) => `${sudo}${c}`),
2581
- manualInstructions: "https://docs.docker.com/get-docker/"
2410
+ instructions: process.platform === "darwin" ? "brew install --cask docker && open -a Docker" : "https://docs.docker.com/get-docker/"
2582
2411
  },
2583
2412
  {
2584
2413
  name: "Claude Code",
2585
2414
  installed: commandExists("claude"),
2586
- installable: true,
2587
- installCommands: ["curl -fsSL https://claude.ai/install.sh | bash"],
2588
- manualInstructions: "curl -fsSL https://claude.ai/install.sh | bash"
2415
+ instructions: "curl -fsSL https://claude.ai/install.sh | bash\n Then run: claude (to log in)"
2589
2416
  },
2590
2417
  {
2591
2418
  name: "Claude credentials",
2592
- installed: existsSync6(join8(homedir5(), ".claude", ".credentials.json")),
2593
- installable: false,
2594
- installCommands: [],
2595
- manualInstructions: 'Run "claude" and complete the login flow'
2419
+ installed: hasClaudeAuth(),
2420
+ instructions: "Run: claude (and complete the login flow)"
2596
2421
  },
2597
2422
  {
2598
2423
  name: "cloudflared",
2599
2424
  installed: commandExists("cloudflared"),
2600
- installable: pm !== "unknown",
2601
- installCommands: CLOUDFLARED_INSTALL[pm].map((c) => `${sudo}${c}`),
2602
- manualInstructions: "https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/downloads/"
2425
+ instructions: process.platform === "darwin" ? "brew install cloudflared" : "https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/downloads/"
2603
2426
  }
2604
2427
  ];
2605
2428
  }
2606
- function installDep(dep) {
2607
- if (dep.installCommands.length === 0) return false;
2608
- for (const cmd of dep.installCommands) {
2609
- try {
2610
- execSync4(cmd, { stdio: "inherit", timeout: 3e5 });
2611
- } catch {
2612
- return false;
2613
- }
2614
- }
2615
- return true;
2616
- }
2617
- function addUserToDockerGroup() {
2618
- if (process.platform !== "linux") return;
2429
+ function hasClaudeAuth() {
2430
+ const credPaths = [
2431
+ join8(homedir5(), ".claude", ".credentials.json"),
2432
+ join8(homedir5(), ".claude", "credentials.json")
2433
+ ];
2434
+ if (credPaths.some((p) => existsSync6(p))) return true;
2619
2435
  try {
2620
- const user = execSync4("whoami", { encoding: "utf-8" }).trim();
2621
- execSync4(`sudo usermod -aG docker ${user}`, { stdio: "pipe" });
2622
- log.info(`Added ${user} to docker group \u2014 log out and back in to apply`);
2436
+ execSync3("claude --version", { stdio: "pipe", timeout: 5e3 });
2437
+ return existsSync6(join8(homedir5(), ".claude"));
2623
2438
  } catch {
2439
+ return false;
2624
2440
  }
2625
2441
  }
2626
2442
  function commandExists(cmd) {
2627
2443
  try {
2628
- execSync4(`which ${cmd}`, { stdio: "pipe" });
2444
+ execSync3(`which ${cmd}`, { stdio: "pipe" });
2629
2445
  return true;
2630
2446
  } catch {
2631
2447
  return false;
@@ -2633,7 +2449,7 @@ function commandExists(cmd) {
2633
2449
  }
2634
2450
  function isDockerRunning() {
2635
2451
  try {
2636
- execSync4("docker info", { stdio: "pipe", timeout: 1e4 });
2452
+ execSync3("docker info", { stdio: "pipe", timeout: 1e4 });
2637
2453
  return true;
2638
2454
  } catch {
2639
2455
  return false;
@@ -2642,7 +2458,7 @@ function isDockerRunning() {
2642
2458
 
2643
2459
  // src/index.ts
2644
2460
  import { existsSync as existsSync7, mkdirSync as mkdirSync3, writeFileSync as writeFileSync3, readFileSync as readFileSync4, unlinkSync } from "fs";
2645
- import { execSync as execSync5, spawn as spawn2 } from "child_process";
2461
+ import { execSync as execSync4, spawn as spawn2 } from "child_process";
2646
2462
  import { createInterface } from "readline";
2647
2463
  import { join as join9 } from "path";
2648
2464
  import { homedir as homedir6 } from "os";
@@ -3045,7 +2861,19 @@ program.command("history").description("Show run history").option("-n, --limit <
3045
2861
  }
3046
2862
  });
3047
2863
  function checkClaudeCredentials() {
3048
- return existsSync7(join9(homedir6(), ".claude", ".credentials.json"));
2864
+ const home = homedir6();
2865
+ if (existsSync7(join9(home, ".claude", ".credentials.json"))) return true;
2866
+ if (existsSync7(join9(home, ".claude", "credentials.json"))) return true;
2867
+ if (existsSync7(join9(home, ".claude")) && commandExistsSync("claude")) return true;
2868
+ return false;
2869
+ }
2870
+ function commandExistsSync(cmd) {
2871
+ try {
2872
+ execSync4(`which ${cmd}`, { stdio: "pipe" });
2873
+ return true;
2874
+ } catch {
2875
+ return false;
2876
+ }
3049
2877
  }
3050
2878
  async function validateGitHubToken(token) {
3051
2879
  try {
@@ -3060,51 +2888,22 @@ program.command("init").description("Set up autoclawd interactively").action(asy
3060
2888
  console.log("\n autoclawd setup\n");
3061
2889
  console.log(" Checking dependencies...\n");
3062
2890
  const deps = checkDeps();
3063
- const stillMissing = [];
2891
+ const missing = [];
3064
2892
  for (const dep of deps) {
3065
2893
  if (dep.installed && dep.running !== false) {
3066
2894
  log.success(`${dep.name}`);
3067
- continue;
3068
- }
3069
- if (dep.installed && dep.running === false) {
2895
+ } else if (dep.installed && dep.running === false) {
3070
2896
  log.warn(`${dep.name} \u2014 installed but not running`);
3071
- stillMissing.push(`${dep.name} (needs restart)`);
3072
- continue;
3073
- }
3074
- if (dep.installable && dep.installCommands.length > 0) {
3075
- const answer = await ask(` ${dep.name} not found. Install? (Y/n)`, "Y");
3076
- if (answer.toLowerCase() !== "n") {
3077
- console.log(`
3078
- Installing ${dep.name} via system package manager...
3079
- `);
3080
- const ok = installDep(dep);
3081
- if (ok) {
3082
- log.success(`${dep.name} installed`);
3083
- if (dep.name === "Docker") addUserToDockerGroup();
3084
- if (dep.name === "Claude Code") {
3085
- console.log('\n Run "claude" in your terminal to log in, then re-run: autoclawd init\n');
3086
- stillMissing.push("Claude Code login");
3087
- }
3088
- } else {
3089
- log.error(`${dep.name} install failed`);
3090
- console.log(` Install manually: ${dep.manualInstructions}`);
3091
- stillMissing.push(dep.name);
3092
- }
3093
- } else {
3094
- console.log(` Install manually: ${dep.manualInstructions}`);
3095
- stillMissing.push(dep.name);
3096
- }
3097
- } else if (dep.name === "Claude credentials") {
3098
- log.warn(`${dep.name} \u2014 run "claude" to log in`);
3099
- stillMissing.push(dep.name);
2897
+ missing.push(dep.name);
3100
2898
  } else {
3101
- log.warn(`${dep.name} \u2014 ${dep.manualInstructions}`);
3102
- stillMissing.push(dep.name);
2899
+ log.error(`${dep.name} \u2014 not installed`);
2900
+ console.log(` ${dep.instructions}`);
2901
+ missing.push(dep.name);
3103
2902
  }
3104
2903
  }
3105
- if (stillMissing.length > 0) {
2904
+ if (missing.length > 0) {
3106
2905
  console.log(`
3107
- Continuing setup \u2014 install ${stillMissing.join(", ")} before running.
2906
+ Install the above dependencies before running autoclawd.
3108
2907
  `);
3109
2908
  } else {
3110
2909
  console.log("");
@@ -3148,7 +2947,7 @@ program.command("init").description("Set up autoclawd interactively").action(asy
3148
2947
  }
3149
2948
  let ghToken = "";
3150
2949
  try {
3151
- ghToken = execSync5("gh auth token", { encoding: "utf-8" }).trim();
2950
+ ghToken = execSync4("gh auth token", { encoding: "utf-8" }).trim();
3152
2951
  log.success(`GitHub token detected from gh CLI`);
3153
2952
  } catch {
3154
2953
  ghToken = await ask("GitHub personal access token");