sisyphi 1.1.31 → 1.1.32

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.
@@ -96,6 +96,9 @@ runcmd:
96
96
  # 6. Sisyphus install (root → /usr/bin/sisyphusd symlink).
97
97
  - npm i -g sisyphi@${sisyphus_version}
98
98
 
99
+ # 6b. Claude Code CLI (sisyphus drives it for agent sessions).
100
+ - npm i -g @anthropic-ai/claude-code
101
+
99
102
  # 7. Daemon as systemd user service.
100
103
  - sudo -u sisyphus XDG_RUNTIME_DIR=/run/user/$(id -u sisyphus) systemctl --user daemon-reload
101
104
  - sudo -u sisyphus XDG_RUNTIME_DIR=/run/user/$(id -u sisyphus) systemctl --user enable --now sisyphusd
package/dist/cli.js CHANGED
@@ -2320,6 +2320,11 @@ function getTmuxSessionInfo() {
2320
2320
  function shellQuote(s) {
2321
2321
  return `'${s.replace(/'/g, "'\\''")}'`;
2322
2322
  }
2323
+ function shellQuoteHomePath(path) {
2324
+ if (path === "~") return "~";
2325
+ if (path.startsWith("~/")) return `~/${shellQuote(path.slice(2))}`;
2326
+ return shellQuote(path);
2327
+ }
2323
2328
  function validateRepoName(repo) {
2324
2329
  return !repo.includes("/") && !repo.includes("\\") && !repo.includes("..");
2325
2330
  }
@@ -10296,7 +10301,7 @@ function ensureGroveInstalled(provider) {
10296
10301
  }
10297
10302
  }
