Skip to main content

briq-cloud

Python client for briq. Create a sandbox, run commands in it, move files in and out.

from briq_cloud import Briq

with Briq() as briq:  # reads BRIQ_API_KEY
    with briq.create_sandbox(sleep="30m") as sandbox:  # destroyed when the block ends
        sandbox.write_file("/work/hello.py", b"print('hello')")
        result = sandbox.exec("python3 hello.py", cwd="/work")
        print(result.stdout, result.exit_code)
        print(sandbox.read_file("/work/hello.py"))
        print(sandbox.preview_url(8000))

The async client has the same methods, awaited:

from briq_cloud import AsyncBriq

async with AsyncBriq() as briq:
    sandbox = await briq.create_sandbox()
    result = await sandbox.exec(["ls", "-la"])
    await sandbox.destroy()

Install: pip install briq-cloud. Python 3.10 or later. The only dependency is httpx.

Configure

Argument Default Environment variable
api_key none, required BRIQ_API_KEY
base_url https://api.briq.cloud BRIQ_API_URL

timeout is the seconds one request may take. The client reads the usual proxy and certificate variables (HTTPS_PROXY, SSL_CERT_FILE). To set up the connection yourself, pass http_client= an httpx.Client (httpx.AsyncClient for AsyncBriq): it is used as it is, close leaves it open, and a redirect is never followed, whatever it says. transport takes an httpx transport, for tests.

Sandbox

Method Does
briq.create_sandbox(...) Makes a sandbox, waits until it runs.
briq.sandbox(id) Reconnects to a sandbox by id.
sandbox.exec(command, ...) Runs a command, returns ExecResult.
sandbox.write_file(path, data) Writes bytes, creates missing directories.
sandbox.read_file(path) Returns the bytes of a file.
sandbox.list_files(path) Returns the entries of a directory. Needs python3 inside.
sandbox.remove(path, recursive=) Removes a file or a directory.
sandbox.preview_url(port) Returns a URL for a port. public=True for anyone.
sandbox.stop() / sandbox.start() Stops it, keeps the disk, bills nothing. Starts it again.
sandbox.set_sleep("30m") Sets the idle time before it sleeps. "never" stays awake.
sandbox.refresh() Reads its state again.
sandbox.destroy() Removes it and its disk.

A sleeping sandbox wakes on the next call.

Run a command

sandbox.exec(
    "make test",
    cwd="/work",
    env={"CI": "1"},
    timeout=600,
    on_output=lambda chunk: print(chunk.text, end=""),
)
  • A string runs in a shell. A list is the program and its arguments.
  • timeout is in seconds, up to 24 hours. A command that outlives it is stopped: timed_out is true and exit_code is None.
  • Without on_output, a command up to 60 seconds runs in one request.
  • With on_output, or past 60 seconds, the output reaches on_output as it is written. Both streams are read, in order within each stream.
  • stdout and stderr are text. Read bytes with read_file.

Secrets

briq.create_sandbox(env={"MODE": "test"}, secret_env={"API_TOKEN": token})

env values show in the sandbox's status. secret_env values are write-only. If the API cannot keep them so, the call raises unsupported.

Errors

Every failure is a BriqError with a stable code.

code Means Try again?
auth No key, a wrong key, or a key that may not do this. No
not_found The sandbox does not exist. No
file_not_found The file or directory does not exist. No
quota A limit stopped it: credits, plan, rate limit, size, a file. Later
unavailable briq could not take the call. Nothing was applied. Yes
invalid_argument The call is wrong. No
provider A refusal that fits no other code. Maybe
outcome_unknown The call was sent. Its result is not known. Check first
timeout A deadline of the client ended the call. Maybe
unsupported This API or image cannot do it. No
aborted The command was stopped by someone else. No

quota also covers HTTP 413 and the API's plan_limit refusals: trying again changes nothing until the limit does. A file over 100 MiB is quota, from read_file and write_file.

Also on the error: status, api_code, request_id (quote it when you ask for help), retry_after, details, idempotency_key and sandbox_id. details holds codes, ids and numbers ({"limit": "size", "plan": "hobby"}); the text a provider gave is never kept.

A command and its directory may total 8,192 bytes. A longer one raises invalid_argument before anything is sent: write the script with write_file and run that file.

The client never repeats a call whose effect it cannot see. When a command's end is not known, or a sandbox's creation got no answer, it raises outcome_unknown. To retry a creation safely, pass the same idempotency_key again: briq returns the first sandbox. Without a key of your own the client makes one, and error.idempotency_key is that key.

try:
    sandbox = briq.create_sandbox()
except BriqError as error:
    if error.code == "outcome_unknown" and error.idempotency_key:
        sandbox = briq.create_sandbox(idempotency_key=error.idempotency_key)
    else:
        raise

If creating fails after the sandbox exists (it did not start in time, or the call was cancelled or interrupted), the client destroys it and raises the original error. When it cannot destroy it, the error is outcome_unknown with error.sandbox_id: call briq.sandbox(error.sandbox_id).destroy(). The cause of the failure is error.__cause__.

Cancel a call

A cancelled task (asyncio.wait_for timing out, task.cancel()) or a KeyboardInterrupt ends a call cleanly. A sandbox made by the call is destroyed, even though the cancel is running, and a command started with on_output is stopped. The cancel or the interrupt is raised again as it was; a cleanup that fails never replaces it. A cancel that arrives while the create request is still in flight cannot be undone, because the id is not known yet: pass your own idempotency_key and repeat the call to get the sandbox.

License

MIT

Metadata

Release files for briq-cloud 0.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for briq-cloud 0.1.1
File Size Uploaded Provenance Actions
briq_cloud-0.1.1.tar.gz 21.4 kB Without provenance Details for briq_cloud-0.1.1.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for briq-cloud 0.1.1
File Interpreter ABI Platform Actions
briq_cloud-0.1.1-py3-none-any.whl Python 3 none any Details for briq_cloud-0.1.1-py3-none-any.whl

Total release size: 47.1 kB

Release files / briq_cloud-0.1.1.tar.gz

Download URL briq_cloud-0.1.1.tar.gz
Size 21.4 kB
Tags Source
SHA-256 checksum
How to use checksums
71e8e71ac62faa70c499888701b58f64178f0c278fdc44d0a26bdb9a2bdeae96
BLAKE2b-256 checksum
How to use checksums
86ae8cbde4b5744c0cc5aec3731f50fd65d20c4bcada1bae38c0f1f2b55c6696
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.13.7 {"installer":{"name":"uv","version":"0.13.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"26.04","id":"resolute","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / briq_cloud-0.1.1-py3-none-any.whl

Download URL briq_cloud-0.1.1-py3-none-any.whl
Size 25.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
5c5682c538da5effbe39a00b55e36a0618ade5a0132c15c822c2420dd8a1e670
BLAKE2b-256 checksum
How to use checksums
868373ad87281ae33588bf70cd6aa475dd55fbab05e302d887d5d30888c535b9
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.13.7 {"installer":{"name":"uv","version":"0.13.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"26.04","id":"resolute","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Security for briq-cloud 0.1.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page