useshards
The Python SDK for shard, the sandbox manager. Shard is for
blocking code and AsyncShard is for asyncio. Both have the same verbs.
pip install useshards
To run the code on main instead, install it from the repository:
pip install "useshards @ git+https://github.com/presmihaylov/shard#subdirectory=sdks/python"
Python 3.11 or later. The runtime dependencies are HTTPX, attrs and typing-extensions.
Connect
The SDK talks to shard serve over HTTPS, or over HTTP on localhost or a trusted encrypted network, where it
warns once per client as the CLI does. Mint a key on the host with shard tokens mint, then:
export SHARD_REMOTE=https://shard.example.com
export SHARD_API_KEY=<the token>
An argument beats the environment: Shard(remote=..., api_key=...). ca_file= (or SHARD_CA_FILE) trusts a
private CA, for an https remote only. A remote with no port takes 443 for https and 80 for http.
Quickstart
from useshards import Shard
with Shard() as shard:
sandbox = shard.create("docker.io/library/alpine:3")
try:
result = sandbox.exec(["uname", "-sr"])
print(result.exit_code, result.stdout)
sandbox.files.write("/tmp/hello.txt", "hello\n")
print(sandbox.exec("cat /tmp/hello.txt").stdout)
finally:
sandbox.remove(force=True)
The same on asyncio:
import asyncio
from useshards import AsyncShard
async def main() -> None:
async with AsyncShard() as shard:
sandbox = await shard.create("docker.io/library/alpine:3")
try:
results = await asyncio.gather(*(sandbox.exec(f"echo {n}") for n in range(3)))
print([r.stdout for r in results])
finally:
await sandbox.remove(force=True)
asyncio.run(main())
examples/ has both in full. Set SHARD_REMOTE and SHARD_API_KEY, then run python examples/quickstart.py.
What to know
create()runs no command. It returns a running sandbox, or one in statefailedwithinfo.failed_reason. Run commands in it withexec().- A sandbox outlives its app.
shard.run(image, command)returns anApp. When the app exits, its sandbox stays running, so you can still exec into it. Onlystop()orremove()ends it. - A string command runs under
/bin/sh -c. A list runs as it is. exec(..., background=True)returns aCommand.wait(),kill(),write_stdin(),close_stdin()andresize()act on it.commands.get(id)finds it again from another client. In the foregroundstdin=is the whole input; in the backgroundstdin=Truekeeps the input open forwrite_stdin().- A cancel never kills the remote command. An asyncio cancel, a timeout or a dropped connection
ends only the wait. The command runs on until it exits or you call
kill(). - Output may hold only its end. A result keeps the newest 8 MiB of stdout and stderr together
(
output_limit_bytes=, 0 keeps none).on_stdout=andon_stderr=see every chunk as it arrives.result.lost_bytesis different: it counts output the daemon dropped before any client read it.logs()is bounded on the daemon too, so a long app may hold only its end. - Files stream.
files.download()writes to a temporary file and renames it at the end, so a large file never sits in memory. An upload sends its length first:files.upload()takes a path, andfiles.write()takes bytes, a seekable file, or a stream withsize=. - A verb the provider lacks raises
UnsupportedError.shard.capabilities()says which of the eight lifecycle verbs the daemon's provider supports (create, start, stop, remove, pause, resume, fork and snapshot), before you call them.
Lists
shard.list() returns SandboxList(sandboxes, warnings). shard.secrets.list() returns
SecretList(secrets, warnings). The async client returns the same result types. The warnings name
entries the daemon could not read. Both lists collect warnings from every page, keeping each exact
text once in first-seen order. Check them before you treat the result as complete. Other lists return
plain lists.
Errors
ShardError is the base of every exception below, which covers the daemon, the transport and the settings. A
bad local argument raises the native exception instead: an upload of a missing file raises
FileNotFoundError, and create() with neither an image nor a snapshot raises ValueError.
| Exception | When |
|---|---|
ConfigurationError |
A setting is missing or refused. The message never shows the API key, and names a CA file path or the remote when that is what to fix. |
ShardConnectionError |
The daemon is unreachable, or a stream ended before the command did. |
CommandNotStartedError |
The command never ran, as when its binary does not exist. |
APIError |
The daemon refused the request: AuthenticationError (401), PermissionDeniedError (403), NotFoundError (404), InvalidRequestError (400, 413), ConflictError (409), UnsupportedError, ServerError (5xx). An exec past the running-exec bound is a plain APIError with status 429 and code exec_limit. |
ProtocolError is an answer the SDK cannot read, UnknownLengthError an upload of unknown size or
one whose source changed size while it was sent, and UnsafeArchiveError a download_dir tar entry
the SDK refuses to land, as one outside the destination, named by entry and reason. A non-zero
exit code is not an exception. Read result.exit_code.
An APIError can carry holders, the sandbox ids that prevent an operation such as secret removal.
The attribute is None when the error has no holders field.
License
Apache-2.0.
Metadata
Release files for useshards 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 | |
|---|---|---|---|---|
| useshards-0.1.1.tar.gz | 76.1 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| useshards-0.1.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 238.0 kB
Release files / useshards-0.1.1.tar.gz
| Download URL | useshards-0.1.1.tar.gz |
|---|---|
| Size | 76.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
117ba0c60e024a009e12ed131900b356b6911f934357c9f47e997ac4dcdadea3
|
|
BLAKE2b-256 checksum How to use checksums |
1b12c2ace71b01d9e44ec8fdc6521c19eaba65ab5647069837010fc6cd9fca2a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 6, 2026.
Transparency logRelease files / useshards-0.1.1-py3-none-any.whl
| Download URL | useshards-0.1.1-py3-none-any.whl |
|---|---|
| Size | 161.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
70b42d17478b7081b1df166866f3bb9cdc343b2ab850da3ed46af429267c2267
|
|
BLAKE2b-256 checksum How to use checksums |
ebb25a054cc004e14c40d4c7610ef9a28e09448237cdc78f17c850218e46287d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 6, 2026.
Transparency logSecurity for useshards 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.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for useshards-0.1.1.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 6, 2026.
Transparency logA 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.