<!-- Source: https://docs.biosimulant.com/how-to/library/compose-hub-labs-locally -->

# Compose Hub Labs Locally

Use a version-pinned public Hub Lab with your own local `BioModule` instances
in one `BioWorld`. The dependency is resolved explicitly and stored only with
the parent Lab.

**Info:**

  This API requires `biosimulant` 0.0.20 or later. Hub package names and SHA-256
  values below are placeholders: use a real, accessible Hub Lab release.

## Pin the Hub Lab

Declare the child in `lab.yaml` with an exact version:

```yaml
children:
  - alias: medium
    package: your-namespace/nutrient-medium
    version: "1.1.0"
```

Add the matching archive checksum in the sibling `biosimulant.lock`:

```yaml
lock_version: 1
dependencies:
  - package: your-namespace/nutrient-medium
    version: "1.1.0"
    artifact_sha256: "<64-character archive SHA-256 from Hub>"
```

Every package-backed child needs one matching lock entry. This checks the bytes
of the downloaded `.bsilab`, preventing a changed artifact from being accepted
under the same version.

## Run it beside local code

```python
from biosimulant import BioWorld
from biosimulant.hub import HubComposition

world = BioWorld(communication_step=0.1)
world.add_biomodule("controller", DoseController())  # Your local BioModule.

composition = HubComposition(world, lab_root="./lab")
composition.add("medium", "your-namespace/nutrient-medium@1.1.0")
composition.apply()
composition.setup()
world.run(duration=24.0)
```

`apply()` verifies and resolves the Hub Lab, then flattens it into the same
world. `setup()` initializes both the resolved Lab and modules you added with
`world.add_biomodule(...)`. Add `composition.connect(...)` only when you know
the child Lab's exposed `io` ports and their signal types.

## Dependency state

For a source Lab, payloads resolve into that Lab only:

```text
lab/.biosimulant/dependencies/
```

The first resolution needs Hub access. Later runs reuse the verified local copy.
Deleting the directory causes a clean re-resolution without changing any other
Lab; ordinary packages exclude this operational state.

For a standalone archive, state is created beside the archive under
`.biosimulant/<archive-name>.dependencies/`. Use a writable override when the
archive directory is read-only:

```bash
biosimulant labs run dist/my-lab.bsilab --dependency-root /tmp/my-lab-state
```

## Vendor an archival release

Normal releases retain the compact package references and lockfile. For a
fully self-contained, offline archive, vendor every locked child:

```bash
biosimulant labs package ./lab --out dist --vendor-dependencies
```

Use this for archival, regulated, or air-gapped distribution; use normal
package references while actively composing and developing a Lab.
