Elixir SDK for Sprites - a code container runtime for interactive development.
Add sprites to your list of dependencies in mix.exs:
def deps do
[
{:sprites, "~> 0.1.0"}
]
end# Create a client
client = Sprites.new(token, base_url: "https://api.sprites.dev")
# Get a sprite handle
sprite = Sprites.sprite(client, "my-sprite")
# Execute a command synchronously (like System.cmd/3)
{output, exit_code} = Sprites.cmd(sprite, "echo", ["hello"])
IO.puts(output) # => "hello\n"
# Execute a command asynchronously (like Port message passing)
{:ok, command} = Sprites.spawn(sprite, "ls", ["-la"])
receive do
{:stdout, ^command, data} -> IO.write(data)
{:stderr, ^command, data} -> IO.write(:stderr, data)
{:exit, ^command, code} -> IO.puts("Exited with: #{code}")
end# Create a client
client = Sprites.new(token, base_url: "https://api.sprites.dev")
# Get a sprite handle (doesn't create the sprite)
sprite = Sprites.sprite(client, "my-sprite")
# Create a new sprite
{:ok, sprite} = Sprites.create(client, "new-sprite")
# Destroy a sprite
:ok = Sprites.destroy(sprite)# Basic execution
{output, exit_code} = Sprites.cmd(sprite, "echo", ["hello"])
# With options
{output, code} = Sprites.cmd(sprite, "ls", ["-la"],
dir: "/app",
env: [{"FOO", "bar"}],
timeout: 30_000,
stderr_to_stdout: true
)
# With TTY
{output, code} = Sprites.cmd(sprite, "bash", ["-c", "tty"],
tty: true,
tty_rows: 24,
tty_cols: 80
)# Start a command
{:ok, command} = Sprites.spawn(sprite, "bash", ["-i"], tty: true)
# Messages are sent to the calling process:
# - {:stdout, command, data}
# - {:stderr, command, data}
# - {:exit, command, exit_code}
# - {:error, command, reason}
# Write to stdin
Sprites.write(command, "ls\n")
# Close stdin (send EOF)
Sprites.close_stdin(command)
# Wait for completion
{:ok, exit_code} = Sprites.await(command)
# Resize TTY
Sprites.resize(command, 40, 120)Asynchronous callers can opt into session_info: true to receive
{:session_info, %{ref: ref}, session_id} from a provider session_info control
frame. Match ref against command.ref. The ID is normalized to a string;
duplicate identical frames produce one notification. Other metadata fields are
not forwarded.
Persist this identity with the intended sandbox and execution before using it for later attachment or termination. Missing metadata gives no identity. Invalid or conflicting IDs produce an error and close the local command transport; this does not confirm that the remote process stopped. Existing callers receive no additional messages unless they opt in.
# Stream command output
sprite
|> Sprites.stream("tail", ["-f", "/var/log/app.log"])
|> Stream.filter(&String.contains?(&1, "ERROR"))
|> Stream.each(&Logger.error/1)
|> Stream.run()The SDK includes a test CLI for integration testing with the shared test harness:
cd test_cli
mix deps.get
mix escript.build
# Set auth token
export SPRITES_TOKEN=your-token
# Create a sprite
./test-cli create my-sprite
# Run a command
./test-cli -sprite my-sprite -output stdout echo hello
# Interactive TTY
./test-cli -sprite my-sprite -tty bash
# Destroy the sprite
./test-cli destroy my-sprite| Flag | Description |
|---|---|
-base-url <url> |
API base URL (default: https://api.sprites.dev) |
-sprite <name> |
Sprite name (required for exec) |
-output <mode> |
Output mode: stdout, combined, exit-code, default |
-tty |
Enable TTY mode |
-tty-rows <n> |
TTY rows (default: 24) |
-tty-cols <n> |
TTY columns (default: 80) |
-timeout <dur> |
Command timeout (e.g., 10s, 5m) |
-dir <path> |
Working directory |
-env key=val |
Environment variables |
-log-target <path> |
JSON event log file |
The Elixir SDK is compatible with the shared test harness:
cd /path/to/sprite-env/sdks/test
export SPRITES_TEST_TOKEN=your-token
export SDK_TEST_COMMAND=/path/to/sprites-ex/test_cli/test-cli
make test-allRequests and WebSocket handshakes carry coarse, privacy-safe
client-signals attribution in
Fly-Client-* headers and a sprites-ex/<version> User-Agent suffix. These
signals help Fly.io estimate how much API traffic is human- or agent-driven;
they are advisory only and are not used for gating or rate-limiting.
Set SPRITES_CLIENT_SIGNALS=0 to opt out. The values off, false, no, and
disabled are also accepted. When disabled, the SDK still sends its plain
User-Agent but does not detect or send client signals.
Signals and the opt-out setting are read once, on first SDK use, and cached for the lifetime of the BEAM instance.
MIT