Docs / quickstart / install-custom-packages

Install custom packages

Add Python and Node dependencies to a Runra sandbox.

Runra sandboxes start from a template image. For small or changing dependencies, install packages at runtime. For heavy or repeated dependencies, build a custom template and pass its template ID to Sandbox.create().

Prerequisites

  • Completed the Quickstart.
  • RUNRA_API_KEY set in your environment.

Install Python packages

Use commands.run() to call pip inside the sandbox:

import { Sandbox } from "runra";

const sbx = await Sandbox.create({ timeout: 900 });

try {
  const install = await sbx.commands.run(
    "python -m pip install --quiet pandas requests",
    { timeoutMs: 120_000 }
  );

  if (install.stderr) console.error(install.stderr);

  const execution = await sbx.runCode(`
import pandas as pd
import requests

print("pandas", pd.__version__)
print("requests", requests.__version__)
`);

  console.log(execution.logs.stdout.join("\n"));
} finally {
  await sbx.kill();
}

Install from requirements.txt

await sbx.files.write(
  "/home/user/requirements.txt",
  "numpy\npandas\nscikit-learn\n"
);

await sbx.commands.run(
  "python -m pip install --quiet -r /home/user/requirements.txt",
  { timeoutMs: 180_000 }
);

Install Node packages

Create a working directory, initialize a package, and install dependencies:

await sbx.commands.run("mkdir -p /home/user/app");
await sbx.files.write(
  "/home/user/app/package.json",
  JSON.stringify(
    {
      type: "module",
      dependencies: {
        zod: "latest",
        lodash: "latest",
      },
    },
    null,
    2
  )
);

await sbx.commands.run("cd /home/user/app && npm install", {
  timeoutMs: 180_000,
});

const result = await sbx.commands.run(
  "cd /home/user/app && node -e 'import { z } from \"zod\"; console.log(z.string().parse(\"ok\"))'"
);

console.log(result.stdout);

Use a custom template for repeated dependencies

Runtime installation is simple but adds latency to every sandbox. If your agents always need the same dependencies, preinstall them in a template and pass the template ID at creation time:

const sbx = await Sandbox.create({
  template: process.env.RUNRA_TEMPLATE_ID,
  timeout: 900,
});

You can also configure it once in the environment:

export RUNRA_TEMPLATE_ID=tpl_your_prebuilt_template

Then all Sandbox.create() calls use that template unless you override template explicitly.

Choosing runtime install vs templates

ApproachUse whenTradeoff
Runtime installDependencies change often or are small.Slower startup for each sandbox.
Custom templateDependencies are large or reused by many jobs.Requires a build step when dependencies change.

Best practices

  • Pin versions for production workflows, for example pandas==2.2.2.
  • Use longer command timeouts for package managers.
  • Keep generated project files under /home/user.
  • Cache heavy, stable dependencies in a template instead of reinstalling them in every sandbox.
  • Do not bake secrets into templates. Pass secrets as environment variables at sandbox creation time:
const sbx = await Sandbox.create({
  envs: {
    OPENAI_API_KEY: process.env.OPENAI_API_KEY ?? "",
  },
});