A decentralized music tracking and discovery platform built on AT Protocol 🎵

Install OpenClaw and Claude in sandboxes

Switch Cloudflare base to node:24-slim and copy the sandbox
binary; add git, curl and ca-certificates, expose port 3000 and set
ENTRYPOINT. Add OpenClaw install to Daytona and Vercel Dockerfiles
and scripts. Improve logging to report Node/Claude/OpenClaw versions
and adjust Deno sandbox creation and PATH. Add deno deploy org and a
.dockerignore for daytona

+60 -5
+16 -2
.sandbox/cloudflare/Dockerfile
··· 1 - FROM docker.io/cloudflare/sandbox:0.7.0 1 + FROM node:24-slim 2 + 3 + COPY --from=docker.io/cloudflare/sandbox:0.7.0 /container-server/sandbox /sandbox 2 4 3 5 RUN apt-get update && apt-get install -y --no-install-recommends \ 4 - openssh-client 6 + openssh-client \ 7 + git \ 8 + curl \ 9 + ca-certificates 10 + 11 + RUN curl -fsSL https://openclaw.ai/install.sh | bash || true 12 + 13 + RUN npm install -g @anthropic-ai/claude-code 14 + 15 + WORKDIR /workspace 5 16 6 17 # Required during local development to access exposed ports 7 18 EXPOSE 8080 19 + EXPOSE 3000 20 + 21 + ENTRYPOINT ["/sandbox"]
+12 -1
.sandbox/cloudflare/src/index.ts
··· 31 31 const clone = await sandbox.exec( 32 32 "git clone git@tangled.org:rocksky.app/rocksky rocksky -b main", 33 33 ); 34 - consola.log(clone.stdout); 34 + consola.info(clone.stdout); 35 35 const ls = await sandbox.exec("ls -la rocksky"); 36 + consola.info(ls.stdout); 37 + 38 + const node = await sandbox.exec("node -v"); 39 + consola.info(`Node version in sandbox: ${node.stdout.trim()}`); 40 + 41 + const claude = await sandbox.exec("claude --version"); 42 + consola.info(`Claude version in sandbox: ${claude.stdout.trim()}`); 43 + 44 + const openclaw = await sandbox.exec("openclaw --version"); 45 + consola.info(`OpenClaw version in sandbox: ${openclaw.stdout.trim()}`); 46 + 36 47 return Response.json({ 37 48 output: ls.stdout, 38 49 error: ls.stderr,
+1
.sandbox/daytona/.dockerignore
··· 1 + node_modules
+3
.sandbox/daytona/Dockerfile
··· 1 + FROM daytonaio/sandbox:0.5.2 2 + 3 + RUN curl -fsSL https://openclaw.ai/install.sh | bash || true
+3
.sandbox/daytona/index.ts
··· 31 31 32 32 consola.info("SSH keys uploaded to sandbox."); 33 33 34 + const openclaw = await sandbox.process.executeCommand("which openclaw"); 35 + consola.log(openclaw.result); 36 + 34 37 await sandbox.process.executeCommand("chmod 600 ${HOME}/.ssh/id_rsa"); 35 38 await sandbox.process.executeCommand( 36 39 "ssh-keyscan -t rsa tangled.org >> ${HOME}/.ssh/known_hosts",
+3
.sandbox/deno/deno.json
··· 7 7 "@std/assert": "jsr:@std/assert@1", 8 8 "chalk": "npm:chalk@^5.6.2", 9 9 "consola": "npm:consola@^3.4.2" 10 + }, 11 + "deploy": { 12 + "org": "tsirysndr" 10 13 } 11 14 }
+10 -2
.sandbox/deno/main.ts
··· 3 3 import chalk from "chalk"; 4 4 5 5 export async function main() { 6 - const HOME = "/home/app"; 6 + await using sandbox = await Sandbox.create({ 7 + root: Deno.env.get("SANDBOX_ROOT"), 8 + }); 9 + 10 + const HOME = await sandbox.env.get("HOME"); 11 + const PATH = await sandbox.env.get("PATH"); 12 + await sandbox.env.set("PATH", `${HOME}/.npm-global/bin:/usr/bin:${PATH}`); 7 13 8 - await using sandbox = await Sandbox.create(); 9 14 consola.info("Sandbox created with ID:", chalk.greenBright(sandbox.id)); 10 15 11 16 await sandbox.sh`mkdir -p $HOME/.ssh`; ··· 31 36 32 37 await sandbox.sh`git clone git@tangled.org:rocksky.app/rocksky rocksky -b main`; 33 38 await sandbox.sh`ls -la rocksky`; 39 + 40 + await sandbox.sh`which claude`; 41 + await sandbox.sh`which openclaw`; 34 42 35 43 await sandbox.close(); 36 44 }
+12
.sandbox/vercel/index.ts
··· 25 25 26 26 consola.info("SSH keys uploaded to sandbox."); 27 27 28 + consola.info("Installing openclaw..."); 29 + 30 + await sandbox.runCommand({ 31 + cmd: "sh", 32 + args: ["-c", "curl -fsSL https://openclaw.ai/install.sh | bash || true"], 33 + stdout: process.stdout, 34 + stderr: process.stderr, 35 + }); 36 + 37 + consola.info("Configuring SSH and Git..."); 38 + 28 39 await sandbox.runCommand({ 29 40 cmd: "chmod", 30 41 args: ["600", `${HOME}/.ssh/id_rsa`], ··· 77 88 }); 78 89 79 90 try { 91 + // await sandbox.snapshot(); 80 92 // await sandbox.stop(); 81 93 } catch (e) { 82 94 consola.error("Error stopping Vercel Sandbox:", e);