Solari

SDKs & Languages

Every Solari SDK speaks the same gateway wire protocol, so you can drive a sandbox or VM from the language your project already lives in. TypeScript and Python are at full parity; Go, Rust, and C++ ship the core surface: create and connect a session plus the commands, files, code.run, and git namespaces, with more to follow.

This page covers the VM & sandbox SDKs. The Cloud Browser ships its own separate packages. See Browser SDKs. Both products export a class named Solari, so check the install line matches the product you want.

Availability

LanguagePackage / moduleSurface
TypeScript@solarisdk/sandbox, @solarisdk/desktopFull: computer-use, PTY, viewer, snapshots
Pythonsolari-sandbox, solari-desktopFull: computer-use, PTY, viewer, snapshots
Gogithub.com/solari-sdk/solari-sandbox-goCore: commands, files, code, git
Rustsolari-sandboxCore: commands, files, code, git
C++ (17)solari:: (CMake)Core: commands, files, code, git

Each binding is idiomatic for its language. Go is context-first with typed error values, Rust is async/tokio returning Result<T, SolariError>, and C++ is a blocking API over libcurl + a WebSocket client + nlohmann/json. The same API key authenticates every one of them.

TypeScript

npm install @solarisdk/sandbox
import { SandboxClient } from "@solarisdk/sandbox"

const sandboxes = new SandboxClient({
  apiKey: process.env.SOLARI_API_KEY!,
  baseUrl: "https://api.getsolari.com",
})

const sbx = await sandboxes.create({ template: "base" })
const res = await sbx.commands.run("echo", { args: ["hello", "world"] })
console.log(res.exitCode, res.stdout)
await sbx.kill()

Python

pip install solari-sandbox
import os
from solari_sandbox import SandboxClient

sandboxes = SandboxClient(
    api_key=os.environ["SOLARI_API_KEY"],
    base_url="https://api.getsolari.com",
)

sbx = await sandboxes.create(template="base")
res = await sbx.commands.run("echo", args=["hello", "world"])
print(res.exit_code, res.stdout)
await sbx.kill()

Go

go get github.com/solari-sdk/solari-sandbox-go
package main

import (
	"context"
	"fmt"
	"log"

	solari "github.com/solari-sdk/solari-sandbox-go"
)

func main() {
	ctx := context.Background()
	client, err := solari.NewClient(solari.ClientOptions{
		APIKey:  "slr_live_…",
		BaseURL: "https://api.getsolari.com",
	})
	if err != nil {
		log.Fatal(err)
	}

	sb, err := client.Create(ctx, solari.CreateOptions{Template: "base"})
	if err != nil {
		log.Fatal(err)
	}
	defer sb.Kill(ctx)

	// The first run rides the warm REST /exec fast path; call sb.Connect(ctx)
	// to open the control WebSocket for streaming or interactive work.
	res, err := sb.Commands.Run(ctx, "echo", solari.CommandOptions{
		Args: []string{"hello", "world"},
	})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("exit=%d stdout=%q\n", res.ExitCode, res.Stdout)
}

Rust

# Cargo.toml
solari-sandbox = "0.1"
use solari::{Client, ClientOptions, CreateOptions, RunOptions};

#[tokio::main]
async fn main() -> Result<(), solari::SolariError> {
    let client = Client::new(ClientOptions::new(
        "slr_live_…",
        "https://api.getsolari.com",
    ))?;

    let sbx = client
        .create(CreateOptions { template: Some("base".into()), ..Default::default() })
        .await?;

    let out = sbx
        .commands()
        .run("echo", RunOptions::new().args(["hello world"]))
        .await?;
    println!("exit={} stdout={:?}", out.exit_code, out.stdout);

    sbx.kill().await?;
    Ok(())
}

C++

The C++ binding is a CMake project; pull it in with FetchContent (it vendors libcurl + a WebSocket client + nlohmann/json). Build with SOLARI_WITH_WS=ON for streaming and interactive work.

#include <iostream>
#include <solari/solari.hpp>

int main() {
  solari::ClientOptions opts;
  opts.apiKey  = "slr_live_...";
  opts.baseUrl = "https://api.getsolari.com";
  solari::Client client(opts);

  auto sbx = client.create();          // POST /sandboxes
  solari::CommandOptions o;
  o.args = {"hello", "world"};
  solari::CommandResult r = sbx->commands.run("echo", o);
  std::cout << "exit " << r.exitCode << "\n" << r.stdout_;

  sbx->kill();
}
One protocol, many clients
All bindings implement the same REST + control-WebSocket contract, so a session created in one language can be driven from another, and new languages only need to speak the wire, so there is no per-language server component.