Python SDK quickstart
Create a sandbox, run a command, work with files, export an artifact, and expose a preview with the crownest package for Python.
This quickstart walks you through the full sandbox lifecycle with the Python SDK: create a sandbox, run a command, write and read a file, export an artifact, expose a preview, and clean up. By the end you have a complete script you can drop into your own project.
Prerequisites
You need two things before you start.
- Python 3.11 or later. The SDK depends on
httpx. - A CrowNest API key, created in the dashboard at https://crownest.dev. See API keys for scopes and presets.
[!WARNING] The raw API key is shown once, at creation time. Copy it immediately and store it somewhere safe — you can't view it again later.
Set up
Follow these steps to install the SDK and authenticate.
-
Install the package from PyPI.
Terminal pip install crownestWith uv:
uv add crownest. -
Export your API key. The client reads
CROWNEST_API_KEYfrom the environment when you don't passapi_keyexplicitly.Terminal export CROWNEST_API_KEY="cn_live_..." -
Create a client. The sync client supports use as a context manager, which closes the underlying connection for you; outside a
withblock, call.close()when you're done.main.py from crownest import CrowNest client = CrowNest( api_key="cn_live_...", # or env CROWNEST_API_KEY base_url="https://api.crownest.dev", timeout=660, # seconds )All constructor arguments are optional;
CrowNest()works on its own whenCROWNEST_API_KEYis set.
Walk through the lifecycle
Each step below builds on the previous one inside the same with block.
-
Create a sandbox.
createreturns aSandboxHandle— the sandbox resource with.id, dict-style and attribute access,.to_dict(), a.kill()method, and bound sub-clients (.commands,.files,.artifacts,.previews), so you don't repeat the sandbox ID on every call.with CrowNest() as client: sandbox = client.sandboxes.create(template="python")Templates available today are
base,node,python, andpython-node. You can also passttl_msto request a lifetime andmetadatato attach small string labels — see Sandboxes. Idempotency keys are generated for you automatically. -
Run a command.
runwaits for the process to exit and returns the full command record, includingexitCode,stdout, andstderr.result = sandbox.commands.run("python -c 'print(40 + 2)'") print(result["exitCode"], result["stdout"])[!IMPORTANT] A non-zero exit code does not raise. The command completed; your code inside it failed. Always check
result["exitCode"]when the outcome matters.CrowNestApiErroris reserved for API-level failures. -
Write and read a file. All file paths are inside
/workspace, the sandbox's working filesystem area.sandbox.files.write("notes.txt", "hello from crownest") content = sandbox.files.read("notes.txt") print(content)[!NOTE] File APIs are confined to
/workspace. Paths that resolve outside it, including through symlinks, are rejected with thepath_outside_workspaceerror code. -
Export an artifact. The workspace disappears with the sandbox, so copy anything you want to keep to durable storage with an explicit export.
artifact = sandbox.artifacts.create("notes.txt") print(artifact["id"])You can download it later — even after the sandbox is gone — with
client.artifacts.download(artifact["id"]), which returnsbytes. -
Expose a preview. When your sandbox hosts an HTTP service, create a preview to get an authenticated URL like
https://p-a1b2c3.preview.crownest.dev.sandbox.commands.start("python -m http.server 8000") preview = sandbox.previews.create(port=8000) print(preview["url"])startlaunches the server without waiting for it to exit. Previews require authentication in v1; see Previews. -
Kill the sandbox. This stops billing and releases the environment. Sandboxes also expire automatically at their TTL.
sandbox.kill()
Handle errors
API failures raise crownest.CrowNestApiError, which carries the HTTP
status, a stable machine-readable code, and optional details. str(e)
gives a readable summary.
from crownest import CrowNest, CrowNestApiError
with CrowNest() as client:
try:
client.sandboxes.get("sbx_does_not_exist")
except CrowNestApiError as e:
print(e.status, e.code, e.details)
print(str(e))See the error reference for the full list of codes.
Complete script
The end-to-end version of the steps above.
from crownest import CrowNest
with CrowNest() as client:
sandbox = client.sandboxes.create(template="python")
result = sandbox.commands.run("python -c 'print(40 + 2)'")
print(result["exitCode"], result["stdout"])
sandbox.files.write("notes.txt", "hello from crownest")
content = sandbox.files.read("notes.txt")
print(content)
artifact = sandbox.artifacts.create("notes.txt")
print("artifact:", artifact["id"])
sandbox.commands.start("python -m http.server 8000")
preview = sandbox.previews.create(port=8000)
print("preview:", preview["url"])
sandbox.kill()Use the async client
AsyncCrowNest exposes the same surface with await on every call, and
works as an async context manager.
import asyncio
from crownest import AsyncCrowNest
async def main() -> None:
async with AsyncCrowNest() as client:
sandbox = await client.sandboxes.create(template="python")
result = await sandbox.commands.run("python -c 'print(40 + 2)'")
print(result["exitCode"], result["stdout"])
await sandbox.kill()
asyncio.run(main())Next steps
- Learn how lifetimes, templates, and statuses work in Sandboxes.
- Stream logs and collect outputs with Commands.
- Browse every method in the Python SDK reference.
- Prefer the terminal? Try the CLI quickstart.
TypeScript SDK quickstart
Create a sandbox, run a command, work with files, export an artifact, and expose a preview with the @crownest/sdk package.
CLI quickstart
Drive CrowNest sandboxes from your terminal with the crownest CLI — create a sandbox, run commands, move files, export artifacts, and stream logs.