Decision: Single-repo single-distribution + [cli] extra (no split, no binary for now)
Status: superseded Superseded-by: 2026-10-12-repository-split-and-layout Task: #95, #105
Problem
The SDK and CLI live in the same repository, so the packaging structure must be decided: (1) whether to split into separate distributions (SDK + a CLI meta-package); (2) how to isolate the CLI dependencies; (3) whether to provide a pre-built binary (shiv/pex/PyInstaller).
Decision
Keep the single-repo single-distribution + [cli] extra structure.
Naming scheme
- Distribution name (pip install X):
agent-sandbox.abxis already taken by a third party on PyPI (evryoneowo's "secret manager", v1.1.0, MIT, first uploaded 2026-01-08) and is unavailable. - Import name (import Y):
agent_sandbox. The hyphen/underscore correspondence with the distribution name follows standard Python packaging convention. - CLI command name:
abx.[project.scripts] abx = "agent_sandbox.cli.main:cli". The CLI command name is independent of the distribution name and can be chosen freely.
Installation modes
- SDK only:
pip install agent-sandbox— core dependencies httpx/websockets/pydantic/python-dotenv. - SDK + CLI:
pip install "agent-sandbox[cli]"— additionally installs click/rich/pyyaml. abxerrors when click is missing after a bare install: this is a known usability pitfall and must be documented up front.
No library split
- Clean, one-way dependency: CLI → SDK. The reverse is zero (a full Grep for
agent_sandbox.cli/from .cliin the SDK layer = 0 matches). No circular dependency. - A split is technically feasible but of limited benefit:
- The
abxdistribution name is unavailable (a hard constraint), so a standalone CLI package could only be calledagent-sandbox-cli, which weakens the original intent. - It would require version coordination (version pinning, duplicate CI, synchronized release cadence).
- The current extra mechanism already satisfies the two needs "SDK only" and "SDK + CLI".
No binary for now
- Freezing is not a structural fix; it is a distribution-UX option. Current blockers:
cli/main.py'sLazyGroupusesimportlib.import_modulefor dynamic imports (PyInstaller needs--hidden-import).@click.version_option(package_name="agent-sandbox")relies onimportlib.metadata(a frozen bundle usually has no*.dist-info).pydantic-core(Rust),orjson(Rust), andmsgpack(C) make the artifact platform-specific.
API Design
# pyproject.toml (current)
[project]
name = "agent-sandbox"
# ...
[project.optional-dependencies]
cli = ["click>=8.0", "rich>=13.0", "pyyaml>=6.0"]
[project.scripts]
abx = "agent_sandbox.cli.main:cli"
[tool.hatch.build.targets.wheel]
packages = ["src/agent_sandbox"]
# installation modes
pip install agent-sandbox # SDK only
pip install "agent-sandbox[cli]" # SDK + CLI
pip install "agent-sandbox[all]" # all extras
Alternatives considered
- Split into two distributions (SDK + a CLI meta-package) — technically
feasible (one-way acyclic dependency), but the
abxdistribution name is taken, version-coordination cost is high, and the benefit is limited. Rejected (not recommended for now). - Split into two repositories — adds cross-repo collaboration/issue/CI complexity on top of the dual-distribution cost; not worth it at the current team size. Rejected.
- Freeze into a single-file binary — a pure UX plus, but requires solving LazyGroup dynamic imports, version_option metadata, and cross-platform builds of native extensions. Optional enhancement (not required).
- Fold the CLI dependencies into the core dependencies — a bare
pip install agent-sandboxwould then install click/rich/pyyaml, which is unnecessary bloat for SDK-only users. Rejected.
Dependencies
pyproject.toml(distribution configuration)src/agent_sandbox/_version.py(version source)cli/main.py(entry point + LazyGroup)
Test Strategy
- After
pip install agent-sandbox,import agent_sandboxsucceeds and theabxcommand raises a clear error due to missing click. - After
pip install "agent-sandbox[cli]",abx --helpworks normally. - Grep for
agent_sandbox.cli/from .cliunder SDK layers such asapi//models//transport//protocol/= 0 matches (continuous verification of no circular dependency).
Acceptance criteria
- A single distribution name
agent-sandbox, a single import nameagent_sandbox, and the CLI commandabx. - The
[cli]extra isolates the CLI dependencies; the SDK core has no click/rich/pyyaml. - The SDK → CLI dependency direction is zero.