# Cache policies (/pipeline-sdk/reference/cache)



{/* Generated by docs-site/scripts/generate-dsl-docs.ts — do not edit. */}

## `CacheCompose` [#cachecompose]

Combine multiple policies. Cache hits ONLY when every sub-policy hits.

Useful for "rebuild daily OR when these files change":

CacheCompose(policies=(
CacheTTL(duration=timedelta(days=1)),
CacheOnChange(paths=("api/cabal.project",)),
))

### Fields [#fields]

| Field      | Type                      | Default    |
| ---------- | ------------------------- | ---------- |
| `policies` | `tuple[CachePolicy, ...]` | *required* |

## `CacheForever` [#cacheforever]

Cache forever, keyed only on (command, parent, env\_keys).

Use for pure computations whose only inputs are visible to the planner.
DO NOT use for installs that fetch the public internet — package repos
drift; manual cache busts will be needed.

### Fields [#fields-1]

| Field      | Type              | Default |
| ---------- | ----------------- | ------- |
| `env_keys` | `tuple[str, ...]` | `()`    |

## `CacheNone` [#cachenone]

Always run the step; never cache its snapshot.

Equivalent to today's behavior. Default for command steps.

## `CacheOnChange` [#cacheonchange]

Rebuild whenever any file under `paths` changes.

Paths are relative to the source-archive root. File hashes are
computed at render time by `harmont.keygen` (paths are read from
the source archive's checkout root).

No `env_keys` field — file content already covers the invalidation
surface.

### Fields [#fields-2]

| Field   | Type              | Default    |
| ------- | ----------------- | ---------- |
| `paths` | `tuple[str, ...]` | *required* |

## `CachePolicy` [#cachepolicy]

Base — never instantiate directly. Use the helpers below.

## `CacheTTL` [#cachettl]

Cache for `duration`; refresh once per window (UTC-midnight floored).

Two builds within the same UTC day share a key; a build at 00:30 UTC
the next day rebuilds.

### Fields [#fields-3]

| Field      | Type              | Default    |
| ---------- | ----------------- | ---------- |
| `duration` | `timedelta`       | *required* |
| `env_keys` | `tuple[str, ...]` | `()`       |

## `compose` [#compose]

Combine multiple cache policies: hit only when every sub-policy hits.

Use to express compound invalidation conditions such as "rebuild daily
OR when these files change".

```python
compose(*policies) -> CacheCompose
```

| Parameter  | Type          | Default | Description |
| ---------- | ------------- | ------- | ----------- |
| `policies` | `CachePolicy` | `()`    | —           |

**Returns** `CacheCompose` — A `CacheCompose` policy for use in `.sh(cache=...)`.

**Examples**

```python
>>> from datetime import timedelta
>>> import harmont as hm
>>> policy = hm.compose(
...     hm.ttl(timedelta(days=1)),
...     hm.on_change("api/cabal.project"),
... )
```

## `forever` [#forever]

Create a permanent cache policy.

The step's snapshot is reused indefinitely, keyed on (command, parent,
env\_keys). Suitable for deterministic installs where the command string
itself encodes the version (e.g. downloading a pinned binary). Do not
use for steps that fetch mutable remote resources.

```python
forever(env_keys=()) -> CacheForever
```

| Parameter                                                     | Type              | Default | Description                                             |
| ------------------------------------------------------------- | ----------------- | ------- | ------------------------------------------------------- |
| `env_keys`                                                    | `tuple[str, ...]` | `()`    | Environment variable names whose values are folded into |
| the cache key. Use this when the command's behavior varies by |                   |         |                                                         |
| environment (e.g. `GOARCH`).                                  |                   |         |                                                         |

**Returns** `CacheForever` — A `CacheForever` policy for use in `.sh(cache=...)`.

**Examples**

```python
>>> import harmont as hm
>>> step = hm.sh("curl .../go1.23.tar.gz | tar ...", cache=hm.forever())
```

## `on_change` [#on_change]

Create a content-addressed cache policy keyed on file hashes.

The step's snapshot is reused until any file under `paths` changes.
Paths are relative to the source-archive root and resolved at render
time by the key generator.

```python
on_change(*paths) -> CacheOnChange
```

| Parameter | Type  | Default | Description |
| --------- | ----- | ------- | ----------- |
| `paths`   | `str` | `()`    | —           |

**Returns** `CacheOnChange` — A `CacheOnChange` policy for use in `.sh(cache=...)`.

**Examples**

```python
>>> import harmont as hm
>>> step = hm.sh("pip install -r requirements.txt",
...               cache=hm.on_change("requirements.txt"))
```

## `ttl` [#ttl]

Create a time-to-live cache policy.

The step's snapshot is reused until `duration` has elapsed since the
last successful run, floored to UTC midnight. Two builds within the same
UTC day share a cache key; a build the following day rebuilds.

```python
ttl(duration) -> CacheTTL
```

| Parameter  | Type        | Default    | Description                               |
| ---------- | ----------- | ---------- | ----------------------------------------- |
| `duration` | `timedelta` | *required* | How long the cached result remains valid. |

**Returns** `CacheTTL` — A `CacheTTL` policy for use in `.sh(cache=...)`.

**Examples**

```python
>>> from datetime import timedelta
>>> import harmont as hm
>>> step = hm.sh("apt-get update", cache=hm.ttl(timedelta(days=1)))
```
