Metadata-Version: 2.4
Name: flaxcloud
Version: 0.5.0
Summary: Python SDK and CLI for Flax Cloud: isolated cloud sandboxes.
Project-URL: Homepage, https://flaxcloud.com
Project-URL: Documentation, https://github.com/tomitokko/flax-cloud/blob/main/docs/user/sdk.md
Project-URL: Source, https://github.com/tomitokko/flax-cloud
Project-URL: Issues, https://github.com/tomitokko/flax-cloud/issues
Author: Flax Cloud
License: MIT License
        
        Copyright (c) 2026 Flax Cloud
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
License-File: LICENSE
Keywords: agents,cloud,code execution,flax,sandbox
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Typing :: Typed
Requires-Python: >=3.9
Requires-Dist: httpx>=0.24
Description-Content-Type: text/markdown

# flaxcloud - Python SDK & CLI for Flax Cloud

Programmatic access to [Flax Cloud](https://flaxcloud.com) isolated sandboxes: create them,
run commands, move files, preview servers, and wire them into agents/automation.

## Install

```bash
pip install flaxcloud
```

## Authenticate

Get an API key from the dashboard, then either set an environment variable or log in with the
CLI (which stores it in `~/.config/flax/config.json`):

```bash
export FLAX_API_KEY=flax_live_...
# or
flax login
```

## SDK

```python
from flaxcloud import FlaxClient

flax = FlaxClient()  # reads FLAX_API_KEY

# create_sandbox returns a handle with methods; use it as a context manager to auto-destroy
with flax.create_sandbox(template="python", name="ci-run") as sb:
    print(sb.name, sb.id)
    out = sb.run("python3 -c 'print(6*7)'")
    print(out.stdout)          # "42\n"

    sb.upload("/workspace/app.py", "print('hello')\n")
    print(sb.run("python3 app.py").stdout)

    # long-running server + a shareable preview link
    sb.set_startup("python3 -m http.server 8000 --bind 0.0.0.0")
    sb.run_startup()
    print(sb.create_preview_link(8000).url)
```

Background commands:

```python
sb = flax.create_sandbox(template="node")
job = sb.run("npm install", background=True)
done = sb.wait(job, timeout=600)
print(done.status, done.exit_code)
```

Environment variables, code execution, git, and filesystem helpers:

```python
sb = flax.create_sandbox(template="python", env={"API_BASE": "https://example.com"})
sb.run("printenv TOKEN", env={"TOKEN": "secret"})        # per-command override
sb.code_run("print(6*7)", language="python")             # also node/bash/ruby
sb.git.clone("https://github.com/me/repo.git", "/workspace/repo")
sb.mkdir("/workspace/out"); sb.find("/workspace", name="*.py")
```

Stateful sessions - working directory and exported env persist across commands:

```python
with sb.create_session() as s:        # auto-deletes on exit
    s.run("cd /workspace && export TOKEN=abc")
    print(s.run("pwd").stdout)         # /workspace
    print(s.run("echo $TOKEN").stdout) # abc
```

Streaming - live combined stdout/stderr as the command runs:

```python
stream = sb.run_stream("for i in 1 2 3; do echo $i; sleep 1; done")
for chunk in stream:
    print(chunk, end="", flush=True)
print("exit:", stream.exit_code)
```

Custom images - register any public registry image, then create sandboxes from it:

```python
tpl = flax.create_template("my-python", image="python:3.12-slim")  # waits until ready
sb = flax.create_sandbox(template="my-python")
print(sb.run("python3 --version").stdout)
```

You can also build a custom image from a Dockerfile (`flax.create_template(..., dockerfile=...)`,
streamed with `flax.build_logs(id)`), or describe it declaratively with `FlaxImage` and let the SDK
generate the Dockerfile for you. The declarative builder uses the same Dockerfile build flow under
the hood, so build status, logs, and `wait` behave identically:

```python
from flaxcloud import FlaxImage

image = (
    FlaxImage.python("3.12")
    .apt_install(["git", "ffmpeg"])
    .pip_install(["requests", "beautifulsoup4"])
    .env({"PYTHONUNBUFFERED": "1"})
    .workdir("/workspace")
)

# Inspect the generated Dockerfile if you want:
print(image.to_dockerfile())

template = flax.create_template_from_image_definition("scraper-agent", image, wait=True)
sb = flax.create_sandbox(template="scraper-agent")
```

`FlaxImage` constructors: `base(image)`, `python(version)`, `node(version)`, `debian_slim()`.
Steps (chainable): `apt_install`, `pip_install`, `npm_install`, `run`, `env`, `workdir`,
`copy_file`, `copy_dir`. Each package/argument is single-quoted and validated, so version
specifiers like `"requests>=2,<3"` are safe; use `.run(...)` for anything custom. Note:
`copy_file`/`copy_dir` need a local build context, which the hosted builder does not accept yet, so
templates that use them can't be built remotely for now (use `.run(...)` to fetch files instead).

Filesystem snapshots - capture a prepared sandbox and create fresh sandboxes from it:

```python
sb = flax.create_sandbox(template="python", env={"READY": "1"})
sb.upload("/workspace/app.py", "print('ready')\n")
snap = sb.create_snapshot("agent-base")
sb.destroy()

restored = flax.create_sandbox(snapshot_id=snap.id)
print(restored.read_text("/workspace/app.py"))
flax.delete_snapshot(snap.id)
```

Snapshots preserve `/workspace` and sandbox configuration, not running processes or RAM.

Fork a sandbox - create an independent copy of its filesystem and configuration:

```python
base = flax.create_sandbox(template="python", env={"CASE": "base"})
base.upload("/workspace/input.txt", "baseline")

fork = base.fork(metadata={"branch": "eval-a"})
fork.upload("/workspace/input.txt", "changed in fork")

print(base.read_text("/workspace/input.txt"))  # baseline
print(fork.read_text("/workspace/input.txt"))  # changed in fork
```

Forks copy `/workspace` and sandbox configuration, not running processes, RAM, terminal sessions,
preview links, or command history.

Browser-capable sandboxes:

```python
browser = flax.create_sandbox(capabilities=["browser"])
browser.browser.start()
cdp_url = browser.browser.get_cdp_url()
shot = browser.browser.screenshot_bytes()
```

Browser sandboxes persist browser artifacts under
`/workspace/.flax/browser/{profile,screenshots,downloads,traces}`. Browser automation is CDP-first:
connect Playwright, Puppeteer, browser-use, Stagehand, or your own CDP client to the short-lived
authenticated URL from `get_cdp_url()`.

Async client:

```python
import asyncio
from flaxcloud import AsyncFlaxClient

async def main():
    async with AsyncFlaxClient() as flax:
        async with await flax.create_sandbox(template="python") as sb:
            print((await sb.run("echo hi")).stdout)

asyncio.run(main())
```

Errors are typed (`FlaxAuthError`, `FlaxNotFoundError`, `FlaxQuotaError`, …), all subclasses of
`FlaxError`. The client retries transient failures, sends a versioned `User-Agent`, and ships
type hints (`py.typed`).

## CLI

```bash
flax login
flax sandbox create --browser
flax browser start sbx_browser
flax browser cdp-url sbx_browser
flax browser screenshot sbx_browser -o shot.png
flax sandbox create --template python --startup "python3 -m http.server 8000 --bind 0.0.0.0"
flax sandbox ls
flax run sbx_abc123 "python3 -c 'print(6*7)'"
flax run sbx_abc123 "make build" --stream         # stream output live
flax session create sbx_abc123                     # cwd/env persist across exec
flax session exec ses_xyz "cd src && export E=1"
flax cp ./app.py sbx_abc123:/workspace/app.py
flax ls sbx_abc123 /workspace
flax preview sbx_abc123 8000
flax sandbox rm sbx_abc123
```

`flax --help` lists every command.
