> ## Documentation Index
> Fetch the complete documentation index at: https://docs.fly.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Quickstart

<Frame>
  <img src="https://mintcdn.com/fly-io/RkpeOaMN_WxQUxWf/sprites/images/quickstart.png?fit=max&auto=format&n=RkpeOaMN_WxQUxWf&q=85&s=a40ff7b427fdff93f5a87799455c6cf9" alt="A bespectacled bird reading a quickstart guide while a small creature sleeps in a tiny bed nearby" width="1600" height="840" data-path="sprites/images/quickstart.png" />
</Frame>

Sprites are cloud VMs that feel like persistent dev environments. You can run commands, install packages, create files—and everything stays exactly how you left it. Unlike containers that reset each time, Sprites remember your entire filesystem between sessions.

The magic: when you're not using your Sprite, it goes to sleep. Send a command or HTTP request, and it wakes up instantly. Everything is right where you left it.

This guide will walk you through creating your first Sprite. In just a few minutes, you'll have a persistent development environment that responds to HTTP traffic and remembers everything between runs.

## Install the CLI

Install with our install script (macOS/Linux):

```bash theme={null}
curl -fsSL https://sprites.dev/install.sh | sh
```

This script auto-detects your platform, verifies checksums, and installs the latest Sprite CLI to `~/.local/bin`.

For Windows or manual installation, see [CLI Installation](/sprites/cli/installation).

Verify installation:

```bash theme={null}
sprite --help
```

## Authenticate

Sprites uses your Fly.io account for authentication:

```bash theme={null}
sprite org auth
```

This opens a browser window to authenticate with Fly.io.

<Info>
  If authentication fails, try running `fly auth logout` followed by `fly auth login` first, then retry `sprite org auth`.
</Info>

## Create Your First Sprite

```bash theme={null}
sprite create my-first-sprite
```

This creates a new Sprite with default configuration, running and ready to accept commands.

Set it as your active Sprite to avoid adding `-s my-first-sprite` to every command:

```bash theme={null}
sprite use my-first-sprite
```

Use `sprite list` to see all your Sprites, or `sprite destroy -s my-first-sprite` when you're done with one. You can have multiple Sprites running simultaneously—each with its own isolated environment.

## Run Commands

Execute commands in your Sprite:

```bash theme={null}
# Run a simple command
sprite exec -- echo "Hello, Sprites!"

# Run multiple commands
sprite exec -- bash -c "cd /tmp && ls -la"

# Open an interactive shell
sprite console
```

<Info>
  **Auto-wakeup magic**: When you're not using your Sprite, it shuts down to save resources. When you run a command or hit its URL, it wakes up instantly—like magic. No manual starting or stopping required.
</Info>

## See Persistence in Action

Your Sprite comes pre-configured with common development tools (Node.js, Python, Go, Git, and more). Here's the magic: **everything you install or create persists between commands**.

### Check available runtimes

See what's already installed and ready to use:

```bash theme={null}
sprite exec -- bash -c "node --version && python3 --version && go version"
```

### Install a package

Install dependencies just like you would locally—they'll stick around:

```bash theme={null}
sprite exec -- pip install requests
```

### Create and read files

Files you create persist across sessions. Write once, read anytime:

```bash theme={null}
# Create a file
sprite exec -- bash -c "echo 'Hello from my persistent Sprite!' > /home/sprite/greeting.txt"

# Disconnect, get coffee, come back later...
# Everything is still there!
sprite exec -- cat /home/sprite/greeting.txt
sprite exec -- python -c "import requests; print(requests.__version__)"
```

Unlike containers that reset on each run, your Sprite keeps your installed packages, files, and entire filesystem intact.

## Start a Web Server

Every Sprite has a unique HTTP URL and can serve traffic. This makes it perfect for testing APIs, hosting prototypes, or running background services.

### Serve HTTP

First, get your Sprite's public URL:

