Skip to content

Instantly share code, notes, and snippets.

@callmephilip
Created February 18, 2026 14:48
Show Gist options
  • Select an option

  • Save callmephilip/8a30a8eccfcf94ee5abb6e76f601f581 to your computer and use it in GitHub Desktop.

Select an option

Save callmephilip/8a30a8eccfcf94ee5abb6e76f601f581 to your computer and use it in GitHub Desktop.
#!/usr/bin/env bun
/**
* Self-contained repro: Run Gemini CLI inside a Deno Sandbox.
*
* Prerequisites:
* - DENO_SANDBOX_TOKEN (or DENO_DEPLOY_TOKEN) env var
* - GEMINI_API_KEY env var
* - bun installed (to run this script)
* - @deno/sandbox package (installed in parent project)
*
* Usage:
* bun run gemini-with-deno-sandbox/run.ts
* bun run gemini-with-deno-sandbox/run.ts "your custom prompt here"
*/
import { Sandbox } from "@deno/sandbox";
// ── Config ──────────────────────────────────────────────────────────────
const PROMPT = process.argv[2] || "Write a TypeScript program that computes Fibonacci numbers. Save it to fibonacci.ts";
const EXTRA_BIN = "/home/app/bin";
// ── Env checks ──────────────────────────────────────────────────────────
const sandboxToken = process.env.DENO_SANDBOX_TOKEN || process.env.DENO_DEPLOY_TOKEN;
if (!sandboxToken) {
console.error("Error: Set DENO_SANDBOX_TOKEN or DENO_DEPLOY_TOKEN");
process.exit(1);
}
if (!process.env.DENO_DEPLOY_TOKEN) {
process.env.DENO_DEPLOY_TOKEN = sandboxToken;
}
const geminiKey = process.env.GEMINI_API_KEY;
if (!geminiKey) {
console.error("Error: Set GEMINI_API_KEY");
process.exit(1);
}
// ── Main ────────────────────────────────────────────────────────────────
async function main() {
console.log("1. Creating Deno Sandbox...");
const sandbox = await Sandbox.create({
env: { GEMINI_API_KEY: geminiKey! },
memoryMb: 2048,
lifetime: "10m",
});
console.log(` Sandbox ID: ${sandbox.id}`);
try {
// 2. Install Gemini CLI
console.log("\n2. Installing Gemini CLI via deno install...");
const install = await sandbox.spawn("deno", {
args: [
"install", "-g", "--root", "/home/app",
"--name", "gemini", "--allow-all",
"npm:@google/gemini-cli",
],
stdout: "piped",
stderr: "piped",
});
const installOut = await install.output();
const installCode = (await install.status).code;
if (installCode !== 0) {
console.error(` Install failed (exit ${installCode}):`);
console.error(installOut.stderrText);
return;
}
console.log(" Installed.");
// 3. Warmup (caches Deno's JIT compilation)
console.log("\n3. Warming up Gemini CLI...");
const warmup = await sandbox.spawn("bash", {
args: ["-c", `export PATH="${EXTRA_BIN}:$PATH" && gemini --version`],
stdout: "piped",
stderr: "piped",
});
const warmupOut = await warmup.output();
console.log(` Version: ${(warmupOut.stdoutText ?? "").trim()}`);
// 4. Create workspace and run Gemini CLI with the prompt
console.log(`\n4. Running Gemini CLI...`);
console.log(` Prompt: "${PROMPT}"`);
console.log(" ─────────────────────────────────────────────");
await sandbox.sh`mkdir -p /tmp/workspace`;
// Escape the prompt for shell
const escaped = PROMPT.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/\$/g, "\\$").replace(/`/g, "\\`");
const cmd = `export PATH="${EXTRA_BIN}:$PATH" && cd /tmp/workspace && gemini -y -m gemini-2.5-flash "${escaped}"`;
const gemini = await sandbox.spawn("bash", {
args: ["-c", cmd],
stdout: "piped",
stderr: "piped",
});
// Stream output in real time
const streamOut = gemini.stdout
? (async () => { for await (const c of gemini.stdout!) process.stdout.write(c); })()
: Promise.resolve();
const streamErr = gemini.stderr
? (async () => { for await (const c of gemini.stderr!) process.stderr.write(c); })()
: Promise.resolve();
const [status] = await Promise.all([gemini.status, streamOut, streamErr]);
console.log(" ─────────────────────────────────────────────");
console.log(` Exit code: ${status.code}`);
// 5. Show workspace contents
console.log("\n5. Workspace contents after run:");
const ls = await sandbox.spawn("bash", {
args: ["-c", "find /tmp/workspace -type f 2>/dev/null | head -20"],
stdout: "piped",
});
const lsOut = await ls.output();
const files = (lsOut.stdoutText ?? "").trim();
if (files) {
console.log(files);
// Show file contents if small
for (const f of files.split("\n").filter(Boolean)) {
console.log(`\n ── ${f} ──`);
const cat = await sandbox.spawn("bash", {
args: ["-c", `head -50 "${f}"`],
stdout: "piped",
});
const catOut = await cat.output();
console.log(catOut.stdoutText ?? "");
}
} else {
console.log(" (no files created)");
}
} finally {
console.log("\n6. Cleaning up sandbox...");
await sandbox.kill();
console.log(" Done.");
}
}
main().catch((err) => {
console.error(err);
process.exit(1);
});
@callmephilip
Copy link
Author

