Metadata-Version: 2.4
Name: opencode-sdx
Version: 0.1.0
Summary: Hexagonal-architected runtime that runs opencode (serve/agent) inside lightweight OS sandboxes on any machine.
License: MIT
Keywords: opencode,sandbox,runtime,agent,hexagonal,ports-adapters
Classifier: Programming Language :: Python :: 3
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Topic :: Software Development :: Code Generators
Requires-Python: >=3.9
Description-Content-Type: text/markdown

# opencode-sdx

Runs the **opencode** agent (`serve` / headless / TUI) inside a **lightweight OS
sandbox** on any machine. Hexagonal architecture (ports & adapters): the
application layer knows nothing about `sandbox-exec` or `bwrap` — those live in
adapters behind `SandboxRuntimePort`.

```bash
pip install opencode-sdx

opencode-sdx check                  # which sandbox backend is available?
opencode-sdx serve --port 4097      # sandboxed `opencode serve` + health probe
opencode-sdx run -p "fix the tests" # sandboxed headless run
```

## Sandbox backends (adapters, auto-selected)

| Backend | OS | Isolation | How |
| --- | --- | --- | --- |
| `seatbelt` | macOS | strong | `sandbox-exec` with generated seatbelt profile (deny-default, write-whitelist, outbound net + loopback) |
| `bubblewrap` | Linux | strong | `bwrap` read-only root + writable whitelist (no root needed) |
| `plain` | any | none (fallback) | direct spawn; warns you have no isolation |

`opencode-sdx check` lists availability so you know what you are getting.

## Hexagonal layout

```
src/opencode_sdx/
  domain/models.py                 # SandboxPolicy, SessionSpec, SessionRecord (pure rules)
  application/ports/inbound/       # StartSessionPort, StopSessionPort...
  application/ports/outbound/      # SandboxRuntimePort, RuntimeHealthPort (contracts)
  application/use_cases/session.py # StartSessionUseCase, HealthCheckUseCase (pure orchestration)
  adapters/outbound/seatbelt/      # macOS sandbox-exec implementation
  adapters/outbound/bubblewrap/    # Linux bwrap implementation
  adapters/outbound/plain/         # no-isolation fallback
  adapters/inbound/cli.py          # `opencode-sdx` CLI (protocol -> use case)
  composition/app.py               # wiring root: pick runtime, bind use cases
```

Dependency direction is inward only: `adapters -> application -> domain`.

## Default sandbox policy

- Write whitelist: runtime data dir, the session work dir, `/tmp`
- Read: everything (read-only root)
- Network: outbound (LLM APIs) + loopback inbound (`localhost:*` for the server port)
- Extend per session: `SandboxPolicy().with_writable("/path")`

## Development

```bash
python -m venv .venv && .venv/bin/pip install -e . pytest
.venv/bin/pytest
```

## License

MIT
