# Example: a node variant
URL: https://lsd.tools/docs/ex-variant
Updated: 2026-07-17

> overrides="mim.solid" makes your step a variant of another package's node identity. override_mode="coexist" keeps both addable (the user picks in the variants dropdown); "replace" makes yours win the identity by default. Engine.set_variant switches the active provider per project.

Sometimes you want to offer a **different implementation of an existing node** — a domain-specific
version of a generic one. `overrides="pkg.node"` registers your step as a *variant* of that node
identity; `override_mode` decides whether it replaces the original or coexists with it.

## The code

```python
# tool.py
from lsdtools import Tool, Source, Table

tool = Tool("mim_openpit", label="Open Pit")


@tool.load(overrides="mim.solid", override_mode="coexist", source_kinds=("file",))
def pit_shell(src: Source, bench_height: float = 15.0) -> Table:
    """Build a pit-shell solid from survey points — a variant of the base `mim.solid` node."""
    t = src.read()
    bench = t["z"] / bench_height # a whole-column expression
    return t.with_column("bench", bench)
```

## What each line does

- **Node identity** is always `f"{tool_name}.{fn_name}"`. The base node here is `mim.solid` — the
 `solid` step of a tool named `mim` (the `lsd-mim` package).
- **`overrides="mim.solid"`** — registers `pit_shell` as a **variant** of that identity. It does not
 need to import `lsd-mim`; it just names the identity.
- **`override_mode="coexist"`** — both stay addable. The base `mim.solid` and your `pit_shell` each
 appear in the palette, and the node's **variants dropdown** lets the user pick which one a given
 node uses. `override_mode="replace"` (the default) instead makes your provider win the identity, so
 existing `mim.solid` nodes silently use `pit_shell`.
- **`pit_shell`'s body** — a normal load: read the picked file, then add a `bench` column derived
 from `z`. `t["z"] / bench_height` is a single-kernel [`Column`](/docs/api-table) expression.

## Run it in Python

Because it coexists, `pit_shell` is a fully-functional load on its own:

```python
from lsdtools import Engine, Source, Table

Table({"x": [0.0], "y": [0.0], "z": [30.0]}).write_csv("survey.csv")

Engine().run(pit_shell(Source.file("survey.csv"), bench_height=15.0)).output.print()
# → x y z bench
# 0 0 30 2
```

To make your variant the active provider for a whole project — the programmatic equivalent of the
variants dropdown — call [`Engine.set_variant`](/docs/api-engine):

```python
eng = Engine("pit.lsd")
eng.set_variant("mim.solid", mode="replace", provider="mim_openpit")
# → every live `mim.solid` node now runs pit_shell; returns the number of steps swapped
```

## Where the user picks it

In the desktop **Package Manager**, the *Variants* section lists every identity that has more than
one provider. Choosing one there is persisted in the `.lsd` project (`package_state.variants`) and
swaps live nodes instantly.

## Try changing it

- Switch to `override_mode="replace"` and reopen the project — existing `mim.solid` nodes adopt your
 step with no re-wiring.
- Override a **shape** instead: `@tool.shape(overrides="mim.wireframe", override_mode="coexist")`.
- Add a `bench_height` validation rule via a `dialog=` so the value can't be zero.

## Related

**Learn** — [Node variants](/docs/tools-variants) · [The Package Manager](/docs/pkg-manager) · [Load steps](/docs/tools-load)

**API** — [Engine](/docs/api-engine) · [Tool](/docs/api-tool) · [PackageManager](/docs/api-package-manager)

**Examples** — [A complete package](/docs/ex-full-package) · [File loader](/docs/ex-file-loader)
