the universal sandbox runtime for agents and humans. pocketenv.io
sandbox openclaw agent claude-code vercel-sandbox deno-sandbox cloudflare-sandbox atproto sprites daytona
7
fork

Configure Feed

Select the types of activity you want to include in your feed.

Add repo cloning to sandboxes and providers

Add a clone(repoUrl) API to BaseSandbox and implement it for
Daytona, Deno, Vercel, Sprite and Cloudflare. Trigger a git clone
during sandbox start when a repo is set (apps/sandbox and
apps/cf-sandbox). Also implement mkdir, writeFile and setupSshKeys
for Daytona, Deno and Vercel, import path where needed, and tidy up
some command returns and permission handling.

+97 -14
+9
apps/cf-sandbox/src/index.ts
··· 327 327 sandbox?.setupTailscale(await decrypt(params[4][0].authKey)), 328 328 ]); 329 329 330 + if (record.repo) { 331 + sandbox 332 + .clone(record.repo) 333 + .then(() => 334 + consola.success(`Git Repository successfully cloned: ${record.repo}`), 335 + ) 336 + .catch((e) => consola.error(`Failed to Clone Repository: ${e}`)); 337 + } 338 + 330 339 await sandbox.start(); 331 340 await c.var.db 332 341 .update(sandboxes)
+4
apps/cf-sandbox/src/providers/cloudflare/index.ts
··· 84 84 await this.sh`pm2 start tailscaled || true`; 85 85 await this.sh`tailscale up --auth-key=${authKey} || true`; 86 86 } 87 + 88 + clone(repoUrl: string): Promise<any> { 89 + return this.sh`git clone ${repoUrl}`; 90 + } 87 91 } 88 92 89 93 class CloudflareProvider implements BaseProvider {
+1
apps/cf-sandbox/src/providers/index.ts
··· 9 9 abstract writeFile(path: string, content: string): Promise<void>; 10 10 abstract setupSshKeys(privateKey: string, publicKey: string): Promise<void>; 11 11 abstract setupTailscale(autKey: string): Promise<void>; 12 + abstract clone(repoUrl: string): Promise<void>; 12 13 } 13 14 14 15 abstract class BaseProvider {
+9
apps/sandbox/src/index.ts
··· 253 253 sandbox?.setupTailscale(decrypt(params[2][0].authKey)), 254 254 ]); 255 255 256 + if (record.repo) { 257 + sandbox 258 + .clone(record.repo) 259 + .then(() => 260 + consola.success(`Git Repository successfully cloned: ${record.repo}`), 261 + ) 262 + .catch((e) => consola.error(`Failed to Clone Repository: ${e}`)); 263 + } 264 + 256 265 await sandbox.start(); 257 266 await c.var.db 258 267 .update(sandboxes)
+23 -4
apps/sandbox/src/providers/daytona/mod.ts
··· 2 2 import { Daytona, Sandbox } from "@daytonaio/sdk"; 3 3 import process from "node:process"; 4 4 import consola from "consola"; 5 + import path from "node:path"; 5 6 6 7 export class DaytonaSandbox implements BaseSandbox { 7 8 constructor(private sandbox: Sandbox) {} ··· 28 29 const command = strings.reduce((acc, str, i) => { 29 30 return acc + str + (values[i] || ""); 30 31 }, ""); 31 - return Promise.resolve(this.sandbox.process.executeCommand(command)); 32 + return this.sandbox.process.executeCommand(command); 32 33 } 33 34 34 35 id(): Promise<string | null> { ··· 46 47 }; 47 48 } 48 49 49 - async mkdir(dir: string): Promise<void> {} 50 + async mkdir(dir: string): Promise<void> { 51 + await this.sh`mkdir -p ${dir}`; 52 + } 50 53 51 - async writeFile(path: string, content: string): Promise<void> {} 54 + async writeFile(absolutePath: string, content: string): Promise<void> { 55 + const basePath = path.dirname(absolutePath); 56 + if (basePath !== "/" && basePath != ".") { 57 + await this.mkdir(basePath); 58 + } 59 + await this.sh`echo '${content}' > ${absolutePath}`; 60 + } 52 61 53 - async setupSshKeys(privateKey: string, publicKey: string): Promise<void> {} 62 + async setupSshKeys(privateKey: string, publicKey: string): Promise<void> { 63 + await this.writeFile("~/.ssh/id_ed25519", privateKey); 64 + await this.writeFile("~/.ssh/id_ed25519.pub", publicKey); 65 + await this.sh`chmod 600 ~/.ssh/id_ed25519`; 66 + await this.sh`chmod 644 ~/.ssh/id_ed25519.pub`; 67 + } 54 68 55 69 async setupTailscale(authKey: string): Promise<void> { 56 70 await this 57 71 .sh`type tailscaled || curl -fsSL https://tailscale.com/install.sh | sh || true`; 58 72 await this.sh`pm2 start tailscaled || true`; 59 73 await this.sh`tailscale up --auth-key=${authKey} || true`; 74 + } 75 + 76 + clone(repoUrl: string): Promise<any> { 77 + const dir = repoUrl.split("/").pop()?.replace(".git", ""); 78 + return this.sh`git clone ${repoUrl} || git -C ${dir} pull`; 60 79 } 61 80 } 62 81
+22 -3
apps/sandbox/src/providers/deno/mod.ts
··· 2 2 import { Sandbox } from "@deno/sandbox"; 3 3 import process from "node:process"; 4 4 import consola from "consola"; 5 + import path from "node:path"; 5 6 6 7 export class DenoSandbox implements BaseSandbox { 7 8 constructor(private sandbox: Sandbox) {} ··· 56 57 return this.sandbox.exposeSsh(); 57 58 } 58 59 59 - async mkdir(dir: string): Promise<void> {} 60 + async mkdir(dir: string): Promise<void> { 61 + await this.sh`mkdir -p ${dir}`; 62 + } 60 63 61 - async writeFile(path: string, content: string): Promise<void> {} 64 + async writeFile(absolutePath: string, content: string): Promise<void> { 65 + const basePath = path.dirname(absolutePath); 66 + if (basePath !== "/" && basePath != ".") { 67 + await this.mkdir(basePath); 68 + } 69 + await this.sh`echo '${content}' > ${absolutePath}`; 70 + } 62 71 63 - async setupSshKeys(privateKey: string, publicKey: string): Promise<void> {} 72 + async setupSshKeys(privateKey: string, publicKey: string): Promise<void> { 73 + await this.writeFile("~/.ssh/id_ed25519", privateKey); 74 + await this.writeFile("~/.ssh/id_ed25519.pub", publicKey); 75 + await this.sh`chmod 600 ~/.ssh/id_ed25519`; 76 + await this.sh`chmod 644 ~/.ssh/id_ed25519.pub`; 77 + } 64 78 65 79 async setupTailscale(authKey: string): Promise<void> { 66 80 await this 67 81 .sh`type tailscaled || curl -fsSL https://tailscale.com/install.sh | sh || true`; 68 82 await this.sh`pm2 start tailscaled || true`; 69 83 await this.sh`tailscale up --auth-key=${authKey} || true`; 84 + } 85 + 86 + clone(repoUrl: string): Promise<any> { 87 + const dir = repoUrl.split("/").pop()?.replace(".git", ""); 88 + return this.sh`git clone ${repoUrl} || git -C ${dir} pull`; 70 89 } 71 90 } 72 91
+1
apps/sandbox/src/providers/mod.ts
··· 12 12 abstract writeFile(path: string, content: string): Promise<void>; 13 13 abstract setupSshKeys(privateKey: string, publicKey: string): Promise<void>; 14 14 abstract setupTailscale(authKey: string): Promise<void>; 15 + abstract clone(repoUrl: string): Promise<any>; 15 16 } 16 17 17 18 abstract class BaseProvider {
+8 -4
apps/sandbox/src/providers/sprites/mod.ts
··· 68 68 "644", 69 69 "/home/sprite/.ssh/id_ed25519.pub", 70 70 ]); 71 - await this.sprite.execFile("chmod", [ 72 - "644", 73 - "/home/sprite/.ssh/authorized_keys", 74 - ]); 75 71 } 76 72 77 73 async setupTailscale(authKey: string): Promise<void> { ··· 90 86 await this.sprite.execFile("bash", [ 91 87 "-c", 92 88 `tailscale up --auth-key=${authKey}`, 89 + ]); 90 + } 91 + 92 + clone(repoUrl: string): Promise<any> { 93 + const dir = repoUrl.split("/").pop()?.replace(".git", ""); 94 + return this.sprite.execFile("bash", [ 95 + "-c", 96 + `git clone ${repoUrl} || git -C ${dir} pull`, 93 97 ]); 94 98 } 95 99 }
+20 -3
apps/sandbox/src/providers/vercel/mod.ts
··· 2 2 import { Sandbox } from "@vercel/sandbox"; 3 3 import process from "node:process"; 4 4 import consola from "consola"; 5 + import path from "node:path"; 5 6 6 7 export class VercelSandbox implements BaseSandbox { 7 8 constructor(private sandbox: Sandbox) {} ··· 43 44 44 45 async ssh(): Promise<any> {} 45 46 46 - async mkdir(dir: string): Promise<void> {} 47 + async mkdir(dir: string): Promise<void> { 48 + await this.sh`mkdir -p ${dir}`; 49 + } 47 50 48 - async writeFile(path: string, content: string): Promise<void> {} 51 + async writeFile(absolutePath: string, content: string): Promise<void> { 52 + const basePath = path.dirname(absolutePath); 53 + if (basePath !== "/" && basePath != ".") { 54 + await this.mkdir(basePath); 55 + } 56 + await this.sh`echo '${content}' > ${absolutePath}`; 57 + } 49 58 50 - async setupSshKeys(privateKey: string, publicKey: string): Promise<void> {} 59 + async setupSshKeys(privateKey: string, publicKey: string): Promise<void> { 60 + await this.writeFile("~/.ssh/id_ed25519", privateKey); 61 + await this.writeFile("~/.ssh/id_ed25519.pub", publicKey); 62 + await this.sh`chmod 600 ~/.ssh/id_ed25519`; 63 + await this.sh`chmod 644 ~/.ssh/id_ed25519.pub`; 64 + } 51 65 52 66 async setupTailscale(authKey: string): Promise<void> { 53 67 await this 54 68 .sh`type tailscaled || curl -fsSL https://tailscale.com/install.sh | sh || true`; 55 69 await this.sh`pm2 start tailscaled || true`; 56 70 await this.sh`tailscale up --auth-key=${authKey} || true`; 71 + } 72 + clone(repoUrl: string): Promise<any> { 73 + return this.sh`git clone ${repoUrl}`; 57 74 } 58 75 } 59 76