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.
timeoutis in seconds, up to 24 hours. A command that outlives it is stopped:timed_outis true andexit_codeisNone.- Without
on_output, a command up to 60 seconds runs in one request. - With
on_output, or past 60 seconds, the output reacheson_outputas it is written. Both streams are read, in order within each stream. stdoutandstderrare text. Read bytes withread_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)
| 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)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| 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.