yolobox 0.1.5 → 0.1.6
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 +101 -6
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -247,6 +247,17 @@ function execInContainer(id, command) {
|
|
|
247
247
|
log(`Exec exited with code ${result.status}`);
|
|
248
248
|
return result.status ?? 1;
|
|
249
249
|
}
|
|
250
|
+
function execInContainerNonInteractive(id, command) {
|
|
251
|
+
const args = ["exec", `yolobox-${id}`, ...command];
|
|
252
|
+
log(`Exec (non-interactive) in container: docker ${args.join(" ")}`);
|
|
253
|
+
const result = spawnSync("docker", args, { stdio: ["pipe", "pipe", "pipe"] });
|
|
254
|
+
logCommand("docker", args, {
|
|
255
|
+
status: result.status,
|
|
256
|
+
stdout: result.stdout?.toString() || "",
|
|
257
|
+
stderr: result.stderr?.toString() || ""
|
|
258
|
+
});
|
|
259
|
+
return result.status === 0;
|
|
260
|
+
}
|
|
250
261
|
function timeAgo(dateStr) {
|
|
251
262
|
const date = new Date(dateStr);
|
|
252
263
|
const seconds = Math.floor((Date.now() - date.getTime()) / 1e3);
|
|
@@ -317,7 +328,7 @@ function killContainer(id) {
|
|
|
317
328
|
import * as p from "@clack/prompts";
|
|
318
329
|
import pc2 from "picocolors";
|
|
319
330
|
function intro2() {
|
|
320
|
-
p.intro(pc2.bgCyan(pc2.black(` yolobox v${"0.1.
|
|
331
|
+
p.intro(pc2.bgCyan(pc2.black(` yolobox v${"0.1.6"} `)));
|
|
321
332
|
}
|
|
322
333
|
function success(message) {
|
|
323
334
|
p.log.success(message);
|
|
@@ -569,10 +580,11 @@ function showStatus() {
|
|
|
569
580
|
import { defineCommand as defineCommand3 } from "citty";
|
|
570
581
|
|
|
571
582
|
// src/lib/container-setup.ts
|
|
583
|
+
import fs2 from "fs";
|
|
572
584
|
import path2 from "path";
|
|
573
585
|
|
|
574
586
|
// src/lib/git.ts
|
|
575
|
-
import { execSync as execSync2 } from "child_process";
|
|
587
|
+
import { execSync as execSync2, spawnSync as spawnSync2 } from "child_process";
|
|
576
588
|
function exec(cmd) {
|
|
577
589
|
return execSync2(cmd, {
|
|
578
590
|
encoding: "utf-8",
|
|
@@ -637,6 +649,28 @@ function getGitIdentity() {
|
|
|
637
649
|
return { name: "", email: "" };
|
|
638
650
|
}
|
|
639
651
|
}
|
|
652
|
+
function listUntrackedFiles(repoRoot, pathspec) {
|
|
653
|
+
const result = spawnSync2(
|
|
654
|
+
"git",
|
|
655
|
+
[
|
|
656
|
+
"-C",
|
|
657
|
+
repoRoot,
|
|
658
|
+
"ls-files",
|
|
659
|
+
"--others",
|
|
660
|
+
"--exclude-standard",
|
|
661
|
+
"--",
|
|
662
|
+
pathspec
|
|
663
|
+
],
|
|
664
|
+
{
|
|
665
|
+
encoding: "utf-8",
|
|
666
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
667
|
+
}
|
|
668
|
+
);
|
|
669
|
+
if (result.status !== 0) return [];
|
|
670
|
+
const output = result.stdout?.trim() ?? "";
|
|
671
|
+
if (!output) return [];
|
|
672
|
+
return output.split("\n").filter(Boolean);
|
|
673
|
+
}
|
|
640
674
|
|
|
641
675
|
// src/lib/id.ts
|
|
642
676
|
var ADJECTIVES = [
|
|
@@ -1408,6 +1442,44 @@ function getExistingWorktreeIds(repoRoot) {
|
|
|
1408
1442
|
}
|
|
1409
1443
|
|
|
1410
1444
|
// src/lib/container-setup.ts
|
|
1445
|
+
function copyUntrackedFilesFromCwd(options) {
|
|
1446
|
+
const { repoRoot, worktreePath, cwd } = options;
|
|
1447
|
+
const relativeCwd = path2.relative(repoRoot, cwd);
|
|
1448
|
+
if (relativeCwd.startsWith("..") || path2.isAbsolute(relativeCwd)) {
|
|
1449
|
+
log(`Skipping untracked copy: cwd outside repo (${cwd})`);
|
|
1450
|
+
return 0;
|
|
1451
|
+
}
|
|
1452
|
+
if (relativeCwd.split(path2.sep).includes(".yolobox")) {
|
|
1453
|
+
log(`Skipping untracked copy: cwd inside .yolobox (${cwd})`);
|
|
1454
|
+
return 0;
|
|
1455
|
+
}
|
|
1456
|
+
const pathspec = relativeCwd === "" ? "." : relativeCwd;
|
|
1457
|
+
const files = listUntrackedFiles(repoRoot, pathspec);
|
|
1458
|
+
if (files.length === 0) return 0;
|
|
1459
|
+
let copied = 0;
|
|
1460
|
+
for (const file of files) {
|
|
1461
|
+
const src = path2.join(repoRoot, file);
|
|
1462
|
+
const dest = path2.join(worktreePath, file);
|
|
1463
|
+
try {
|
|
1464
|
+
if (fs2.existsSync(dest)) continue;
|
|
1465
|
+
fs2.mkdirSync(path2.dirname(dest), { recursive: true });
|
|
1466
|
+
const stat = fs2.lstatSync(src);
|
|
1467
|
+
if (stat.isSymbolicLink()) {
|
|
1468
|
+
const target = fs2.readlinkSync(src);
|
|
1469
|
+
fs2.symlinkSync(target, dest);
|
|
1470
|
+
} else if (stat.isDirectory()) {
|
|
1471
|
+
fs2.mkdirSync(dest, { recursive: true });
|
|
1472
|
+
} else {
|
|
1473
|
+
fs2.copyFileSync(src, dest);
|
|
1474
|
+
}
|
|
1475
|
+
copied++;
|
|
1476
|
+
} catch (err) {
|
|
1477
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
1478
|
+
log(`Failed to copy untracked file "${file}": ${message}`);
|
|
1479
|
+
}
|
|
1480
|
+
}
|
|
1481
|
+
return copied;
|
|
1482
|
+
}
|
|
1411
1483
|
async function setupContainer(options = {}) {
|
|
1412
1484
|
intro2();
|
|
1413
1485
|
if (isEnabled()) {
|
|
@@ -1471,6 +1543,18 @@ async function setupContainer(options = {}) {
|
|
|
1471
1543
|
success(`Created worktree .yolobox/${id} (branch: yolo/${id})`);
|
|
1472
1544
|
}
|
|
1473
1545
|
ensureGitignore(repoRoot);
|
|
1546
|
+
if (!worktreeAlreadyExists && !branchAlreadyExists) {
|
|
1547
|
+
const copied = copyUntrackedFilesFromCwd({
|
|
1548
|
+
repoRoot,
|
|
1549
|
+
worktreePath,
|
|
1550
|
+
cwd: process.cwd()
|
|
1551
|
+
});
|
|
1552
|
+
if (copied > 0) {
|
|
1553
|
+
const cwdRel = path2.relative(repoRoot, process.cwd()) || ".";
|
|
1554
|
+
const label = copied === 1 ? "file" : "files";
|
|
1555
|
+
info(`Copied ${copied} untracked ${label} from ${cwdRel}`);
|
|
1556
|
+
}
|
|
1557
|
+
}
|
|
1474
1558
|
const gitIdentity = getGitIdentity();
|
|
1475
1559
|
log("Resolving Docker image...");
|
|
1476
1560
|
const imageResolution = resolveDockerImage({
|
|
@@ -1546,6 +1630,17 @@ async function setupContainer(options = {}) {
|
|
|
1546
1630
|
}
|
|
1547
1631
|
process.exit(1);
|
|
1548
1632
|
}
|
|
1633
|
+
const safeDirOk = execInContainerNonInteractive(id, [
|
|
1634
|
+
"git",
|
|
1635
|
+
"config",
|
|
1636
|
+
"--global",
|
|
1637
|
+
"--add",
|
|
1638
|
+
"safe.directory",
|
|
1639
|
+
"/workspace"
|
|
1640
|
+
]);
|
|
1641
|
+
if (!safeDirOk) {
|
|
1642
|
+
log("Failed to mark /workspace as a safe git directory");
|
|
1643
|
+
}
|
|
1549
1644
|
return { id, repoRoot };
|
|
1550
1645
|
}
|
|
1551
1646
|
|
|
@@ -1578,7 +1673,7 @@ var claude_default = defineCommand3({
|
|
|
1578
1673
|
});
|
|
1579
1674
|
|
|
1580
1675
|
// src/commands/help.ts
|
|
1581
|
-
import { spawnSync as
|
|
1676
|
+
import { spawnSync as spawnSync3 } from "child_process";
|
|
1582
1677
|
import { defineCommand as defineCommand4 } from "citty";
|
|
1583
1678
|
var help_default = defineCommand4({
|
|
1584
1679
|
meta: {
|
|
@@ -1586,7 +1681,7 @@ var help_default = defineCommand4({
|
|
|
1586
1681
|
description: "Show help information"
|
|
1587
1682
|
},
|
|
1588
1683
|
run: async () => {
|
|
1589
|
-
const result =
|
|
1684
|
+
const result = spawnSync3(process.argv[0], [process.argv[1], "--help"], {
|
|
1590
1685
|
stdio: "inherit"
|
|
1591
1686
|
});
|
|
1592
1687
|
process.exit(result.status || 0);
|
|
@@ -2023,7 +2118,7 @@ var debugIndex = process.argv.indexOf("--debug");
|
|
|
2023
2118
|
if (debugIndex !== -1) {
|
|
2024
2119
|
process.argv.splice(debugIndex, 1);
|
|
2025
2120
|
const logPath = enable();
|
|
2026
|
-
log(`yolobox v${"0.1.
|
|
2121
|
+
log(`yolobox v${"0.1.6"}`);
|
|
2027
2122
|
log(`args: ${process.argv.slice(2).join(" ")}`);
|
|
2028
2123
|
log(`cwd: ${process.cwd()}`);
|
|
2029
2124
|
log(`node: ${process.version}`);
|
|
@@ -2033,7 +2128,7 @@ if (debugIndex !== -1) {
|
|
|
2033
2128
|
var main = defineCommand10({
|
|
2034
2129
|
meta: {
|
|
2035
2130
|
name: "yolobox",
|
|
2036
|
-
version: "0.1.
|
|
2131
|
+
version: "0.1.6",
|
|
2037
2132
|
description: "Run Claude Code in Docker containers. YOLO safely."
|
|
2038
2133
|
},
|
|
2039
2134
|
subCommands: {
|