# ToolEnv


Typed tool-environment vocabulary. The underlying `ToolEnvSpec`
lives in `mb.descriptions` and carries only a `tools : [ToolSpec]`
list — no bash-string fragments leak into the spec.

- **Smart constructors**:
  - `toolEnv.define { tools }` proxies to `mb.operations.toolEnv`
    (eager structural validation).
  - `toolEnv.create { name = package; ... }` builds the spec from
    a `{ name = package | null; }` attrset (legacy ergonomic shape;
    `null` entries are dropped).
  - `toolEnv.empty` is the zero element.
  - `toolEnv.merge a b` combines two environments; tool name
    collisions resolve B-wins.

- **Eliminators** (pure functions of the typed spec):
  - `toolInputs : ToolEnvSpec → [Derivation]` — deduplicated
    package list for `nativeBuildInputs`.
  - `toolBinPath : ToolEnvSpec → String` — `lib.makeBinPath` view.
  - `toExportSnippet : ToolEnvSpec → String` — heredoc-style
    `export PATH=...` snippet (empty for empty envs).
  - `toInlineSnippet : ToolEnvSpec → String` — indented variant.
  - `toWrapPrefix : ToolEnvSpec → String` — `wrapProgram --prefix`
    fragment.
  - `toolPackages : ToolEnvSpec → { name = Derivation; }` —
    legacy-shaped attrset view, useful for `passthru` round-trip.
  - `isEmpty : ToolEnvSpec → Bool`.

The spec is the single source of truth; every derived view comes
from an eliminator. Shell snippets live in eliminator outputs, not
in spec fields.

