# ocx_sdk

*module*

Python SDK for [OCX](https://github.com/ocx-sh/ocx).

`ocx-sdk` drives the ocx binary rather than reimplementing it: ocx owns
resolution, verification, and the identifier grammar, and this package gives
you typed, CWD-independent handles over the commands it exposes.

```python
from ocx_sdk import Ocx, bootstrap

ocx = Ocx(exe=bootstrap.ensure())
project = ocx.project("/srv/build")
project.pull()
project.exec(["task", "verify"])
```

**This module is the API.** Everything listed in `__all__` is the stable
surface; every other module is underscored and package-private, and the one
public submodule is `ocx_sdk.bootstrap`. Reaching into an underscored path
means the next release may move it without notice — pre-1.0, breaking
changes ship without shims.

Start at `Ocx` for the runtime API and `bootstrap.ensure` for provisioning.

[View source](https://github.com/ocx-sh/ocx-sdk-python/blob/main/src/ocx_sdk/__init__.py#L1-L1)

## ocx_sdk.HostEnv

*class* · *dataclass*

```python
class HostEnv
```

Re-exported from: `ocx_sdk._types`

A snapshot of the environment a spawned ocx inherits.

The mapping is copied and made read-only at construction, so neither a
later mutation of the source dict nor a write through `.source` can
rewrite a snapshot that was already taken. (A read-only snapshot is not
picklable — an implementation detail, not a contract.)

`repr` lists key names only. An ambient snapshot holds `OCX_AUTH_*`
values, and a repr is exactly what a traceback or a pytest diff prints.

> **Example**
>
> >>> HostEnv({"PATH": "/usr/bin", "TOKEN": "s"}).without("TOKEN").source["PATH"]
> '/usr/bin'

[View source](https://github.com/ocx-sh/ocx-sdk-python/blob/main/src/ocx_sdk/_types.py#L117-L181)

### ocx_sdk.HostEnv.source

*attribute* · *instance attribute*

```python
source: Mapping[str, str]
```

[View source](https://github.com/ocx-sh/ocx-sdk-python/blob/main/src/ocx_sdk/_types.py#L134-L134)

### ocx_sdk.HostEnv.ambient

*method* · *classmethod*

```python
def ambient() -> HostEnv
```

Return a snapshot of the current `os.environ`.

[View source](https://github.com/ocx-sh/ocx-sdk-python/blob/main/src/ocx_sdk/_types.py#L145-L148)

### ocx_sdk.HostEnv.clean

*method* · *classmethod*

```python
def clean() -> HostEnv
```

Return an empty environment.

Hermetic, and a documented footgun: spawned tools lose `PATH` and fail
in ways that read like anything but a missing variable. `minimal()` is
the recovery.

[View source](https://github.com/ocx-sh/ocx-sdk-python/blob/main/src/ocx_sdk/_types.py#L150-L158)

### ocx_sdk.HostEnv.minimal

*method* · *classmethod*

```python
def minimal(windows: bool | None = None) -> HostEnv
```

Return only the platform-essential variables from the ambient env.

`PATH`, `HOME`, and `TMPDIR` everywhere; `SYSTEMROOT` and `TEMP` on
Windows. Variables that are not set are simply absent.

**Parameters**

- `windows` (`bool | None`) (default: `None`) — Force the platform branch. Defaults to detecting the host; tests pass it explicitly so both branches run anywhere.

[View source](https://github.com/ocx-sh/ocx-sdk-python/blob/main/src/ocx_sdk/_types.py#L160-L173)

### ocx_sdk.HostEnv.only

*method*

```python
def only(*keys: str) -> HostEnv
```

Return a snapshot narrowed to `keys` that are actually set.

[View source](https://github.com/ocx-sh/ocx-sdk-python/blob/main/src/ocx_sdk/_types.py#L175-L177)

### ocx_sdk.HostEnv.without

*method*

```python
def without(*keys: str) -> HostEnv
```

Return a snapshot with `keys` removed.

[View source](https://github.com/ocx-sh/ocx-sdk-python/blob/main/src/ocx_sdk/_types.py#L179-L181)
