@1claw/cli 0.34.6 → 0.35.0

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 (76) hide show
  1. package/README.md +61 -4
  2. package/dist/bin/1claw.js +0 -0
  3. package/dist/src/commands/containers.d.ts +3 -0
  4. package/dist/src/commands/containers.d.ts.map +1 -0
  5. package/dist/src/commands/containers.js +130 -0
  6. package/dist/src/commands/containers.js.map +1 -0
  7. package/dist/src/commands/daemon.js +35 -11
  8. package/dist/src/commands/daemon.js.map +1 -1
  9. package/dist/src/commands/deploy.d.ts +3 -0
  10. package/dist/src/commands/deploy.d.ts.map +1 -0
  11. package/dist/src/commands/deploy.js +158 -0
  12. package/dist/src/commands/deploy.js.map +1 -0
  13. package/dist/src/commands/eject.d.ts +3 -0
  14. package/dist/src/commands/eject.d.ts.map +1 -0
  15. package/dist/src/commands/eject.js +84 -0
  16. package/dist/src/commands/eject.js.map +1 -0
  17. package/dist/src/commands/import.js +1 -1
  18. package/dist/src/commands/import.js.map +1 -1
  19. package/dist/src/commands/init.d.ts +3 -0
  20. package/dist/src/commands/init.d.ts.map +1 -0
  21. package/dist/src/commands/init.js +475 -0
  22. package/dist/src/commands/init.js.map +1 -0
  23. package/dist/src/commands/publish.d.ts +3 -0
  24. package/dist/src/commands/publish.d.ts.map +1 -0
  25. package/dist/src/commands/publish.js +153 -0
  26. package/dist/src/commands/publish.js.map +1 -0
  27. package/dist/src/deploy/google-cloud/main.tf +74 -0
  28. package/dist/src/deploy/google-cloud/outputs.tf +9 -0
  29. package/dist/src/deploy/google-cloud/variables.tf +44 -0
  30. package/dist/src/docker/base/Dockerfile +34 -0
  31. package/dist/src/docker/base/chat-ui/index.html +110 -0
  32. package/dist/src/docker/base/chat-ui/server.js +233 -0
  33. package/dist/src/docker/base/entrypoint.sh +61 -0
  34. package/dist/src/docker/base/healthcheck.sh +2 -0
  35. package/dist/src/docker/compose.yaml +20 -0
  36. package/dist/src/docker/templates/Dockerfile.tmpl +7 -0
  37. package/dist/src/index.d.ts.map +1 -1
  38. package/dist/src/index.js +11 -0
  39. package/dist/src/index.js.map +1 -1
  40. package/dist/src/lib/container-config.d.ts +43 -0
  41. package/dist/src/lib/container-config.d.ts.map +1 -0
  42. package/dist/src/lib/container-config.js +98 -0
  43. package/dist/src/lib/container-config.js.map +1 -0
  44. package/dist/src/lib/daemon-control.d.ts +10 -0
  45. package/dist/src/lib/daemon-control.d.ts.map +1 -0
  46. package/dist/src/lib/daemon-control.js +58 -0
  47. package/dist/src/lib/daemon-control.js.map +1 -0
  48. package/dist/src/lib/docker-client.d.ts +58 -0
  49. package/dist/src/lib/docker-client.d.ts.map +1 -0
  50. package/dist/src/lib/docker-client.js +193 -0
  51. package/dist/src/lib/docker-client.js.map +1 -0
  52. package/dist/src/lib/image-build.d.ts +30 -0
  53. package/dist/src/lib/image-build.d.ts.map +1 -0
  54. package/dist/src/lib/image-build.js +74 -0
  55. package/dist/src/lib/image-build.js.map +1 -0
  56. package/dist/src/lib/paths.d.ts +14 -0
  57. package/dist/src/lib/paths.d.ts.map +1 -0
  58. package/dist/src/lib/paths.js +38 -0
  59. package/dist/src/lib/paths.js.map +1 -0
  60. package/dist/src/modules/ampersend/config.json +8 -0
  61. package/dist/src/modules/ampersend/module.yaml +32 -0
  62. package/dist/src/modules/ampersend/startup.sh +4 -0
  63. package/dist/src/modules/elizaos/config.json +7 -0
  64. package/dist/src/modules/elizaos/module.yaml +30 -0
  65. package/dist/src/modules/elizaos/startup.sh +3 -0
  66. package/dist/src/modules/langchain/module.yaml +30 -0
  67. package/dist/src/modules/langchain/startup.sh +3 -0
  68. package/dist/src/modules/onchain/module.yaml +28 -0
  69. package/dist/src/modules/onchain/startup.sh +3 -0
  70. package/dist/src/modules/registry.d.ts +48 -0
  71. package/dist/src/modules/registry.d.ts.map +1 -0
  72. package/dist/src/modules/registry.js +201 -0
  73. package/dist/src/modules/registry.js.map +1 -0
  74. package/dist/src/modules/scaffold-agent/module.yaml +30 -0
  75. package/dist/src/modules/scaffold-agent/startup.sh +3 -0
  76. package/package.json +4 -3
