moru-javascript

Use this skill when writing JavaScript or TypeScript code that interacts with Moru cloud sandboxes. This includes: creating sandboxes with `await Sandbox.create()`, running commands with `await sbx.commands.run()`, reading and writing files with `sbx.files.read()` and `sbx.files.write()`, working with persistent volumes using the `Volume` class, building custom templates with the `Template` builder, handling background processes, and streaming command output. The SDK includes full TypeScript types for `SandboxOpts`, `SandboxInfo`, `CommandResult`, `EntryInfo`, `VolumeInfo`, and more. Error handling uses typed exceptions: `TimeoutError`, `CommandExitError`, `AuthenticationError`, `NotFoundError`, `NotEnoughSpaceError` from `@moru-ai/core`. Use this skill whenever users want to: execute code safely in isolated environments from Node.js or browser applications, build AI agents that run untrusted code, create serverless functions that need compute isolation, or any JavaScript/TypeScript automation involving Moru sandboxes. Triggers on: 'moru javascript', 'moru typescript', 'moru node', '@moru-ai/core', 'npm install @moru', 'Sandbox.create', 'typescript sandbox', 'node sandbox', 'Volume.create', 'Template.build', or any JS/TS code that needs to run in isolated cloud environments. Do NOT use this skill for Python code - use moru-python instead.

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "moru-javascript" with this command: npx skills add moru-ai/skills/moru-ai-skills-moru-javascript

Moru JavaScript/TypeScript SDK

npm install @moru-ai/core

TypeScript types included.

Quick Start

import Sandbox from '@moru-ai/core'

const sbx = await Sandbox.create()
try {
  await sbx.files.write("/app/script.py", "print('Hello from Moru!')")
  const result = await sbx.commands.run("python3 /app/script.py")
  console.log(result.stdout)
} finally {
  await sbx.kill()
}

Quick Reference

TaskCode
Create sandboxawait Sandbox.create() or await Sandbox.create("template")
Run commandawait sbx.commands.run("cmd")
Read fileawait sbx.files.read("/path")
Write fileawait sbx.files.write("/path", "content")
Background processawait sbx.commands.run("cmd", { background: true })
Set timeoutSandbox.create({ timeoutMs: 600000 }) or sbx.setTimeout(600000)
Use volumeSandbox.create({ volumeId, volumeMountPath: "/workspace" })

Sandbox Lifecycle

Create

import Sandbox from '@moru-ai/core'

// Default template
const sbx = await Sandbox.create()

// Specific template
const sbx = await Sandbox.create("python")

// With options
const sbx = await Sandbox.create("python", {
  timeoutMs: 600000,                // milliseconds (default: 300000)
  metadata: { project: "myapp" },
  envs: { API_KEY: "secret" },
  volumeId: "vol_xxx",
  volumeMountPath: "/workspace",
  allowInternetAccess: true,
})

Connect to Existing

const sbx = await Sandbox.connect("sbx_abc123")
if (await sbx.isRunning()) {
  const result = await sbx.commands.run("echo still alive")
}

Kill

await sbx.kill()
// or
await Sandbox.kill("sbx_abc123")

List All

for await (const info of Sandbox.list()) {
  console.log(`${info.sandboxId}: ${info.state}`)
}

Running Commands

Basic

const result = await sbx.commands.run("echo hello")
console.log(result.stdout)      // "hello\n"
console.log(result.stderr)      // ""
console.log(result.exitCode)    // 0

With Options

const result = await sbx.commands.run("python3 script.py", {
  cwd: "/app",                              // Working directory
  user: "root",                             // Run as root
  envs: { DEBUG: "1" },                    // Environment variables
  timeoutMs: 120000,                        // Command timeout (ms)
  onStdout: (data) => process.stdout.write(data),  // Stream stdout
  onStderr: (data) => process.stderr.write(data),  // Stream stderr
})

Background Process

const handle = await sbx.commands.run("python3 server.py", { background: true })

// Get public URL
const url = sbx.getHost(8080)
console.log(`Server at: ${url}`)

// Send input
await handle.sendStdin("quit\n")

// Wait for completion
const result = await handle.wait()

// Or kill it
await handle.kill()

Process Management

// List running processes
for (const proc of await sbx.commands.list()) {
  console.log(`PID ${proc.pid}: ${proc.command}`)
}

// Kill by PID
await sbx.commands.kill(1234)

Working with Files

Read/Write

// Write
await sbx.files.write("/app/config.json", '{"key": "value"}')

// Read
const content = await sbx.files.read("/app/config.json")

// Binary
const bytes = await sbx.files.read("/app/image.png", { format: 'bytes' })
const blob = await sbx.files.read("/app/image.png", { format: 'blob' })
await sbx.files.write("/app/output.bin", binaryData)

// Stream large files
const stream = await sbx.files.read("/app/large.bin", { format: 'stream' })

Multiple Files

await sbx.files.write([
  { path: "/app/file1.txt", data: "content1" },
  { path: "/app/file2.txt", data: "content2" },
])

Directory Operations

// Check existence
if (await sbx.files.exists("/app/config.json")) {
  const config = await sbx.files.read("/app/config.json")
}

// List directory
for (const entry of await sbx.files.list("/app")) {
  console.log(`${entry.type}: ${entry.name} (${entry.size} bytes)`)
}

// Recursive list
const entries = await sbx.files.list("/app", { depth: 5 })

