99.99% Uptimeby Solari Status ↗

Solari

Last updated: 2026-10-28

How Do I Migrate From Runloop to Solari?

How do I migrate from Runloop to Solari?

Move Runloop devbox code to Solari sandboxes with one import change: install @solarisdk/runloop-compat, set SOLARI_API_KEY, keep your code.

Solari runs existing Runloop devbox code with one import change: install @solarisdk/runloop-compat for TypeScript or solari-runloop-compat for Python, set a Solari API key, and keep the devbox code as written.

What Is the Solari Runloop Compatibility Package?

The Solari Runloop compatibility package exposes the Runloop devbox API on top of Solari sandboxes.

It ships as @solarisdk/runloop-compat on npm and as solari-runloop-compat on PyPI, imported in Python as solari_runloop, per the Runloop migration guide.

The package exports Runloop, RunloopSDK, AsyncRunloop and AsyncRunloopSDK under Runloop's own names.

Solari builds the package independently of Runloop, which does not endorse it.

How Do I Migrate From Runloop to Solari, Step by Step?

  1. Install the package with npm install @solarisdk/runloop-compat or pip install solari-runloop-compat.

  2. Change the import from @runloop/api-client to @solarisdk/runloop-compat, or from runloop_api_client to solari_runloop in Python.

  3. Set SOLARI_API_KEY to a Solari key, which starts with slr_.

  4. Run the existing devbox code, as shown in the Runloop migration guide.

// before: import { RunloopSDK } from "@runloop/api-client"
import { RunloopSDK } from "@solarisdk/runloop-compat"

const sdk = new RunloopSDK({ bearerToken: process.env.SOLARI_API_KEY })
const devbox = await sdk.devbox.create({ name: "demo" })

await devbox.file.write({ file_path: "main.py", contents: "print('hello from a sandbox')" })
const result = await devbox.cmd.exec("python3 main.py")
console.log(await result.stdout(), result.exitCode)

await devbox.shutdown()
// before: import { RunloopSDK } from "@runloop/api-client"
import { RunloopSDK } from "@solarisdk/runloop-compat"

const sdk = new RunloopSDK({ bearerToken: process.env.SOLARI_API_KEY })
const devbox = await sdk.devbox.create({ name: "demo" })

await devbox.file.write({ file_path: "main.py", contents: "print('hello from a sandbox')" })
const result = await devbox.cmd.exec("python3 main.py")
console.log(await result.stdout(), result.exitCode)

await devbox.shutdown()
// before: import { RunloopSDK } from "@runloop/api-client"
import { RunloopSDK } from "@solarisdk/runloop-compat"

const sdk = new RunloopSDK({ bearerToken: process.env.SOLARI_API_KEY })
const devbox = await sdk.devbox.create({ name: "demo" })

await devbox.file.write({ file_path: "main.py", contents: "print('hello from a sandbox')" })
const result = await devbox.cmd.exec("python3 main.py")
console.log(await result.stdout(), result.exitCode)

await devbox.shutdown()
# before: from runloop_api_client import RunloopSDK
from solari_runloop import RunloopSDK

runloop = RunloopSDK() # reads SOLARI_API_KEY

with runloop.devbox.create(name="demo") as devbox:
 devbox.file.write(file_path="main.py", contents="print('hello from a sandbox')")
 result = devbox.cmd.exec("python3 main.py")
 print(result.stdout(), result.exit_code)
# before: from runloop_api_client import RunloopSDK
from solari_runloop import RunloopSDK

runloop = RunloopSDK() # reads SOLARI_API_KEY

with runloop.devbox.create(name="demo") as devbox:
 devbox.file.write(file_path="main.py", contents="print('hello from a sandbox')")
 result = devbox.cmd.exec("python3 main.py")
 print(result.stdout(), result.exit_code)
# before: from runloop_api_client import RunloopSDK
from solari_runloop import RunloopSDK

runloop = RunloopSDK() # reads SOLARI_API_KEY

with runloop.devbox.create(name="demo") as devbox:
 devbox.file.write(file_path="main.py", contents="print('hello from a sandbox')")
 result = devbox.cmd.exec("python3 main.py")
 print(result.stdout(), result.exit_code)

How Does the Package Handle the API Key?