@@ -0,0 +1,61 @@
1
+ #!/bin/sh
2
+ # 1Claw agent container entrypoint.
3
+ # Supports two modes:
4
+ # local (ONECLAW_LOCAL_VAULT=true) → credentials injected by the host daemon
5
+ # over the mounted Unix socket. The key
6
+ # NEVER enters the container.
7
+ # cloud (ONECLAW_LOCAL_VAULT=false) → the agent API key is provided directly
8
+ # (e.g. via a Secret Manager mount).
9
+ set -e
10
+
11
+ CHAT_UI_PORT="${CHAT_UI_PORT:-3000}"
12
+
13
+ echo "─────────────────────────────────────────────"
14
+ echo " 1Claw agent container starting"
15
+ echo " Agent ID: ${ONECLAW_AGENT_ID:-not set}"
16
+ echo " Modules: ${ONECLAW_CONTAINER_MODULES:-none}"
17
+
18
+ if [ "$ONECLAW_LOCAL_VAULT" = "true" ]; then
19
+ echo " Mode: local (daemon socket)"
20
+ echo " Socket: $ONECLAW_DAEMON_SOCKET"
21
+ if [ ! -S "$ONECLAW_DAEMON_SOCKET" ]; then
22
+ echo ""
23
+ echo "ERROR: Daemon socket not found at $ONECLAW_DAEMON_SOCKET"
24
+ echo ""
25
+ echo "The 1Claw daemon must be running on the host with the socket mounted:"
26
+ echo " 1claw daemon start"
27
+ echo " docker run -v ~/.config/1claw/daemon.sock:/run/1claw/daemon.sock:ro ..."
28
+ exit 1
29
+ fi
30
+ echo "─────────────────────────────────────────────"
31
+ # Start the MCP server in local daemon mode (best-effort).
32
+ if command -v 1claw-mcp >/dev/null 2>&1; then
33
+ ONECLAW_LOCAL_VAULT=true 1claw-mcp --local 2>/tmp/mcp.log &
34
+ else
35
+ echo "NOTE: @1claw/mcp not installed in image; chat UI uses the daemon directly."
36
+ fi
37
+ else
38
+ echo " Mode: cloud (agent API key)"
39
+ if [ -z "$ONECLAW_AGENT_API_KEY" ]; then
40
+ echo ""
41
+ echo "ERROR: ONECLAW_AGENT_API_KEY is not set (cloud mode)."
42
+ echo "Provide it via a Secret Manager mount or -e ONECLAW_AGENT_API_KEY=..."
43
+ exit 1
44
+ fi
45
+ echo "─────────────────────────────────────────────"
46
+ if command -v 1claw-mcp >/dev/null 2>&1; then
47
+ 1claw-mcp 2>/tmp/mcp.log &
48
+ fi
49
+ fi
50
+
51
+ # Run module startup hooks (each module may drop an executable startup.sh).
52
+ for hook in /app/modules/*/startup.sh; do
53
+ if [ -x "$hook" ]; then
54
+ echo "Running module hook: $hook"
55
+ "$hook" || echo "WARN: module hook $hook exited non-zero"
56
+ fi
57
+ done
58
+
59
+ # Start the chat UI (the container's health anchor) in the foreground.
60
+ echo "Ready: http://0.0.0.0:${CHAT_UI_PORT}"
61
+ exec node /app/chat-ui/server.js
@@ -0,0 +1,2 @@
1
+ #!/bin/sh
2
+ curl -sf "http://localhost:${CHAT_UI_PORT:-3000}/health" >/dev/null || exit 1
@@ -0,0 +1,20 @@
1
+ # docker-compose template for a 1Claw agent container (local daemon mode).
2
+ # Generated by `1claw eject`. The daemon must be running on the host:
3
+ # 1claw daemon start
4
+ services:
5
+ agent:
6
+ image: {{IMAGE}}
7
+ container_name: {{NAME}}
8
+ restart: unless-stopped
9
+ ports:
10
+ - "{{PORT}}:3000"
11
+ volumes:
12
+ # Host daemon socket — credentials are injected here; the container
13
+ # never receives the raw agent key.
14
+ - {{DAEMON_SOCKET}}:/run/1claw/daemon.sock:ro
15
+ environment:
16
+ ONECLAW_LOCAL_VAULT: "true"
17
+ ONECLAW_DAEMON_SOCKET: /run/1claw/daemon.sock
18
+ ONECLAW_AGENT_ID: "{{AGENT_ID}}"
19
+ ONECLAW_CONTAINER_MODULES: "{{MODULES}}"
20
+ CHAT_UI_PORT: "3000"
@@ -0,0 +1,7 @@
1
+ # Generated by `1claw init --docker` / `1claw eject`.
2
+ # Base image provides @1claw/mcp + chat UI + entrypoint. Module layers are
3
+ # appended below. Edit freely, then build with:
4
+ # docker build -t my-agent .
5
+ FROM {{BASE_IMAGE}}
6
+
7
+ {{MODULE_LAYERS}}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA+CpC,wBAAgB,aAAa,IAAI,OAAO,CA0EvC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAoDpC,wBAAgB,aAAa,IAAI,OAAO,CAiFvC"}
package/dist/src/index.js CHANGED
@@ -26,6 +26,11 @@ import { webhookCommand } from "./commands/webhook.js";
26
26
  import { platformCommand } from "./commands/platform.js";
27
27
  import { deviceCommand } from "./commands/device.js";
28
28
  import { approvalCommand } from "./commands/approval.js";
29
+ import { initCommand } from "./commands/init.js";
30
+ import { publishCommand } from "./commands/publish.js";
31
+ import { ejectCommand } from "./commands/eject.js";
32
+ import { containersCommand } from "./commands/containers.js";
33
+ import { deployCommand } from "./commands/deploy.js";
29
34
  import { setOutputFormat, setApiUrl } from "./config.js";
30
35
  const __dirname = dirname(fileURLToPath(import.meta.url));
31
36
  // Compiled to dist/src/index.js → ../../package.json; ts-node from src/ → ../package.json
@@ -65,6 +70,12 @@ export function createProgram() {
65
70
  program.addCommand(importCommand);
66
71
  program.addCommand(localCommand);
67
72
  program.addCommand(daemonCommand);
73
+ // Containerized agent runtime
74
+ program.addCommand(initCommand);
75
+ program.addCommand(publishCommand);
76
+ program.addCommand(ejectCommand);
77
+ program.addCommand(containersCommand);
78
+ program.addCommand(deployCommand);
68
79
  // Config
69
80
  program.addCommand(configCommand);
70
81
  // Treasury
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,43 @@
1
+ export declare const CONTAINERS_DIR: string;
2
+ export interface ContainerState {
3
+ containerName: string;
4
+ containerId: string | null;
5
+ agentId: string | null;
6
+ vaultId: string | null;
7
+ image: string;
8
+ modules: string[];
9
+ port: number;
10
+ createdAt: string;
11
+ /** Local-vault path where the daemon stores the agent key (cloud mode only). */
12
+ localVaultPath: string | null;
13
+ /** Set by `1claw publish` once an image is pushed to a registry. */
14
+ customImage: string | null;
15
+ publishedAt?: string;
16
+ /** "local" (daemon socket) or "cloud" (agent API key direct). */
17
+ mode: "local" | "cloud";
18
+ /** Deployment info, populated by `1claw deploy`. */
19
+ deployment?: {
20
+ provider: string;
21
+ serviceUrl?: string;
22
+ region?: string;
23
+ deployedAt: string;
24
+ };
25
+ }
26
+ /** A short, URL/identifier-safe random id (8 hex chars). */
27
+ export declare function shortId(): string;
28
+ /** Generate a default container name: docker-agent-<shortId>. */
29
+ export declare function generateContainerName(): string;
30
+ /** Restrict names to docker-safe characters. */
31
+ export declare function sanitizeName(name: string): string;
32
+ export declare function isValidContainerName(name: string): boolean;
33
+ export declare function saveContainerState(state: ContainerState): void;
34
+ export declare function loadContainerState(name: string): ContainerState | null;
35
+ export declare function deleteContainerState(name: string): boolean;
36
+ export declare function listContainerStates(): ContainerState[];
37
+ /** Check whether a TCP port is free to bind on localhost. */
38
+ export declare function isPortAvailable(port: number): Promise<boolean>;
39
+ /** Find the first available port at or after `start` (bounded search). */
40
+ export declare function findAvailablePort(start: number): Promise<number>;
41
+ /** Label namespace applied to every CLI-managed container. */
42
+ export declare const MANAGED_LABEL = "1claw.managed";
43
+ //# sourceMappingURL=container-config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"container-config.d.ts","sourceRoot":"","sources":["../../../src/lib/container-config.ts"],"names":[],"mappings":"AAiBA,eAAO,MAAM,cAAc,QAAiC,CAAC;AAE7D,MAAM,WAAW,cAAc;IAC3B,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,gFAAgF;IAChF,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,oEAAoE;IACpE,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iEAAiE;IACjE,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC;IACxB,oDAAoD;IACpD,UAAU,CAAC,EAAE;QACT,QAAQ,EAAE,MAAM,CAAC;QACjB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,UAAU,EAAE,MAAM,CAAC;KACtB,CAAC;CACL;AAYD,4DAA4D;AAC5D,wBAAgB,OAAO,IAAI,MAAM,CAEhC;AAED,iEAAiE;AACjE,wBAAgB,qBAAqB,IAAI,MAAM,CAE9C;AAED,gDAAgD;AAChD,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEjD;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAG1D;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,cAAc,GAAG,IAAI,CAS9D;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI,CAQtE;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAK1D;AAED,wBAAgB,mBAAmB,IAAI,cAAc,EAAE,CAgBtD;AAED,6DAA6D;AAC7D,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAS9D;AAED,0EAA0E;AAC1E,wBAAsB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAOtE;AAED,8DAA8D;AAC9D,eAAO,MAAM,aAAa,kBAAkB,CAAC"}
@@ -0,0 +1,98 @@
1
+ import { existsSync, mkdirSync, readFileSync, writeFileSync, readdirSync, unlinkSync, chmodSync, } from "node:fs";
2
+ import { homedir } from "node:os";
3
+ import { join } from "node:path";
4
+ import { randomBytes } from "node:crypto";
5
+ import { createServer } from "node:net";
6
+ const CONFIG_DIR = process.env.ONECLAW_CONFIG_DIR || join(homedir(), ".config", "1claw");
7
+ export const CONTAINERS_DIR = join(CONFIG_DIR, "containers");
8
+ function ensureContainersDir() {
9
+ if (!existsSync(CONTAINERS_DIR)) {
10
+ mkdirSync(CONTAINERS_DIR, { recursive: true });
11
+ }
12
+ }
13
+ function statePath(name) {
14
+ return join(CONTAINERS_DIR, `${sanitizeName(name)}.json`);
15
+ }
16
+ /** A short, URL/identifier-safe random id (8 hex chars). */
17
+ export function shortId() {
18
+ return randomBytes(4).toString("hex");
19
+ }
20
+ /** Generate a default container name: docker-agent-<shortId>. */
21
+ export function generateContainerName() {
22
+ return `docker-agent-${shortId()}`;
23
+ }
24
+ /** Restrict names to docker-safe characters. */
25
+ export function sanitizeName(name) {
26
+ return name.replace(/[^a-zA-Z0-9_.-]/g, "-");
27
+ }
28
+ export function isValidContainerName(name) {
29
+ // Docker: [a-zA-Z0-9][a-zA-Z0-9_.-]+
30
+ return /^[a-zA-Z0-9][a-zA-Z0-9_.-]*$/.test(name);
31
+ }
32
+ export function saveContainerState(state) {
33
+ ensureContainersDir();
34
+ const path = statePath(state.containerName);
35
+ writeFileSync(path, JSON.stringify(state, null, 2) + "\n", "utf-8");
36
+ try {
37
+ chmodSync(path, 0o600);
38
+ }
39
+ catch {
40
+ // best-effort
41
+ }
42
+ }
43
+ export function loadContainerState(name) {
44
+ const path = statePath(name);
45
+ if (!existsSync(path))
46
+ return null;
47
+ try {
48
+ return JSON.parse(readFileSync(path, "utf-8"));
49
+ }
50
+ catch {
51
+ return null;
52
+ }
53
+ }
54
+ export function deleteContainerState(name) {
55
+ const path = statePath(name);
56
+ if (!existsSync(path))
57
+ return false;
58
+ unlinkSync(path);
59
+ return true;
60
+ }
61
+ export function listContainerStates() {
62
+ if (!existsSync(CONTAINERS_DIR))
63
+ return [];
64
+ const states = [];
65
+ for (const file of readdirSync(CONTAINERS_DIR)) {
66
+ if (!file.endsWith(".json"))
67
+ continue;
68
+ try {
69
+ states.push(JSON.parse(readFileSync(join(CONTAINERS_DIR, file), "utf-8")));
70
+ }
71
+ catch {
72
+ // skip corrupt entries
73
+ }
74
+ }
75
+ return states.sort((a, b) => b.createdAt.localeCompare(a.createdAt));
76
+ }
77
+ /** Check whether a TCP port is free to bind on localhost. */
78
+ export function isPortAvailable(port) {
79
+ return new Promise((resolve) => {
80
+ const server = createServer();
81
+ server.once("error", () => resolve(false));
82
+ server.once("listening", () => {
83
+ server.close(() => resolve(true));
84
+ });
85
+ server.listen(port, "127.0.0.1");
86
+ });
87
+ }
88
+ /** Find the first available port at or after `start` (bounded search). */
89
+ export async function findAvailablePort(start) {
90
+ for (let p = start; p < start + 100; p++) {
91
+ if (await isPortAvailable(p))
92
+ return p;
93
+ }
94
+ throw new Error(`No available port found in range ${start}-${start + 100}.`);
95
+ }
96
+ /** Label namespace applied to every CLI-managed container. */
97
+ export const MANAGED_LABEL = "1claw.managed";
98
+ //# sourceMappingURL=container-config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"container-config.js","sourceRoot":"","sources":["../../../src/lib/container-config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ export declare function daemonSocketPath(): string;
2
+ /** Ping the daemon's /health over its Unix socket. */
3
+ export declare function daemonHealthy(socketPath?: string): Promise<boolean>;
4
+ /**
5
+ * Start the local daemon as a detached background process. The passphrase is
6
+ * passed via the child's environment (ONECLAW_VAULT_PASSPHRASE) so no
7
+ * interactive prompt is needed. Resolves once the socket answers /health.
8
+ */
9
+ export declare function startDaemonDetached(passphrase: string, socketPath?: string, timeoutMs?: number): Promise<boolean>;
10
+ //# sourceMappingURL=daemon-control.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"daemon-control.d.ts","sourceRoot":"","sources":["../../../src/lib/daemon-control.ts"],"names":[],"mappings":"AASA,wBAAgB,gBAAgB,IAAI,MAAM,CAEzC;AAED,sDAAsD;AACtD,wBAAgB,aAAa,CAAC,UAAU,SAAqB,GAAG,OAAO,CAAC,OAAO,CAAC,CAoB/E;AAED;;;;GAIG;AACH,wBAAsB,mBAAmB,CACrC,UAAU,EAAE,MAAM,EAClB,UAAU,SAAqB,EAC/B,SAAS,SAAQ,GAClB,OAAO,CAAC,OAAO,CAAC,CAwBlB"}
@@ -0,0 +1,58 @@
1
+ import { request as httpRequest } from "node:http";
2
+ import { spawn } from "node:child_process";
3
+ import { existsSync } from "node:fs";
4
+ import { homedir } from "node:os";
5
+ import { join } from "node:path";
6
+ const CONFIG_DIR = process.env.ONECLAW_CONFIG_DIR || join(homedir(), ".config", "1claw");
7
+ export function daemonSocketPath() {
8
+ return process.env.ONECLAW_DAEMON_SOCKET || join(CONFIG_DIR, "daemon.sock");
9
+ }
10
+ /** Ping the daemon's /health over its Unix socket. */
11
+ export function daemonHealthy(socketPath = daemonSocketPath()) {
12
+ return new Promise((resolve) => {
13
+ if (!existsSync(socketPath)) {
14
+ resolve(false);
15
+ return;
16
+ }
17
+ const req = httpRequest({ socketPath, path: "/health", method: "GET", timeout: 2000 }, (res) => {
18
+ res.resume();
19
+ resolve(res.statusCode === 200);
20
+ });
21
+ req.on("error", () => resolve(false));
22
+ req.on("timeout", () => {
23
+ req.destroy();
24
+ resolve(false);
25
+ });
26
+ req.end();
27
+ });
28
+ }
29
+ /**
30
+ * Start the local daemon as a detached background process. The passphrase is
31
+ * passed via the child's environment (ONECLAW_VAULT_PASSPHRASE) so no
32
+ * interactive prompt is needed. Resolves once the socket answers /health.
33
+ */
34
+ export async function startDaemonDetached(passphrase, socketPath = daemonSocketPath(), timeoutMs = 10000) {
35
+ // process.argv[1] is the CLI entry (dist/bin/1claw.js). Re-invoke it so the
36
+ // daemon runs the same code path in both dev and installed environments.
37
+ const cliEntry = process.argv[1];
38
+ const child = spawn(process.execPath, [cliEntry, "daemon", "start", "--socket", socketPath], {
39
+ detached: true,
40
+ stdio: "ignore",
41
+ env: {
42
+ ...process.env,
43
+ ONECLAW_VAULT_PASSPHRASE: passphrase,
44
+ },
45
+ });
46
+ child.unref();
47
+ const deadline = Date.now() + timeoutMs;
48
+ while (Date.now() < deadline) {
49
+ if (await daemonHealthy(socketPath))
50
+ return true;
51
+ await sleep(250);
52
+ }
53
+ return false;
54
+ }
55
+ function sleep(ms) {
56
+ return new Promise((r) => setTimeout(r, ms));
57
+ }
58
+ //# sourceMappingURL=daemon-control.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"daemon-control.js","sourceRoot":"","sources":["../../../src/lib/daemon-control.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,WAAW,CAAC;AACnD,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,MAAM,UAAU,GACZ,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;AAE1E,MAAM,UAAU,gBAAgB;IAC5B,OAAO,OAAO,CAAC,GAAG,CAAC,qBAAqB,IAAI,IAAI,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;AAChF,CAAC;AAED,sDAAsD;AACtD,MAAM,UAAU,aAAa,CAAC,UAAU,GAAG,gBAAgB,EAAE;IACzD,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC3B,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;YAC1B,OAAO,CAAC,KAAK,CAAC,CAAC;YACf,OAAO;QACX,CAAC;QACD,MAAM,GAAG,GAAG,WAAW,CACnB,EAAE,UAAU,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,EAC7D,CAAC,GAAG,EAAE,EAAE;YACJ,GAAG,CAAC,MAAM,EAAE,CAAC;YACb,OAAO,CAAC,GAAG,CAAC,UAAU,KAAK,GAAG,CAAC,CAAC;QACpC,CAAC,CACJ,CAAC;QACF,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;QACtC,GAAG,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE;YACnB,GAAG,CAAC,OAAO,EAAE,CAAC;YACd,OAAO,CAAC,KAAK,CAAC,CAAC;QACnB,CAAC,CAAC,CAAC;QACH,GAAG,CAAC,GAAG,EAAE,CAAC;IACd,CAAC,CAAC,CAAC;AACP,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACrC,UAAkB,EAClB,UAAU,GAAG,gBAAgB,EAAE,EAC/B,SAAS,GAAG,KAAK;IAEjB,4EAA4E;IAC5E,yEAAyE;IACzE,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACjC,MAAM,KAAK,GAAG,KAAK,CACf,OAAO,CAAC,QAAQ,EAChB,CAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,UAAU,EAAE,UAAU,CAAC,EACrD;QACI,QAAQ,EAAE,IAAI;QACd,KAAK,EAAE,QAAQ;QACf,GAAG,EAAE;YACD,GAAG,OAAO,CAAC,GAAG;YACd,wBAAwB,EAAE,UAAU;SACvC;KACJ,CACJ,CAAC;IACF,KAAK,CAAC,KAAK,EAAE,CAAC;IAEd,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;IACxC,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,QAAQ,EAAE,CAAC;QAC3B,IAAI,MAAM,aAAa,CAAC,UAAU,CAAC;YAAE,OAAO,IAAI,CAAC;QACjD,MAAM,KAAK,CAAC,GAAG,CAAC,CAAC;IACrB,CAAC;IACD,OAAO,KAAK,CAAC;AACjB,CAAC;AAED,SAAS,KAAK,CAAC,EAAU;IACrB,OAAO,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;AACjD,CAAC"}
@@ -0,0 +1,58 @@
1
+ import { type ChildProcess } from "node:child_process";
2
+ /**
3
+ * Thin wrapper around the Docker CLI via `child_process.execFile`.
4
+ *
5
+ * We deliberately avoid `dockerode` / any Docker SDK to keep the CLI's
6
+ * dependency surface minimal. Every call shells out to the local `docker`
7
+ * binary with an argv array (never a `/bin/sh -c` string), so user-supplied
8
+ * values (image names, env values, tags) cannot inject shell metacharacters.
9
+ */
10
+ export interface DockerRunOptions {
11
+ image: string;
12
+ name: string;
13
+ /** Host port → container port, e.g. { "3000": "3000" } */
14
+ ports: Record<string, string>;
15
+ /** Host path → container mount spec, e.g. { "/host/x.sock": "/run/x.sock:ro" } */
16
+ volumes: Record<string, string>;
17
+ env: Record<string, string>;
18
+ detach: boolean;
19
+ restart?: string;
20
+ labels?: Record<string, string>;
21
+ }
22
+ export interface DockerBuildOptions {
23
+ context: string;
24
+ dockerfile: string;
25
+ tag: string;
26
+ buildArgs?: Record<string, string>;
27
+ onProgress?: (line: string) => void;
28
+ }
29
+ declare class DockerError extends Error {
30
+ stderr?: string | undefined;
31
+ constructor(message: string, stderr?: string | undefined);
32
+ }
33
+ export declare function dockerAvailable(): Promise<boolean>;
34
+ /** True if Docker is installed but the daemon is unreachable. */
35
+ export declare function dockerDaemonError(): Promise<string | null>;
36
+ export declare function dockerImageExists(image: string): Promise<boolean>;
37
+ export declare function dockerPull(image: string, onProgress?: (line: string) => void): Promise<void>;
38
+ export declare function dockerBuild(opts: DockerBuildOptions): Promise<string>;
39
+ export declare function dockerRun(opts: DockerRunOptions): Promise<string>;
40
+ export declare function dockerStop(nameOrId: string): Promise<void>;
41
+ export declare function dockerRm(nameOrId: string, force?: boolean): Promise<void>;
42
+ export declare function dockerInspect(nameOrId: string): Promise<unknown>;
43
+ export interface ContainerStatus {
44
+ exists: boolean;
45
+ running: boolean;
46
+ status?: string;
47
+ health?: string;
48
+ }
49
+ export declare function dockerContainerStatus(nameOrId: string): Promise<ContainerStatus>;
50
+ export declare function dockerPush(tag: string, onProgress?: (line: string) => void): Promise<void>;
51
+ export declare function dockerTag(source: string, target: string): Promise<void>;
52
+ export declare function dockerCommit(container: string, tag: string): Promise<string>;
53
+ /** Spawn `docker logs -f` and return the child process so the caller streams it. */
54
+ export declare function dockerLogs(nameOrId: string, follow: boolean): ChildProcess;
55
+ /** True if the local docker client is authenticated to the given registry. */
56
+ export declare function dockerLoggedIn(registry?: string): Promise<boolean>;
57
+ export { DockerError };
58
+ //# sourceMappingURL=docker-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"docker-client.d.ts","sourceRoot":"","sources":["../../../src/lib/docker-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAExE;;;;;;;GAOG;AAEH,MAAM,WAAW,gBAAgB;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,0DAA0D;IAC1D,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,kFAAkF;IAClF,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5B,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACnC;AAED,MAAM,WAAW,kBAAkB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACvC;AAED,cAAM,WAAY,SAAQ,KAAK;IAGhB,MAAM,CAAC,EAAE,MAAM;gBADtB,OAAO,EAAE,MAAM,EACR,MAAM,CAAC,EAAE,MAAM,YAAA;CAK7B;AAmFD,wBAAsB,eAAe,IAAI,OAAO,CAAC,OAAO,CAAC,CAOxD;AAED,iEAAiE;AACjE,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAOhE;AAED,wBAAsB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAOvE;AAED,wBAAsB,UAAU,CAC5B,KAAK,EAAE,MAAM,EACb,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GACpC,OAAO,CAAC,IAAI,CAAC,CAEf;AAED,wBAAsB,WAAW,CAAC,IAAI,EAAE,kBAAkB,GAAG,OAAO,CAAC,MAAM,CAAC,CAY3E;AAED,wBAAsB,SAAS,CAAC,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC,MAAM,CAAC,CAmBvE;AAED,wBAAsB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAEhE;AAED,wBAAsB,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,UAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAK7E;AAED,wBAAsB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAItE;AAED,MAAM,WAAW,eAAe;IAC5B,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,wBAAsB,qBAAqB,CACvC,QAAQ,EAAE,MAAM,GACjB,OAAO,CAAC,eAAe,CAAC,CAkB1B;AAED,wBAAsB,UAAU,CAC5B,GAAG,EAAE,MAAM,EACX,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GACpC,OAAO,CAAC,IAAI,CAAC,CAEf;AAED,wBAAsB,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE7E;AAED,wBAAsB,YAAY,CAC9B,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,MAAM,GACZ,OAAO,CAAC,MAAM,CAAC,CAGjB;AAED,oFAAoF;AACpF,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,YAAY,CAK1E;AAED,8EAA8E;AAC9E,wBAAsB,cAAc,CAAC,QAAQ,SAAgC,GAAG,OAAO,CAAC,OAAO,CAAC,CAa/F;AAED,OAAO,EAAE,WAAW,EAAE,CAAC"}
@@ -0,0 +1,193 @@
1
+ import { execFile, spawn } from "node:child_process";
2
+ class DockerError extends Error {
3
+ stderr;
4
+ constructor(message, stderr) {
5
+ super(message);
6
+ this.stderr = stderr;
7
+ this.name = "DockerError";
8
+ }
9
+ }
10
+ function run(args, opts = {}) {
11
+ return new Promise((resolve, reject) => {
12
+ execFile("docker", args, { cwd: opts.cwd, maxBuffer: 64 * 1024 * 1024 }, (err, stdout, stderr) => {
13
+ if (err) {
14
+ reject(translateError(err, stderr));
15
+ return;
16
+ }
17
+ resolve({ stdout: stdout.toString(), stderr: stderr.toString() });
18
+ });
19
+ });
20
+ }
21
+ function translateError(err, stderr) {
22
+ if (err.code === "ENOENT") {
23
+ return new DockerError("Docker is not installed or not on your PATH. Install Docker Desktop (https://docs.docker.com/get-docker/) and try again.");
24
+ }
25
+ const s = (stderr || "").trim();
26
+ if (s.includes("Cannot connect to the Docker daemon") ||
27
+ s.includes("Is the docker daemon running")) {
28
+ return new DockerError("Docker is not running. Start Docker Desktop, or run `sudo systemctl start docker` on Linux.", s);
29
+ }
30
+ return new DockerError(s || err.message || "docker command failed", s);
31
+ }
32
+ /** Stream a long-running docker command, forwarding output line-by-line. */
33
+ function runStreaming(args, onProgress, cwd) {
34
+ return new Promise((resolve, reject) => {
35
+ const child = spawn("docker", args, { cwd });
36
+ let stderrTail = "";
37
+ const onData = (buf) => {
38
+ const text = buf.toString();
39
+ stderrTail = (stderrTail + text).slice(-4096);
40
+ if (onProgress) {
41
+ for (const line of text.split("\n")) {
42
+ if (line.trim())
43
+ onProgress(line.trimEnd());
44
+ }
45
+ }
46
+ };
47
+ child.stdout?.on("data", onData);
48
+ child.stderr?.on("data", onData);
49
+ child.on("error", (err) => reject(translateError(err, stderrTail)));
50
+ child.on("close", (code) => {
51
+ if (code === 0)
52
+ resolve();
53
+ else
54
+ reject(new DockerError(`docker ${args[0]} exited with code ${code}`, stderrTail));
55
+ });
56
+ });
57
+ }
58
+ export async function dockerAvailable() {
59
+ try {
60
+ await run(["info", "--format", "{{.ServerVersion}}"]);
61
+ return true;
62
+ }
63
+ catch {
64
+ return false;
65
+ }
66
+ }
67
+ /** True if Docker is installed but the daemon is unreachable. */
68
+ export async function dockerDaemonError() {
69
+ try {
70
+ await run(["info", "--format", "{{.ServerVersion}}"]);
71
+ return null;
72
+ }
73
+ catch (err) {
74
+ return err instanceof Error ? err.message : String(err);
75
+ }
76
+ }
77
+ export async function dockerImageExists(image) {
78
+ try {
79
+ await run(["image", "inspect", image]);
80
+ return true;
81
+ }
82
+ catch {
83
+ return false;
84
+ }
85
+ }
86
+ export async function dockerPull(image, onProgress) {
87
+ await runStreaming(["pull", image], onProgress);
88
+ }
89
+ export async function dockerBuild(opts) {
90
+ const args = ["build", "-t", opts.tag, "-f", opts.dockerfile];
91
+ if (opts.buildArgs) {
92
+ for (const [k, v] of Object.entries(opts.buildArgs)) {
93
+ args.push("--build-arg", `${k}=${v}`);
94
+ }
95
+ }
96
+ args.push(opts.context);
97
+ await runStreaming(args, opts.onProgress);
98
+ // Resolve the built image ID.
99
+ const { stdout } = await run(["image", "inspect", opts.tag, "--format", "{{.Id}}"]);
100
+ return stdout.trim();
101
+ }
102
+ export async function dockerRun(opts) {
103
+ const args = ["run", "--name", opts.name];
104
+ args.push(opts.detach ? "-d" : "-d"); // always detached; logs streamed separately
105
+ if (opts.restart)
106
+ args.push("--restart", opts.restart);
107
+ for (const [host, container] of Object.entries(opts.ports)) {
108
+ args.push("-p", `${host}:${container}`);
109
+ }
110
+ for (const [host, container] of Object.entries(opts.volumes)) {
111
+ args.push("-v", `${host}:${container}`);
112
+ }
113
+ for (const [k, v] of Object.entries(opts.env)) {
114
+ args.push("-e", `${k}=${v}`);
115
+ }
116
+ for (const [k, v] of Object.entries(opts.labels ?? {})) {
117
+ args.push("--label", `${k}=${v}`);
118
+ }
119
+ args.push(opts.image);
120
+ const { stdout } = await run(args);
121
+ return stdout.trim();
122
+ }
123
+ export async function dockerStop(nameOrId) {
124
+ await run(["stop", nameOrId]);
125
+ }
126
+ export async function dockerRm(nameOrId, force = false) {
127
+ const args = ["rm"];
128
+ if (force)
129
+ args.push("-f");
130
+ args.push(nameOrId);
131
+ await run(args);
132
+ }
133
+ export async function dockerInspect(nameOrId) {
134
+ const { stdout } = await run(["inspect", nameOrId]);
135
+ const parsed = JSON.parse(stdout);
136
+ return Array.isArray(parsed) ? parsed[0] : parsed;
137
+ }
138
+ export async function dockerContainerStatus(nameOrId) {
139
+ try {
140
+ const { stdout } = await run([
141
+ "inspect",
142
+ nameOrId,
143
+ "--format",
144
+ "{{.State.Status}}|{{if .State.Health}}{{.State.Health.Status}}{{else}}none{{end}}",
145
+ ]);
146
+ const [status, health] = stdout.trim().split("|");
147
+ return {
148
+ exists: true,
149
+ running: status === "running",
150
+ status,
151
+ health: health === "none" ? undefined : health,
152
+ };
153
+ }
154
+ catch {
155
+ return { exists: false, running: false };
156
+ }
157
+ }
158
+ export async function dockerPush(tag, onProgress) {
159
+ await runStreaming(["push", tag], onProgress);
160
+ }
161
+ export async function dockerTag(source, target) {
162
+ await run(["tag", source, target]);
163
+ }
164
+ export async function dockerCommit(container, tag) {
165
+ const { stdout } = await run(["commit", container, tag]);
166
+ return stdout.trim();
167
+ }
168
+ /** Spawn `docker logs -f` and return the child process so the caller streams it. */
169
+ export function dockerLogs(nameOrId, follow) {
170
+ const args = ["logs"];
171
+ if (follow)
172
+ args.push("-f");
173
+ args.push(nameOrId);
174
+ return spawn("docker", args, { stdio: ["ignore", "inherit", "inherit"] });
175
+ }
176
+ /** True if the local docker client is authenticated to the given registry. */
177
+ export async function dockerLoggedIn(registry = "https://index.docker.io/v1/") {
178
+ try {
179
+ const { stdout } = await run(["system", "info", "--format", "{{json .}}"]);
180
+ const info = JSON.parse(stdout);
181
+ // `docker info` doesn't reliably expose auth; fall back to checking the
182
+ // config file via `docker logout --help`-free heuristic is unreliable,
183
+ // so we simply return true and let `docker push` surface auth errors.
184
+ void info;
185
+ void registry;
186
+ return true;
187
+ }
188
+ catch {
189
+ return true;
190
+ }
191
+ }
192
+ export { DockerError };
193
+ //# sourceMappingURL=docker-client.js.map