trying run gemini CLI inside Deno sandbox:

1. Creating Deno Sandbox...
[bun] Warning: ws.WebSocket 'unexpected-response' event is not implemented in bun
[bun] Warning: ws.WebSocket 'upgrade' event is not implemented in bun
   Sandbox ID: 378e3697-18c4-4a5d-83a6-9e83606f7b60

2. Installing Gemini CLI via deno install...
   Installed.

3. Warming up Gemini CLI...
   Version: 0.29.0

4. Running Gemini CLI...
   Prompt: "Write a TypeScript program that computes Fibonacci numbers. Save it to fibonacci.ts"
   ─────────────────────────────────────────────
╭ Warning
│
│  Ignored build scripts for packages:
│  npm:keytar@7.9.0
│  npm:tree-sitter-bash@0.25.1
│  npm:node-pty@1.1.0
│  npm:protobufjs@7.5.4
│
│  Lifecycle scripts are only supported when using a `node_modules` directory.
│  Enable it in your deno config file:
│  "nodeModulesDir": "auto"
╰─
YOLO mode is enabled. All tool calls will be automatically approved.
YOLO mode is enabled. All tool calls will be automatically approved.
YOLO mode is enabled. All tool calls will be automatically approved.
Error executing tool write_file: Path not in workspace: Attempted path "/tmp/workspace/fibonacci.ts" resolves outside the allowed workspace directories: /tmp/workspace or the project temp directory: /home/app/.gemini/tmp/workspace
Error executing tool write_file: Path not in workspace: Attempted path "/tmp/workspace/fibonacci.ts" resolves outside the allowed workspace directories: /tmp/workspace or the project temp directory: /home/app/.gemini/tmp/workspace
I will write the TypeScript program to compute Fibonacci numbers to `fibonacci.ts`.
Error executing tool write_file: Path not in workspace: Attempted path "/tmp/workspace/fibonacci.ts" resolves outside the allowed workspace directories: /tmp/workspace or the project temp directory: /home/app/.gemini/tmp/workspace
missing pgrep output
Error executing tool run_shell_command: Command failed: Only fd 0 is supported.
TypeError: Cannot read properties of undefined (reading 'destroy')
    at Timeout._onTimeout (file:///home/app/.cache/deno/npm/registry.npmjs.org/@lydell/node-pty/1.1.0/unixTerminal.js:71:35)
    at cb (ext:deno_node/internal/timers.mjs:85:49)
    at callback (ext:deno_web/02_timers.js:42:7)
    at eventLoopTick (ext:core/01_core.js:223:13)
   ─────────────────────────────────────────────
   Exit code: 1

5. Workspace contents after run:
   (no files created)

6. Cleaning up sandbox...
   Done.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment