# 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.ConfigOverrides

*class*

```python
class ConfigOverrides(TypedDict)
```

Bases: `TypedDict`

Re-exported from: `ocx_sdk._config`

The `OcxConfig` fields a `with_config` call may replace, all optional.

What makes `Ocx.with_config(...)` and `Project.with_config(...)` check
their keyword arguments instead of accepting `**overrides: Any`, so a
misspelled field is a type error rather than a `TypeError` at runtime.
Public for the same reason `MaybeRetry` is: a wrapper around this SDK can
forward a caller's overrides with `**overrides: Unpack[ConfigOverrides]`
rather than re-declaring the field list itself.

Mirrors `OcxConfig` field for field — a field added there and not here is
a field `with_config` would refuse.

Optional at the class level rather than per field: this module postpones
annotation evaluation, and a `NotRequired[...]` inside a string annotation
is invisible to `__required_keys__`, so anything introspecting the type at
runtime would be told every field was mandatory. Every field is optional
here anyway, which is exactly what `total=False` says.

> **Example**
>
> ```python
> from typing import Unpack
> 
> from ocx_sdk import ConfigOverrides, Ocx
> 
> 
> def hermetic(ocx: Ocx, **overrides: Unpack[ConfigOverrides]) -> Ocx:
>     return ocx.with_config(no_config=True, **overrides)
> ```

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

### ocx_sdk.ConfigOverrides.docker_config

*attribute* · *instance attribute*

```python
docker_config: Path | None
```

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

### ocx_sdk.ConfigOverrides.forge_git_token

*attribute* · *instance attribute*

```python
forge_git_token: str | None
```

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

### ocx_sdk.ConfigOverrides.forge_git_username

*attribute* · *instance attribute*

```python
forge_git_username: str | None
```

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

### ocx_sdk.ConfigOverrides.forge_token

*attribute* · *instance attribute*

```python
forge_token: str | None
```

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

### ocx_sdk.ConfigOverrides.frozen

*attribute* · *instance attribute*

```python
frozen: bool
```

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

### ocx_sdk.ConfigOverrides.home

*attribute* · *instance attribute*

```python
home: Path | None
```

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

### ocx_sdk.ConfigOverrides.managed_config

*attribute* · *instance attribute*

```python
managed_config: str | None
```

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

### ocx_sdk.ConfigOverrides.mirrors

*attribute* · *instance attribute*

```python
mirrors: Mapping[str, str] | None
```

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

### ocx_sdk.ConfigOverrides.no_config

*attribute* · *instance attribute*

```python
no_config: bool
```

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

### ocx_sdk.ConfigOverrides.no_config_refresh

*attribute* · *instance attribute*

```python
no_config_refresh: bool | None
```

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

### ocx_sdk.ConfigOverrides.timeout

*attribute* · *instance attribute*

```python
timeout: float | None
```

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

### ocx_sdk.ConfigOverrides.toolchain_dir

*attribute* · *instance attribute*

```python
toolchain_dir: Path | None
```

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