```bash theme={null}
sprite info
```

Then start a simple Python server:

```bash theme={null}
sprite exec -- python -m http.server 8080
```

Visit the URL in your browser—you'll see Python's directory listing page. Press `Ctrl+C` to stop the server when you're done. Your Sprite automatically routes HTTP traffic to port 8080 and wakes up to handle requests.

<Info>
  By default, your Sprite's URL requires authentication. To make it publicly accessible, run:

  ```bash theme={null}
  sprite config update --url-auth public
  ```

  The `sprite` auth mode (the default) requires a Sprite token with Bearer authentication.
</Info>

### Test on-demand wake-up

Here's where it gets cool. Close your terminal, wait a minute, then visit the URL again. Your Sprite wakes up automatically to serve the request. That's the magic of on-demand wakeup—no manual starting or stopping required.

***

<Tip>
  **You've got a working Sprite!** You've created a persistent environment, installed packages, created files, and served HTTP traffic—all of which will be there next time you connect. Try cloning a repo, running a build, or deploying a tiny HTTP service to see what else you can do.
</Tip>

## Using the SDKs

The CLI is perfect for day-to-day development, but if you're building tools, automation workflows, or integrating Sprites into your application, the SDKs give you programmatic control. Use them to dynamically create environments, orchestrate workloads, or embed Sprites into your product.

<CodeGroup>
  ```javascript JavaScript theme={null}
  import { SpritesClient } from '@fly/sprites';

  const client = new SpritesClient(process.env.SPRITE_TOKEN);

  const sprite = await client.createSprite('my-sprite');

  // Execute a command
  const result = await sprite.execFile('python', ['-c', "print('hello')"]);
  console.log(result.stdout);

  // Stream output from long-running commands
  const cmd = sprite.spawn('bash', ['-c', 'for i in {1..10}; do date +%T; sleep 0.5; done']);
  for await (const line of cmd.stdout) {
    process.stdout.write(line);
  }

  await sprite.delete();
  ```

  ```go Go theme={null}
  package main

  import (
      "context"
      "fmt"
      "io"
      "os"

      sprites "github.com/superfly/sprites-go"
  )

  func main() {
      ctx := context.Background()
      client := sprites.New(os.Getenv("SPRITE_TOKEN"))

      sprite, _ := client.CreateSprite(ctx, "my-sprite", nil)
      defer client.DeleteSprite(ctx, "my-sprite")

      // Execute a command
      cmd := sprite.Command("python", "-c", "print('hello')")
      output, _ := cmd.Output()
      fmt.Println(string(output))

      // Stream output from long-running commands
      cmd = sprite.Command("bash", "-c", "for i in {1..10}; do date +%T; sleep 0.5; done")
      stdout, _ := cmd.StdoutPipe()
      cmd.Start()
      io.Copy(os.Stdout, stdout)
      cmd.Wait()
  }
  ```

  ```elixir Elixir theme={null}
  client = Sprites.new(System.get_env("SPRITE_TOKEN"))

  {:ok, sprite} = Sprites.create(client, "my-sprite")

  # Execute a command
  {output, 0} = Sprites.cmd(sprite, "python", ["-c", "print('hello')"])
  IO.puts(output)

  # Stream output from long-running commands
  sprite
  |> Sprites.stream("bash", ["-c", "for i in {1..10}; do date +%T; sleep 0.5; done"])
  |> Stream.each(&IO.write/1)
  |> Stream.run()

  Sprites.destroy(sprite)
  ```
</CodeGroup>

***

## Next Steps

<CardGroup cols={2}>
  <Card title="Working with Sprites" icon="book-open" href="/sprites/working-with-sprites">
    Sessions, ports, persistence, and everything beyond the basics
  </Card>

  <Card title="CLI Reference" icon="terminal" href="/sprites/cli/commands">
    Complete command-line documentation
  </Card>
</CardGroup>
