claw-zero 0.1.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.
package/README.md ADDED
@@ -0,0 +1,96 @@
1
+ # One-Click Claw
2
+
3
+ A Node.js CLI that installs and sandboxes the [OpenClaw](https://github.com/openclaw/openclaw) AI agent on your local Mac with zero manual configuration.
4
+
5
+ **What it does in one command:**
6
+ - Checks for Docker (installs via Homebrew if missing)
7
+ - Creates `~/Desktop/OpenClaw_Workspace`
8
+ - Generates a `clawdbot.json` security config based on your chosen profile
9
+ - Pulls `ghcr.io/openclaw/openclaw:latest` and boots it on `localhost:3845`
10
+
11
+ ---
12
+
13
+ ## Prerequisites
14
+
15
+ | Requirement | Notes |
16
+ |---|---|
17
+ | macOS | Homebrew auto-install is Mac-only for MVP |
18
+ | Node.js ≥ 18 | ESModules + native `fetch` |
19
+ | Docker Desktop | Auto-installed via Homebrew if absent |
20
+ | Anthropic or OpenAI API key | Entered during setup; never stored in plaintext |
21
+
22
+ ---
23
+
24
+ ## Quickstart
25
+
26
+ ```bash
27
+ git clone <repo-url> claw_zero
28
+ cd claw_zero
29
+ npm install
30
+ npm start
31
+ ```
32
+
33
+ Follow the interactive prompts — the entire setup takes under 2 minutes.
34
+
35
+ ---
36
+
37
+ ## Security Profiles
38
+
39
+ Choose a profile during setup. The selection writes a `clawdbot.json` to your workspace.
40
+
41
+ | Profile | Sandbox | Workspace | Human Approval Required | Skill Trust | Budget |
42
+ |---|---|---|---|---|---|
43
+ | **Fort Knox** | `all` | Read-only | All commands | None | 100k tokens |
44
+ | **Pragmatic PM** *(default)* | `non-main` | Scoped | `rm`, `sudo`, `curl`, `wget`, `git push`, `npm publish` | Verified only | 500k tokens |
45
+ | **Cowboy Coder** | `off` | Scoped | `sudo`, `rm -rf` | All | 2M tokens |
46
+ | **YOLO Mode** | `off` | Read-write | None | All | Unlimited |
47
+
48
+ ---
49
+
50
+ ## Container Details
51
+
52
+ | Parameter | Value |
53
+ |---|---|
54
+ | Image | `ghcr.io/openclaw/openclaw:latest` |
55
+ | Container name | `openclaw_sandbox` |
56
+ | Port | `3845` → `localhost:3845` |
57
+ | Volume mount | `~/Desktop/OpenClaw_Workspace:/workspace` |
58
+ | API key env var | `ANTHROPIC_API_KEY` |
59
+
60
+ The container runs with `--detach --rm` — it stops automatically when Docker restarts.
61
+
62
+ ---
63
+
64
+ ## Key Environment Variables
65
+
66
+ None required at the host level. The API key is collected interactively and passed directly to the container via `--env`.
67
+
68
+ ---
69
+
70
+ ## Project Structure
71
+
72
+ ```
73
+ claw_zero/
74
+ ├── src/
75
+ │ ├── index.ts # Entry point — UI flow
76
+ │ ├── types.ts # TypeScript types
77
+ │ ├── profiles.ts # Security profile config map
78
+ │ ├── config.ts # clawdbot.json generation
79
+ │ ├── docker.ts # Docker detection, install, daemon start
80
+ │ ├── workspace.ts # Workspace directory creation
81
+ │ └── container.ts # Image pull + container launch
82
+ ├── PRD.md
83
+ ├── tasks.md
84
+ └── architecture.md
85
+ ```
86
+
87
+ ---
88
+
89
+ ## Scripts
90
+
91
+ | Command | Action |
92
+ |---|---|
93
+ | `npm start` | Run the CLI via `tsx` |
94
+ | `npm run build` | Compile TypeScript to `dist/` |
95
+ | `npm run dev` | Same as `start` (alias) |
96
+ | `npx tsc --noEmit` | Type-check without emitting |
@@ -0,0 +1,6 @@
1
+ import type { SecurityProfileKey } from './types.js';
2
+ export declare const WORKSPACE_PATH: string;
3
+ export declare const CONFIG_FILENAME = "clawdbot.json";
4
+ /** Generates clawdbot.json and writes it to the workspace directory. */
5
+ export declare function generateConfig(profileKey: SecurityProfileKey, apiKey: string): Promise<void>;
6
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAGrD,eAAO,MAAM,cAAc,QAAmD,CAAC;AAC/E,eAAO,MAAM,eAAe,kBAAkB,CAAC;AAE/C,wEAAwE;AACxE,wBAAsB,cAAc,CAClC,UAAU,EAAE,kBAAkB,EAC9B,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,IAAI,CAAC,CAef"}
package/dist/config.js ADDED
@@ -0,0 +1,19 @@
1
+ import { writeFile, mkdir } from 'node:fs/promises';
2
+ import { join } from 'node:path';
3
+ import { homedir } from 'node:os';
4
+ import { PROFILES } from './profiles.js';
5
+ export const WORKSPACE_PATH = join(homedir(), 'Desktop', 'OpenClaw_Workspace');
6
+ export const CONFIG_FILENAME = 'clawdbot.json';
7
+ /** Generates clawdbot.json and writes it to the workspace directory. */
8
+ export async function generateConfig(profileKey, apiKey) {
9
+ const profile = PROFILES[profileKey];
10
+ if (!profile)
11
+ throw new Error(`Unknown profile: ${profileKey}`);
12
+ const configData = {
13
+ ...profile.config,
14
+ api_key: apiKey,
15
+ };
16
+ await mkdir(WORKSPACE_PATH, { recursive: true });
17
+ await writeFile(join(WORKSPACE_PATH, CONFIG_FILENAME), JSON.stringify(configData, null, 2), 'utf-8');
18
+ }
19
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAElC,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEzC,MAAM,CAAC,MAAM,cAAc,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,oBAAoB,CAAC,CAAC;AAC/E,MAAM,CAAC,MAAM,eAAe,GAAG,eAAe,CAAC;AAE/C,wEAAwE;AACxE,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,UAA8B,EAC9B,MAAc;IAEd,MAAM,OAAO,GAAG,QAAQ,CAAC,UAAU,CAAC,CAAC;IACrC,IAAI,CAAC,OAAO;QAAE,MAAM,IAAI,KAAK,CAAC,oBAAoB,UAAU,EAAE,CAAC,CAAC;IAEhE,MAAM,UAAU,GAAG;QACjB,GAAG,OAAO,CAAC,MAAM;QACjB,OAAO,EAAE,MAAM;KAChB,CAAC;IAEF,MAAM,KAAK,CAAC,cAAc,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACjD,MAAM,SAAS,CACb,IAAI,CAAC,cAAc,EAAE,eAAe,CAAC,EACrC,IAAI,CAAC,SAAS,CAAC,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC,EACnC,OAAO,CACR,CAAC;AACJ,CAAC"}
@@ -0,0 +1,15 @@
1
+ import type { SecurityProfileKey } from './types.js';
2
+ /** Pulls the OpenClaw container image; returns the pulled image size. */
3
+ export declare function pullContainerImage(): Promise<{
4
+ size: string;
5
+ }>;
6
+ /**
7
+ * Runs the OpenClaw container:
8
+ * - Mounts ONLY ~/Desktop/OpenClaw_Workspace (never the full home dir)
9
+ * - Exposes port 3845
10
+ * - Passes the API key as ANTHROPIC_API_KEY env var
11
+ */
12
+ export declare function launchContainer(apiKey: string, _profileKey: SecurityProfileKey): Promise<{
13
+ port: number;
14
+ }>;
15
+ //# sourceMappingURL=container.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"container.d.ts","sourceRoot":"","sources":["../src/container.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAMrD,yEAAyE;AACzE,wBAAsB,kBAAkB,IAAI,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAepE;AAED;;;;;GAKG;AACH,wBAAsB,eAAe,CACnC,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,kBAAkB,GAC9B,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAiB3B"}
@@ -0,0 +1,41 @@
1
+ import { execa } from 'execa';
2
+ import { homedir } from 'node:os';
3
+ import { join } from 'node:path';
4
+ const WORKSPACE_PATH = join(homedir(), 'Desktop', 'OpenClaw_Workspace');
5
+ const IMAGE = 'ghcr.io/openclaw/openclaw:latest';
6
+ const PORT = 3845;
7
+ /** Pulls the OpenClaw container image; returns the pulled image size. */
8
+ export async function pullContainerImage() {
9
+ await execa('docker', ['pull', IMAGE], { stdio: 'inherit' });
10
+ // Get image size after pull
11
+ const { stdout } = await execa('docker', [
12
+ 'image',
13
+ 'inspect',
14
+ IMAGE,
15
+ '--format',
16
+ '{{.Size}}',
17
+ ]);
18
+ const bytes = parseInt(stdout.trim(), 10);
19
+ const size = isNaN(bytes) ? 'unknown' : `${(bytes / 1_073_741_824).toFixed(1)} GB`;
20
+ return { size };
21
+ }
22
+ /**
23
+ * Runs the OpenClaw container:
24
+ * - Mounts ONLY ~/Desktop/OpenClaw_Workspace (never the full home dir)
25
+ * - Exposes port 3845
26
+ * - Passes the API key as ANTHROPIC_API_KEY env var
27
+ */
28
+ export async function launchContainer(apiKey, _profileKey) {
29
+ await execa('docker', [
30
+ 'run',
31
+ '--detach',
32
+ '--rm',
33
+ '--name', 'openclaw_sandbox',
34
+ '--publish', `${PORT}:${PORT}`,
35
+ '--volume', `${WORKSPACE_PATH}:/workspace`,
36
+ '--env', `ANTHROPIC_API_KEY=${apiKey}`,
37
+ IMAGE,
38
+ ], { stdio: 'ignore' });
39
+ return { port: PORT };
40
+ }
41
+ //# sourceMappingURL=container.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"container.js","sourceRoot":"","sources":["../src/container.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC;AAC9B,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAGjC,MAAM,cAAc,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,oBAAoB,CAAC,CAAC;AACxE,MAAM,KAAK,GAAG,kCAAkC,CAAC;AACjD,MAAM,IAAI,GAAG,IAAI,CAAC;AAElB,yEAAyE;AACzE,MAAM,CAAC,KAAK,UAAU,kBAAkB;IACtC,MAAM,KAAK,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;IAE7D,4BAA4B;IAC5B,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,KAAK,CAAC,QAAQ,EAAE;QACvC,OAAO;QACP,SAAS;QACT,KAAK;QACL,UAAU;QACV,WAAW;KACZ,CAAC,CAAC;IACH,MAAM,KAAK,GAAG,QAAQ,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;IAC1C,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,GAAG,aAAa,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC;IAEnF,OAAO,EAAE,IAAI,EAAE,CAAC;AAClB,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,MAAc,EACd,WAA+B;IAE/B,MAAM,KAAK,CACT,QAAQ,EACR;QACE,KAAK;QACL,UAAU;QACV,MAAM;QACN,QAAQ,EAAE,kBAAkB;QAC5B,WAAW,EAAE,GAAG,IAAI,IAAI,IAAI,EAAE;QAC9B,UAAU,EAAE,GAAG,cAAc,aAAa;QAC1C,OAAO,EAAE,qBAAqB,MAAM,EAAE;QACtC,KAAK;KACN,EACD,EAAE,KAAK,EAAE,QAAQ,EAAE,CACpB,CAAC;IAEF,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;AACxB,CAAC"}
@@ -0,0 +1,7 @@
1
+ /** Silent check — returns true if docker CLI is available. */
2
+ export declare function checkDocker(): Promise<boolean>;
3
+ /** Install Docker Desktop via Homebrew Cask. */
4
+ export declare function installDocker(): Promise<void>;
5
+ /** Open Docker.app and poll `docker info` until daemon is ready (max 60s). */
6
+ export declare function startDockerDaemon(): Promise<void>;
7
+ //# sourceMappingURL=docker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"docker.d.ts","sourceRoot":"","sources":["../src/docker.ts"],"names":[],"mappings":"AAEA,8DAA8D;AAC9D,wBAAsB,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC,CAOpD;AAED,gDAAgD;AAChD,wBAAsB,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CAEnD;AAED,8EAA8E;AAC9E,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC,CA0BvD"}
package/dist/docker.js ADDED
@@ -0,0 +1,42 @@
1
+ import { execa } from 'execa';
2
+ /** Silent check — returns true if docker CLI is available. */
3
+ export async function checkDocker() {
4
+ try {
5
+ await execa('docker', ['--version']);
6
+ return true;
7
+ }
8
+ catch {
9
+ return false;
10
+ }
11
+ }
12
+ /** Install Docker Desktop via Homebrew Cask. */
13
+ export async function installDocker() {
14
+ await execa('brew', ['install', '--cask', 'docker'], { stdio: 'inherit' });
15
+ }
16
+ /** Open Docker.app and poll `docker info` until daemon is ready (max 60s). */
17
+ export async function startDockerDaemon() {
18
+ // Check if daemon is already running
19
+ try {
20
+ await execa('docker', ['info'], { stdio: 'ignore' });
21
+ return; // Already running
22
+ }
23
+ catch {
24
+ // Not running — launch it
25
+ }
26
+ await execa('open', ['-a', 'Docker']);
27
+ const POLL_INTERVAL_MS = 2000;
28
+ const MAX_WAIT_MS = 60_000;
29
+ const start = Date.now();
30
+ while (Date.now() - start < MAX_WAIT_MS) {
31
+ await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS));
32
+ try {
33
+ await execa('docker', ['info'], { stdio: 'ignore' });
34
+ return; // Daemon ready
35
+ }
36
+ catch {
37
+ // Still starting — keep polling
38
+ }
39
+ }
40
+ throw new Error('Docker daemon did not start within 60 seconds.');
41
+ }
42
+ //# sourceMappingURL=docker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"docker.js","sourceRoot":"","sources":["../src/docker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC;AAE9B,8DAA8D;AAC9D,MAAM,CAAC,KAAK,UAAU,WAAW;IAC/B,IAAI,CAAC;QACH,MAAM,KAAK,CAAC,QAAQ,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC;QACrC,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,gDAAgD;AAChD,MAAM,CAAC,KAAK,UAAU,aAAa;IACjC,MAAM,KAAK,CAAC,MAAM,EAAE,CAAC,SAAS,EAAE,QAAQ,EAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;AAC7E,CAAC;AAED,8EAA8E;AAC9E,MAAM,CAAC,KAAK,UAAU,iBAAiB;IACrC,qCAAqC;IACrC,IAAI,CAAC;QACH,MAAM,KAAK,CAAC,QAAQ,EAAE,CAAC,MAAM,CAAC,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;QACrD,OAAO,CAAC,kBAAkB;IAC5B,CAAC;IAAC,MAAM,CAAC;QACP,0BAA0B;IAC5B,CAAC;IAED,MAAM,KAAK,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC;IAEtC,MAAM,gBAAgB,GAAG,IAAI,CAAC;IAC9B,MAAM,WAAW,GAAG,MAAM,CAAC;IAC3B,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAEzB,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,GAAG,WAAW,EAAE,CAAC;QACxC,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,gBAAgB,CAAC,CAAC,CAAC;QACtE,IAAI,CAAC;YACH,MAAM,KAAK,CAAC,QAAQ,EAAE,CAAC,MAAM,CAAC,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;YACrD,OAAO,CAAC,eAAe;QACzB,CAAC;QAAC,MAAM,CAAC;YACP,gCAAgC;QAClC,CAAC;IACH,CAAC;IAED,MAAM,IAAI,KAAK,CAAC,gDAAgD,CAAC,CAAC;AACpE,CAAC"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,154 @@
1
+ #!/usr/bin/env node
2
+ import * as p from '@clack/prompts';
3
+ import pc from 'picocolors';
4
+ import { Listr } from 'listr2';
5
+ import { PROFILES } from './profiles.js';
6
+ import { generateConfig, WORKSPACE_PATH } from './config.js';
7
+ import { execa } from 'execa';
8
+ import { checkDocker, installDocker, startDockerDaemon } from './docker.js';
9
+ import { createWorkspace } from './workspace.js';
10
+ import { pullContainerImage, launchContainer } from './container.js';
11
+ /** Formats API key for inline confirmation: first 7 + last 4 chars. */
12
+ function maskApiKey(key) {
13
+ if (key.length <= 11)
14
+ return key.slice(0, 3) + '••••' + key.slice(-2);
15
+ return key.slice(0, 7) + '••••' + key.slice(-4);
16
+ }
17
+ /** Syntax-highlights a JSON object: cyan keys, green strings, purple numbers. */
18
+ function highlightJson(obj) {
19
+ return JSON.stringify(obj, null, 2)
20
+ .split('\n')
21
+ .map((line) => {
22
+ return line
23
+ .replace(/"([^"]+)":/g, (_, k) => pc.cyan('"' + k + '"') + ':')
24
+ .replace(/: "([^"]*)"/g, (_, v) => ': ' + pc.green('"' + v + '"'))
25
+ .replace(/: (\d+)/g, (_, n) => ': ' + pc.magenta(n))
26
+ .replace(/: \[/g, ': [')
27
+ .replace(/"(\*|rm|sudo|curl|wget|git push|npm publish|rm -rf)"/g, (_, v) => pc.green('"' + v + '"'));
28
+ })
29
+ .join('\n');
30
+ }
31
+ async function main() {
32
+ // ── 3.2 Welcome intro ───────────────────────────────────────────────────────
33
+ console.clear();
34
+ console.log(pc.dim('──────────────────────────────────────────────'));
35
+ p.intro(`${pc.bgCyan(pc.black(' 🦞 ONE-CLICK CLAW '))} ${pc.dim('Secure Local Sandbox')}`);
36
+ console.log(pc.dim('──────────────────────────────────────────────'));
37
+ // ── 3.3 API key masked input ────────────────────────────────────────────────
38
+ const apiKey = await p.password({
39
+ message: 'Paste your Anthropic or OpenAI API Key',
40
+ mask: '•',
41
+ validate: (value) => {
42
+ if (!value)
43
+ return 'API Key is required to power the brain.';
44
+ },
45
+ });
46
+ if (p.isCancel(apiKey)) {
47
+ p.cancel('Setup cancelled.');
48
+ process.exit(0);
49
+ }
50
+ // Inline confirmation
51
+ console.log(`${pc.green('◆')} API Key ${pc.dim('✓')} ${pc.dim(maskApiKey(apiKey))}`);
52
+ // ── 3.4 Security profile selection ─────────────────────────────────────────
53
+ const profileKey = await p.select({
54
+ message: 'Select your security profile',
55
+ initialValue: 'pragmatic',
56
+ options: [
57
+ { value: 'fort_knox', label: 'Fort Knox', hint: 'Super strict. Read-only.' },
58
+ { value: 'pragmatic', label: 'The Pragmatic PM', hint: 'Recommended. Scoped access.' },
59
+ { value: 'cowboy', label: 'Cowboy Coder', hint: 'Lenient. Proceed with caution.' },
60
+ { value: 'yolo', label: 'YOLO Mode', hint: 'Unrestricted. Good luck.' },
61
+ ],
62
+ });
63
+ if (p.isCancel(profileKey)) {
64
+ p.cancel('Setup cancelled.');
65
+ process.exit(0);
66
+ }
67
+ const selectedProfile = PROFILES[profileKey];
68
+ // Inline confirmation
69
+ console.log(`${pc.green('◆')} Profile ${pc.yellow(selectedProfile.label)}`);
70
+ // ── 3.5 Config preview ──────────────────────────────────────────────────────
71
+ console.log(`\n${pc.dim('◇')} ${pc.dim('Generating clawdbot.json')}`);
72
+ console.log(highlightJson(selectedProfile.config));
73
+ console.log();
74
+ // ── 3.6 Sequential install checklist (listr2) ───────────────────────────────
75
+ let dockerVersion = 'Docker';
76
+ let imageSize = '1.2 GB';
77
+ let containerPort = 3845;
78
+ const tasks = new Listr([
79
+ {
80
+ title: 'Checking Docker daemon...',
81
+ task: async (_, task) => {
82
+ const installed = await checkDocker();
83
+ if (!installed) {
84
+ task.title = 'Installing Docker via Homebrew...';
85
+ await installDocker();
86
+ }
87
+ await startDockerDaemon();
88
+ try {
89
+ const { stdout } = await execa('docker', ['--version']);
90
+ dockerVersion = stdout.trim();
91
+ }
92
+ catch {
93
+ // version string is cosmetic — don't block
94
+ }
95
+ task.title = pc.dim(`✔ ${dockerVersion} is running`);
96
+ },
97
+ },
98
+ {
99
+ title: 'Creating workspace directory...',
100
+ task: async (_, task) => {
101
+ await createWorkspace();
102
+ task.title = pc.dim(`✔ Workspace ready at ${WORKSPACE_PATH}`);
103
+ },
104
+ },
105
+ {
106
+ title: 'Writing clawdbot.json...',
107
+ task: async (_, task) => {
108
+ await generateConfig(profileKey, apiKey);
109
+ task.title = pc.dim('✔ clawdbot.json written');
110
+ },
111
+ },
112
+ {
113
+ title: 'Pulling OpenClaw container image...',
114
+ task: async (_, task) => {
115
+ const result = await pullContainerImage();
116
+ imageSize = result.size;
117
+ task.title = pc.dim(`✔ Image pulled (${imageSize})`);
118
+ },
119
+ },
120
+ {
121
+ title: 'Booting container...',
122
+ task: async (_, task) => {
123
+ const result = await launchContainer(apiKey, profileKey);
124
+ containerPort = result.port;
125
+ task.title = pc.dim(`✔ Container live on port ${containerPort}`);
126
+ },
127
+ },
128
+ ], {
129
+ rendererOptions: { collapseErrors: false },
130
+ });
131
+ try {
132
+ await tasks.run();
133
+ }
134
+ catch (err) {
135
+ p.cancel(`Setup failed: ${err.message}`);
136
+ process.exit(1);
137
+ }
138
+ // ── 3.7 Outro ───────────────────────────────────────────────────────────────
139
+ const box = [
140
+ ` ${pc.dim('│')} ☕ Pouring some coffee for your new AI intern...`,
141
+ ` ${pc.dim('│')}`,
142
+ ` ${pc.dim('│')} Workspace → ${pc.cyan(WORKSPACE_PATH)}`,
143
+ ` ${pc.dim('│')} Access → ${pc.cyan(`localhost:${containerPort}`)}`,
144
+ ` ${pc.dim('│')} Profile → ${pc.yellow(selectedProfile.label)}`,
145
+ ` ${pc.dim('│')}`,
146
+ ` ${pc.dim('│')} Drop files into the workspace folder to begin.`,
147
+ ].join('\n');
148
+ p.outro(`${pc.green('✔')} Sandbox successfully booted!\n\n${box}`);
149
+ }
150
+ main().catch((err) => {
151
+ p.cancel(`Unexpected error: ${err.message}`);
152
+ process.exit(1);
153
+ });
154
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { SecurityProfile } from './types.js';
2
+ export declare const PROFILES: Record<string, SecurityProfile>;
3
+ //# sourceMappingURL=profiles.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profiles.d.ts","sourceRoot":"","sources":["../src/profiles.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD,eAAO,MAAM,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CA6CpD,CAAC"}
@@ -0,0 +1,47 @@
1
+ export const PROFILES = {
2
+ fort_knox: {
3
+ key: 'fort_knox',
4
+ label: 'Fort Knox',
5
+ config: {
6
+ sandbox: { mode: 'all' },
7
+ workspaceAccess: 'ro',
8
+ require_human_approval: ['*'],
9
+ skill_registry_trust: 'none',
10
+ max_budget: 100000,
11
+ },
12
+ },
13
+ pragmatic: {
14
+ key: 'pragmatic',
15
+ label: 'The Pragmatic PM',
16
+ config: {
17
+ sandbox: { mode: 'non-main' },
18
+ workspaceAccess: 'scoped',
19
+ require_human_approval: ['rm', 'sudo', 'curl', 'wget', 'git push', 'npm publish'],
20
+ skill_registry_trust: 'verified_only',
21
+ max_budget: 500000,
22
+ },
23
+ },
24
+ cowboy: {
25
+ key: 'cowboy',
26
+ label: 'Cowboy Coder',
27
+ config: {
28
+ sandbox: { mode: 'off' },
29
+ workspaceAccess: 'scoped',
30
+ require_human_approval: ['sudo', 'rm -rf'],
31
+ skill_registry_trust: 'all',
32
+ max_budget: 2000000,
33
+ },
34
+ },
35
+ yolo: {
36
+ key: 'yolo',
37
+ label: 'YOLO Mode',
38
+ config: {
39
+ sandbox: { mode: 'off' },
40
+ workspaceAccess: 'rw',
41
+ require_human_approval: [],
42
+ skill_registry_trust: 'all',
43
+ max_budget: 0, // 0 = unlimited
44
+ },
45
+ },
46
+ };
47
+ //# sourceMappingURL=profiles.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profiles.js","sourceRoot":"","sources":["../src/profiles.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,QAAQ,GAAoC;IACvD,SAAS,EAAE;QACT,GAAG,EAAE,WAAW;QAChB,KAAK,EAAE,WAAW;QAClB,MAAM,EAAE;YACN,OAAO,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE;YACxB,eAAe,EAAE,IAAI;YACrB,sBAAsB,EAAE,CAAC,GAAG,CAAC;YAC7B,oBAAoB,EAAE,MAAM;YAC5B,UAAU,EAAE,MAAM;SACnB;KACF;IACD,SAAS,EAAE;QACT,GAAG,EAAE,WAAW;QAChB,KAAK,EAAE,kBAAkB;QACzB,MAAM,EAAE;YACN,OAAO,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE;YAC7B,eAAe,EAAE,QAAQ;YACzB,sBAAsB,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,aAAa,CAAC;YACjF,oBAAoB,EAAE,eAAe;YACrC,UAAU,EAAE,MAAM;SACnB;KACF;IACD,MAAM,EAAE;QACN,GAAG,EAAE,QAAQ;QACb,KAAK,EAAE,cAAc;QACrB,MAAM,EAAE;YACN,OAAO,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE;YACxB,eAAe,EAAE,QAAQ;YACzB,sBAAsB,EAAE,CAAC,MAAM,EAAE,QAAQ,CAAC;YAC1C,oBAAoB,EAAE,KAAK;YAC3B,UAAU,EAAE,OAAO;SACpB;KACF;IACD,IAAI,EAAE;QACJ,GAAG,EAAE,MAAM;QACX,KAAK,EAAE,WAAW;QAClB,MAAM,EAAE;YACN,OAAO,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE;YACxB,eAAe,EAAE,IAAI;YACrB,sBAAsB,EAAE,EAAE;YAC1B,oBAAoB,EAAE,KAAK;YAC3B,UAAU,EAAE,CAAC,EAAE,gBAAgB;SAChC;KACF;CACF,CAAC"}
@@ -0,0 +1,19 @@
1
+ export type SecurityProfileKey = 'fort_knox' | 'pragmatic' | 'cowboy' | 'yolo';
2
+ export type SandboxMode = 'all' | 'non-main' | 'off';
3
+ export type WorkspaceAccess = 'ro' | 'scoped' | 'rw';
4
+ export type SkillRegistryTrust = 'none' | 'verified_only' | 'all';
5
+ export interface ClawdbotConfig {
6
+ sandbox: {
7
+ mode: SandboxMode;
8
+ };
9
+ workspaceAccess: WorkspaceAccess;
10
+ require_human_approval: string[];
11
+ skill_registry_trust: SkillRegistryTrust;
12
+ max_budget: number;
13
+ }
14
+ export interface SecurityProfile {
15
+ key: SecurityProfileKey;
16
+ label: string;
17
+ config: ClawdbotConfig;
18
+ }
19
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,kBAAkB,GAAG,WAAW,GAAG,WAAW,GAAG,QAAQ,GAAG,MAAM,CAAC;AAE/E,MAAM,MAAM,WAAW,GAAG,KAAK,GAAG,UAAU,GAAG,KAAK,CAAC;AAErD,MAAM,MAAM,eAAe,GAAG,IAAI,GAAG,QAAQ,GAAG,IAAI,CAAC;AAErD,MAAM,MAAM,kBAAkB,GAAG,MAAM,GAAG,eAAe,GAAG,KAAK,CAAC;AAElE,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE;QACP,IAAI,EAAE,WAAW,CAAC;KACnB,CAAC;IACF,eAAe,EAAE,eAAe,CAAC;IACjC,sBAAsB,EAAE,MAAM,EAAE,CAAC;IACjC,oBAAoB,EAAE,kBAAkB,CAAC;IACzC,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,kBAAkB,CAAC;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,cAAc,CAAC;CACxB"}
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,4 @@
1
+ export declare const WORKSPACE_PATH: string;
2
+ /** Idempotent — creates workspace directory; no error if it already exists. */
3
+ export declare function createWorkspace(): Promise<void>;
4
+ //# sourceMappingURL=workspace.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspace.d.ts","sourceRoot":"","sources":["../src/workspace.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,cAAc,QAAmD,CAAC;AAE/E,+EAA+E;AAC/E,wBAAsB,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC,CAErD"}
@@ -0,0 +1,9 @@
1
+ import { execa } from 'execa';
2
+ import { homedir } from 'node:os';
3
+ import { join } from 'node:path';
4
+ export const WORKSPACE_PATH = join(homedir(), 'Desktop', 'OpenClaw_Workspace');
5
+ /** Idempotent — creates workspace directory; no error if it already exists. */
6
+ export async function createWorkspace() {
7
+ await execa('mkdir', ['-p', WORKSPACE_PATH]);
8
+ }
9
+ //# sourceMappingURL=workspace.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspace.js","sourceRoot":"","sources":["../src/workspace.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC;AAC9B,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,MAAM,CAAC,MAAM,cAAc,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,oBAAoB,CAAC,CAAC;AAE/E,+EAA+E;AAC/E,MAAM,CAAC,KAAK,UAAU,eAAe;IACnC,MAAM,KAAK,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC,CAAC;AAC/C,CAAC"}
package/package.json ADDED
@@ -0,0 +1,34 @@
1
+ {
2
+ "name": "claw-zero",
3
+ "version": "0.1.0",
4
+ "description": "One-Click CLI to securely install and sandbox the OpenClaw AI agent",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "bin": {
8
+ "claw-zero": "dist/index.js"
9
+ },
10
+ "files": [
11
+ "dist",
12
+ "README.md"
13
+ ],
14
+ "scripts": {
15
+ "start": "tsx src/index.ts",
16
+ "build": "tsc",
17
+ "dev": "tsx watch src/index.ts",
18
+ "prepublishOnly": "npm run build"
19
+ },
20
+ "dependencies": {
21
+ "@clack/prompts": "^0.9.0",
22
+ "execa": "^9.5.2",
23
+ "listr2": "^8.2.5",
24
+ "picocolors": "^1.1.1"
25
+ },
26
+ "devDependencies": {
27
+ "@types/node": "^22.0.0",
28
+ "tsx": "^4.19.2",
29
+ "typescript": "^5.7.2"
30
+ },
31
+ "engines": {
32
+ "node": ">=18.0.0"
33
+ }
34
+ }