@computesdk/just-bash
just-bash provider for ComputeSDK - Local sandboxed bash execution with a virtual filesystem. No external services, containers, or authentication required.
Installation
npm install @computesdk/just-bash
Quick Start
import { justBash } from '@computesdk/just-bash';
const compute = justBash({});
const sandbox = await compute.sandbox.create();
const result = await sandbox.runCommand('echo "Hello" | tr a-z A-Z');
console.log(result.stdout);
await sandbox.destroy();
Configuration
Environment Variables
No environment variables are required. just-bash runs entirely locally.
Configuration Options
interface JustBashConfig {
python?: boolean;
files?: Record<string, string>;
env?: Record<string, string>;
cwd?: string;
fs?: IFileSystem;
customCommands?: CustomCommand[];
network?: NetworkConfig;
}
Filesystem Backends
By default, just-bash uses an InMemoryFs — a pure in-memory filesystem. You can swap in alternative backends depending on your use case:
InMemoryFs (default)
All files live in memory. Fast, deterministic, fully isolated.
const compute = justBash({});
OverlayFs (copy-on-write)
Reads from a real directory on disk; writes stay in memory. The underlying directory is never modified.
import { OverlayFs } from 'just-bash';
const compute = justBash({
fs: new OverlayFs({ root: '/path/to/project' }),
cwd: '/path/to/project',
});
ReadWriteFs (direct disk access)
Reads and writes go directly to a real directory. Use with caution — changes are real.
import { ReadWriteFs } from 'just-bash';
const compute = justBash({
fs: new ReadWriteFs({ root: '/tmp/sandbox' }),
});
MountableFs (compose multiple filesystems)
Mount different filesystem backends at different paths.
import { MountableFs, InMemoryFs } from 'just-bash';
import { OverlayFs } from 'just-bash';
const compute = justBash({
fs: new MountableFs({
base: new InMemoryFs(),
mounts: [
{ mountPoint: '/project', filesystem: new OverlayFs({ root: '/real/project' }) },
],
}),
cwd: '/project',
});
Custom Commands
You can extend just-bash with custom commands using defineCommand():
import { justBash } from '@computesdk/just-bash';
import { defineCommand } from 'just-bash';
const hello = defineCommand('hello', async (args, ctx) => {
const name = args[0] || 'world';
return {
stdout: `Hello, ${name}!\n`,
stderr: '',
exitCode: 0,
};
});
const compute = justBash({ customCommands: [hello] });
const sandbox = await compute.sandbox.create();
const result = await sandbox.runCommand('hello Alice');
console.log(result.stdout);
Custom commands receive a context object (ctx) with access to:
ctx.fs — the virtual filesystem
ctx.cwd — current working directory
ctx.env — environment variables
ctx.stdin — standard input
ctx.exec(command) — run subcommands
API Reference
Code Execution
const result = await sandbox.runCommand(`
for i in 1 2 3; do
echo "Number: $i"
done
`);
console.log(result.stdout);
const compute = justBash({ python: true });
const sandbox = await compute.sandbox.create();
const result = await sandbox.runCommand(`python - <<'PY'
import json
data = {"message": "Hello from Python"}
print(json.dumps(data))
PY`);
Command Execution
const result = await sandbox.runCommand('echo -e "banana\\napple\\ncherry" | sort');
console.log(result.stdout);
await sandbox.filesystem.writeFile('/data.json', '[{"name":"Alice"},{"name":"Bob"}]');
const result = await sandbox.runCommand('cat /data.json | jq ".[].name"');
const result = await sandbox.runCommand('echo $MY_VAR', { env: { MY_VAR: 'hello' } });
const result = await sandbox.runCommand('cat config.json', { cwd: '/app' });
Filesystem Operations
await sandbox.filesystem.writeFile('/tmp/hello.txt', 'Hello World');
const content = await sandbox.filesystem.readFile('/tmp/hello.txt');
await sandbox.filesystem.mkdir('/tmp/data');
const files = await sandbox.filesystem.readdir('/tmp');
const exists = await sandbox.filesystem.exists('/tmp/hello.txt');
await sandbox.filesystem.remove('/tmp/hello.txt');
Sandbox Management
const info = await sandbox.getInfo();
console.log(info.id, info.provider, info.status);
const sandboxes = await compute.sandbox.list();
const existing = await compute.sandbox.getById('sandbox-id');
await sandbox.destroy();
Pre-populated Files
const compute = justBash({
files: {
'/app/config.json': '{"port": 3000}',
'/app/data.csv': 'name,age\nAlice,25\nBob,30',
},
env: {
APP_ENV: 'production',
},
cwd: '/app',
});
const sandbox = await compute.sandbox.create();
const result = await sandbox.runCommand('cat config.json');
console.log(result.stdout);
Built-in Commands
just-bash includes 60+ built-in commands:
| File ops | cat, cp, ls, mkdir, mv, rm, touch, tree, ln, find |
| Text processing | awk, grep, sed, cut, sort, uniq, wc, head, tail, tr |
| Data processing | jq (JSON), yq (YAML/XML), sqlite3 (SQLite), CSV tools |
| Compression | gzip, tar |
| Utilities | echo, printf, date, seq, timeout, basename, dirname |
| Shell | export, source, alias, test, read, set, unset |
Error Handling
import { justBash } from '@computesdk/just-bash';
const compute = justBash({});
const sandbox = await compute.sandbox.create();
const result = await sandbox.runCommand('cat /nonexistent');
if (result.exitCode !== 0) {
console.error('Command failed:', result.stderr);
}
try {
await sandbox.getUrl({ port: 3000 });
} catch (error) {
console.error(error.message);
}
Examples
Data Pipeline
import { justBash } from '@computesdk/just-bash';
const compute = justBash({});
const sandbox = await compute.sandbox.create();
await sandbox.filesystem.writeFile('/data/sales.csv',
'product,quantity,price\nWidget,100,9.99\nGadget,50,24.99\nDoohickey,200,4.99'
);
const result = await sandbox.runCommand(
'cat /data/sales.csv | tail -n +2 | awk -F, \'{ total += $2 * $3 } END { printf "Total revenue: $%.2f\\n", total }\''
);
console.log(result.stdout);
await sandbox.destroy();
JSON Processing
import { justBash } from '@computesdk/just-bash';
const compute = justBash({
files: {
'/data/users.json': JSON.stringify([
{ name: 'Alice', age: 30, role: 'admin' },
{ name: 'Bob', age: 25, role: 'user' },
{ name: 'Charlie', age: 35, role: 'admin' },
]),
},
});
const sandbox = await compute.sandbox.create();
const result = await sandbox.runCommand(
'cat /data/users.json | jq \'[.[] | select(.role == "admin") | .name]\''
);
console.log(result.stdout);
await sandbox.destroy();
Script Execution
import { justBash } from '@computesdk/just-bash';
const compute = justBash({});
const sandbox = await compute.sandbox.create();
const result = await sandbox.runCommand(`
#!/bin/bash
count=0
for f in /proc/self/status /etc/hostname; do
if test -f "$f"; then
count=$((count + 1))
fi
done
echo "Found $count system files"
`);
console.log(result.stdout);
await sandbox.destroy();
Limitations
- No Network Access -
getUrl() is not supported; curl requires explicit network config
- No Real Processes - Commands are interpreted in TypeScript, not executed as real OS processes
- No Native Node.js Runtime - use shell commands; this provider is bash-first and does not run a real Node.js VM
- In-Memory by Default - Files don't persist unless you use
OverlayFs, ReadWriteFs, or MountableFs
- Python via Pyodide - Python support requires
python: true and uses pyodide (WebAssembly-based)
When to Use just-bash
- Testing & Development - Fast, no-cost sandbox for development and CI
- AI Agent Tools - Secure bash execution for AI code generation
- Offline Environments - No network or API keys required
- Unit Tests - Deterministic, isolated test environments
License
MIT