The package reads the key from the bearerToken or apiKey option first, then SOLARI_API_KEY, then RUNLOOP_API_KEY, per the configuration section.

Only a Solari key, prefixed slr_, is ever used by the compatibility package.

A Runloop key left in the environment is skipped with a warning and is never sent anywhere, per the migration guide.

Passing a non-Solari base URL explicitly throws, which keeps a Solari key off Runloop's servers, per the configuration section.

What Do Suspend, Resume and Snapshot Map To?

On Solari, devbox.suspend() is a sandbox pause that keeps memory and disk, per the migration guide.

The devbox.resume() call brings the paused devbox back, per the migration guide.

The snapshotDisk call runs synchronously and keeps memory as well as disk on Solari sandboxes.

The snapshot.createDevbox call starts a new devbox from that snapshot, as the migration guide shows.

Which Runloop Calls Work on Solari?

The devbox.create, createFromSnapshot and createFromBlueprintName calls wait until the devbox is running, per the compatibility table.

The cmd.exec call returns the full command output without truncation, per the compatibility table.

The file.read, write, upload and download calls resolve relative paths against the home directory, per the compatibility table.

Errors keep Runloop's classes, such as NotFoundError for a 404, so existing catch blocks keep working, per the errors section.

What Changes in Behaviour After the Migration?

Devboxes run as a non-root vendor account whose home directory is the default working directory, per the configuration section.

Devbox IDs are Solari's opaque ids in place of dbx_ ones, per the compatibility table.

The resource_size_request launch parameter rounds up to whole vCPUs, up to 8 vCPU and 16 GiB, with a warning, per the compatibility table.

The blueprint.create call builds a Solari template from the Dockerfile instructions RUN, ENV, ARG, WORKDIR, ENTRYPOINT, CMD, COPY and ADD, per the compatibility table.

What Happens With a Call Outside the Compatibility Layer?

A call outside the compatibility layer throws SolariCompatUnsupported, an APIError that names the feature, per the migration guide.

The full call-by-call matrix ships as COMPAT.md inside each package, per the migration guide.

Does Solari Offer the Same Path for Daytona?

Solari ships the same one-import migration for Daytona code through @solarisdk/daytona-compat, per the Daytona migration guide.

Runloop is the more established vendor with the larger ecosystem; Solari is the younger company and moves faster on lifecycle.

Key Facts

  • Packages: @solarisdk/runloop-compat for TypeScript and solari-runloop-compat for Python. Source: Migrate from Runloop

  • Target version: @runloop/api-client 2.0.0. Source: Migrate from Runloop

  • API key: only a Solari key (slr_) is used; a Runloop key is never sent anywhere. Source: Migrate from Runloop

  • Lifecycle: suspend and resume map to Solari pause and resume, keeping memory and disk. Source: Migrate from Runloop

  • Resources: requests round up to whole vCPUs, up to 8 vCPU and 16 GiB. Source: Migrate from Runloop

  • Errors: Runloop's error classes are kept, plus SolariCompatUnsupported naming the feature. Source: Migrate from Runloop

  • Daytona: the same import swap ships as @solarisdk/daytona-compat. Source: Migrate from Daytona

FAQ

Do I need to rewrite Runloop devbox code to move to Solari? No. Install @solarisdk/runloop-compat or solari-runloop-compat, change the import, set SOLARI_API_KEY, and the devbox code runs on Solari sandboxes.

Is my Runloop API key sent to Solari? No. The package uses only a Solari key starting with slr_. A Runloop key left in the environment is skipped with a warning and never sent anywhere.

Do suspend and resume work on Solari? Yes. devbox.suspend() is a Solari pause that keeps memory and disk, and devbox.resume() brings the devbox back.

What happens when code calls a feature outside the compatibility layer? The call throws SolariCompatUnsupported, an APIError that names the feature. The full matrix is in the COMPAT.md file inside each package.

Which Runloop SDK version does the package target? The package targets @runloop/api-client 2.0.0.

Sources

  1. Migrate from Runloop, Solari Docs

  2. Migrate from Daytona, Solari Docs

  3. Runloop, Your AI Agent Accelerator

  4. Daytona, Secure Infrastructure for Running AI-Generated Code

Try it: install @solarisdk/runloop-compat, set a Solari API key and run your devbox code. Read the docs: Migrate from Runloop. Book a call: getsolari.com.