10298
10303
  function ensureGroveRegistered(provider, repo, instancePath) {
10299
- const cmd = `grove register --update --name ${shellQuote(repo)} ${shellQuote(instancePath)}`;
10304
+ const cmd = `grove register --update --name ${shellQuote(repo)} ${shellQuoteHomePath(instancePath)}`;
10300
10305
  const result = runOnBox(provider, cmd);
10301
10306
  if (result.exitCode !== 0) {
10302
10307
  throw new Error(`Failed to register grove project ${repo}: ${result.stderr || result.stdout}`);
@@ -10382,7 +10387,7 @@ function packageManagerInstallCmd(pm) {
10382
10387
  init_paths();
10383
10388
  function readSidecar(provider, repo) {
10384
10389
  const path = boxCloudSidecarPath(repo);
10385
- const result = runOnBox(provider, `cat ${shellQuote(path)} 2>/dev/null`);
10390
+ const result = runOnBox(provider, `cat ${shellQuoteHomePath(path)} 2>/dev/null`);
10386
10391
  if (result.exitCode !== 0 || !result.stdout.trim()) return null;
10387
10392
  try {
10388
10393
  const parsed = JSON.parse(result.stdout);
@@ -10396,8 +10401,8 @@ function writeSidecar(provider, repo, data) {
10396
10401
  const path = boxCloudSidecarPath(repo);
10397
10402
  const json = JSON.stringify(data, null, 2);
10398
10403
  const cmd = [
10399
- `mkdir -p ${shellQuote(dir)}`,
10400
- `cat > ${shellQuote(path)} <<'SISYPHUS_CLOUD_SIDECAR_EOF'`,
10404
+ `mkdir -p ${shellQuoteHomePath(dir)}`,
10405
+ `cat > ${shellQuoteHomePath(path)} <<'SISYPHUS_CLOUD_SIDECAR_EOF'`,
10401
10406
  json,
10402
10407
  "SISYPHUS_CLOUD_SIDECAR_EOF"
10403
10408
  ].join("\n");
@@ -10438,14 +10443,14 @@ Pass --name <slug> to disambiguate, or --fresh to overwrite.`
10438
10443
  }
10439
10444
  console.log(`\u2192 wiping ${remoteDir} and cloning ${localOrigin} on box...`);
10440
10445
  const cloneCmd = [
10441
- `rm -rf ${shellQuote(remoteDir)}`,
10442
- `mkdir -p ${shellQuote("~/projects")}`,
10443
- `git clone ${shellQuote(localOrigin)} ${shellQuote(remoteDir)}`
10446
+ `rm -rf ${shellQuoteHomePath(remoteDir)}`,
10447
+ `mkdir -p ${shellQuoteHomePath("~/projects")}`,
10448
+ `git clone ${shellQuote(localOrigin)} ${shellQuoteHomePath(remoteDir)}`
10444
10449
  ].join(" && ");
10445
10450
  const code = await runOnBoxStreaming(provider, cloneCmd);
10446
10451
  if (code !== 0) throw new Error(`fresh clone failed (exit ${code})`);
10447
10452
  } else {
10448
- const mkdir = runOnBox(provider, `mkdir -p ${shellQuote(remoteDir)}`);
10453
+ const mkdir = runOnBox(provider, `mkdir -p ${shellQuoteHomePath(remoteDir)}`);
10449
10454
  if (mkdir.exitCode !== 0) {
10450
10455
  throw new Error(`Failed to mkdir on box: ${mkdir.stderr}`);
10451
10456
  }
@@ -10483,7 +10488,7 @@ async function cloudInstall(provider, repo) {
10483
10488
  return;
10484
10489
  }
10485
10490
  console.log(`\u2192 ${pm} install in ${remoteDir} on box...`);
10486
- const remoteCmd = `cd ${shellQuote(remoteDir)} && ${cmd}`;
10491
+ const remoteCmd = `cd ${shellQuoteHomePath(remoteDir)} && ${cmd}`;
10487
10492
  const code = await runOnBoxStreaming(provider, remoteCmd);
10488
10493
  if (code !== 0) throw new Error(`${pm} install failed (exit ${code})`);
10489
10494
  const existing = readSidecar(provider, repo);
@@ -10499,7 +10504,7 @@ async function cloudInstall(provider, repo) {
10499
10504
  }
10500
10505
  async function cloudSession(provider, repo) {
10501
10506
  const remoteDir = boxRepoPath(repo);
10502
- const cmd = `sis admin home-init ${shellQuote(repo)} ${shellQuote(remoteDir)}`;
10507
+ const cmd = `sis admin home-init ${shellQuote(repo)} ${shellQuoteHomePath(remoteDir)}`;
10503
10508
  console.log(`\u2192 initializing tmux home session "${repo}" on box...`);
10504
10509
  const result = runOnBox(provider, cmd);
10505
10510
  if (result.exitCode !== 0) {
@@ -10523,6 +10528,19 @@ Use a fresh terminal, or run from outside tmux:
10523
10528
  });
10524
10529
  child.on("exit", (code) => process.exit(code === null ? 1 : code));
10525
10530
  }
10531
+ function cloudClaudeLogin(provider) {
10532
+ const target = effectiveSshTarget(provider);
10533
+ const remote = [
10534
+ "command -v claude >/dev/null 2>&1",
10535
+ "|| sudo npm i -g @anthropic-ai/claude-code",
10536
+ "&& claude auth login"
10537
+ ].join(" ");
10538
+ const child = spawn4("ssh", ["-t", target, remote], {
10539
+ stdio: "inherit",
10540
+ env: EXEC_ENV
10541
+ });
10542
+ child.on("exit", (code) => process.exit(code === null ? 1 : code));
10543
+ }
10526
10544
  async function cloudStart(provider, repo, opts) {
10527
10545
  await cloudSync(provider, repo, { fresh: opts.fresh, yes: opts.yes });
10528
10546
  await cloudInstall(provider, repo);
@@ -10605,6 +10623,10 @@ function registerCloud(program2) {
10605
10623
  const { provider, repo } = resolve11(raw);
10606
10624
  await cloudStart(provider, repo, { fresh: raw.fresh === true, yes: raw.yes === true });
10607
10625
  });
10626
+ cloud.command("claude-login").description("Run `claude auth login` on the box (device-code flow; paste the URL into your local browser).").option("--provider <name>", "Cloud provider.").action((raw) => {
10627
+ const provider = pickProvider(raw.provider);
10628
+ cloudClaudeLogin(provider);
10629
+ });
10608
10630
  cloud.command("status").description("Print box-side status for this repo (planted, session running, last sync/install).").option("--name <repo>", "Override the repo name.").option("--provider <name>", "Cloud provider.").action((raw) => {
10609
10631
  const { provider, repo } = resolve11(raw);
10610
10632
  cloudStatus(provider, repo);