// Get info
const info = await sbx.files.getInfo("/app/file.txt")
console.log(`Size: ${info.size}, Modified: ${info.modifiedTime}`)

// Create directory
await sbx.files.makeDir("/app/data")

// Delete
await sbx.files.remove("/app/old_file.txt")

// Rename/Move
await sbx.files.rename("/app/old.txt", "/app/new.txt")

Watch for Changes

const handle = await sbx.files.watchDir("/app", (event) => {
  console.log(`${event.type}: ${event.name}`)
})
await handle.stop()

Volumes (Persistent Storage)

import Sandbox, { Volume } from '@moru-ai/core'

// Create volume (idempotent)
const vol = await Volume.create({ name: "my-workspace" })

// Attach to sandbox
const sbx = await Sandbox.create("base", {
  volumeId: vol.volumeId,
  volumeMountPath: "/workspace"  // Must be /workspace, /data, /mnt, or /volumes
})

// Data in /workspace persists after kill
await sbx.commands.run("echo 'persistent' > /workspace/data.txt")
await sbx.kill()

// Later - data still there
const sbx2 = await Sandbox.create("base", {
  volumeId: vol.volumeId,
  volumeMountPath: "/workspace"
})
const result = await sbx2.commands.run("cat /workspace/data.txt")
console.log(result.stdout)  // "persistent"

Volume Operations (No Sandbox Needed)

const vol = await Volume.get("my-workspace")

// List files
for (const f of await vol.listFiles("/")) {
  console.log(`${f.type}: ${f.name}`)
}

// Download/Upload
const content = await vol.download("/data.txt")
await vol.upload("/config.json", Buffer.from('{"key": "value"}'))

// Delete file
await vol.delete("/old_file.txt")

// Delete volume (WARNING: permanent)
await vol.delete()

Templates

import { Template, waitForPort } from '@moru-ai/core'

// Define template
const template = Template()
  .fromPythonImage("3.11")
  .aptInstall(["curl", "git"])
  .pipInstall(["flask", "pandas", "requests"])
  .copy("./app", "/app")
  .setWorkdir("/app")
  .setEnvs({ FLASK_ENV: "production" })
  .setStartCmd("python app.py", waitForPort(5000))

// Build
const info = await Template.build(template, { alias: "my-flask-app" })

// Use
const sbx = await Sandbox.create("my-flask-app")

From Dockerfile

const template = Template().fromDockerfile("./Dockerfile")
await Template.build(template, { alias: "my-app" })

Build Options

await Template.build(template, {
  alias: "my-app",
  cpuCount: 4,
  memoryMB: 2048,
  onBuildLogs: (entry) => console.log(entry.message),
})

// Background build
const info = await Template.buildInBackground(template, { alias: "my-app" })
const status = await Template.getBuildStatus(info)  // building, success, failed

Error Handling

import Sandbox, {
  SandboxError,              // Base
  TimeoutError,              // Operation timed out
  NotFoundError,             // Resource not found
  AuthenticationError,       // Invalid API key
  NotEnoughSpaceError,       // Disk full
  CommandExitError,          // Non-zero exit (has exitCode, stdout, stderr)
} from '@moru-ai/core'

try {
  const sbx = await Sandbox.create()
  try {
    const result = await sbx.commands.run("python3 script.py", { timeoutMs: 30000 })
  } finally {
    await sbx.kill()
  }
} catch (error) {
  if (error instanceof TimeoutError) {
    console.log("Command timed out")
  } else if (error instanceof CommandExitError) {
    console.log(`Failed with exit code ${error.exitCode}: ${error.stderr}`)
  } else if (error instanceof AuthenticationError) {
    console.log("Invalid API key - check MORU_API_KEY")
  }
}

TypeScript Types

import type {
  SandboxOpts,
  SandboxInfo,
  CommandResult,
  CommandStartOpts,
  EntryInfo,
  VolumeInfo,
} from '@moru-ai/core'

Common Pitfalls

Always cleanup sandboxes

// ❌ WRONG
const sbx = await Sandbox.create()
await sbx.commands.run("echo hello")
// Forgot to kill - sandbox keeps running!

// ✅ CORRECT
const sbx = await Sandbox.create()
try {
  await sbx.commands.run("echo hello")
} finally {
  await sbx.kill()
}

Don't assume packages exist

// ❌ WRONG
await sbx.commands.run("python3 -c 'import pandas'")  // ImportError!

// ✅ CORRECT
await sbx.commands.run("pip install pandas", { timeoutMs: 120000 })
await sbx.commands.run("python3 -c 'import pandas'")

Write to volume path for persistence

// ❌ WRONG - lost on kill
await sbx.files.write("/home/user/data.txt", "important")

// ✅ CORRECT - persisted
await sbx.files.write("/workspace/data.txt", "important")

Handle command failures

const result = await sbx.commands.run("python3 script.py")
if (result.exitCode !== 0) {
  console.log(`Error: ${result.stderr}`)
}

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Coding

moru-python

No summary provided by upstream source.

Repository SourceNeeds Review
General

moru

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

frontend-design

Create distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, artifacts, posters, or applications (examples include websites, landing pages, dashboards, React components, HTML/CSS layouts, or when styling/beautifying any web UI). Generates creative, polished code and UI design that avoids generic AI aesthetics.

Repository SourceNeeds Review
94.2K159.5K
anthropics