> ## Documentation Index
> Fetch the complete documentation index at: https://docs.astrakairo.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Declaring and Locking Dependencies in Kairo Projects

> Declare, restore, and lock dependencies in Kairo using the kairo.toml manifest and forge.lock for reproducible, deterministic builds on every machine.

Kairo packages can depend on other packages to reuse shared functionality. You declare those dependencies in your `kairo.toml` manifest, restore them with Forge, and lock them to exact resolved versions in a `forge.lock` file that you commit to source control. This model keeps builds reproducible across machines and over time — every developer and every CI run sees exactly the same dependency graph.

## Declaring dependencies

Add a `[dependencies]` section to your `kairo.toml` and list each dependency as a `Name = "version"` pair. Versions must be **exact** — Kairo does not support version ranges, wildcards, or the `latest` keyword.

```toml theme={null}
manifest_version = 1

[package]
name             = "Astra.Sales"
version          = "1.0.0.0"
language_version = "0.1"
kind             = "application"

[dependencies]
Astra.Data    = "1.0.0.0"
Astra.Http    = "2.1.0.0"
Astra.Logging = "1.3.2.0"
```

<Warning>
  Only `library` packages may be listed as dependencies. If you add an
  `application` package to your `[dependencies]` section, Forge will report an
  error during `forge restore`.
</Warning>

<Note>
  Declaring a dependency in `[dependencies]` makes it available for import in
  your source files. **Transitive dependencies are not implicit source
  imports.** If your code directly uses a module from a package that one of
  your dependencies depends on, you must add that package to your own
  `[dependencies]` section and import it explicitly.
</Note>

## Restoring dependencies with `forge restore`

After adding or changing entries in `[dependencies]`, run `forge restore` to resolve the full dependency graph and write the lockfile:

```bash theme={null}
forge restore
```

Forge resolves every declared dependency and its transitive closure, then writes the result to `forge.lock`. Subsequent commands (`forge check`, `forge build`, `forge test`) all read from `forge.lock` rather than re-resolving the graph, so the lockfile must exist before you build.

<Tip>
  Run `forge restore` whenever you add, remove, or change a dependency in
  `kairo.toml`. If `forge.lock` is out of date, Forge will warn you and may
  refuse to proceed.
</Tip>

## The lockfile: `forge.lock`

`forge.lock` is the canonical record of every package in your resolved build graph — direct dependencies, transitive dependencies, and their exact versions. It is generated by `forge restore` and read by every subsequent Forge command.

**Always commit `forge.lock` to source control.** Committing the lockfile ensures that every developer, every CI job, and every deployment uses an identical dependency graph. Excluding it forces Forge to re-resolve on every fresh clone, which can produce different results if new package versions have been published since you last ran `forge restore`.

```bash theme={null}
# After cloning a repository for the first time:
forge restore   # produces forge.lock from kairo.toml
forge build     # uses forge.lock — reproducible everywhere
```

<Note>
  `forge clean` removes `build/` and `.forge/` but **never** deletes
  `forge.lock`. Your lockfile is always safe.
</Note>

## Dependency rules

Kairo enforces a strict set of rules on the dependency graph to keep builds deterministic and auditable:

### Only libraries can be dependencies

An `application` package is a terminal artifact — it runs, but it is not consumed by other packages. Only packages with `kind = "library"` may appear in a `[dependencies]` section.

### One version per package name

At most one version of any given package name may appear anywhere in a resolved build graph. If two packages in your dependency tree require different versions of the same library, Forge reports a **hard error** and refuses to build:

```
[FRG-0042] Dependency conflict: "Astra.Data" is required at both
           "1.0.0.0" (by Astra.Sales) and "2.0.0.0" (by Astra.Http).
           Resolve the conflict by aligning your direct dependencies.
```

To fix a conflict, update your direct dependency declarations so that all packages in the graph agree on a single version, or contact the maintainers of the conflicting libraries.

### Transitive dependencies require explicit imports

Including a library as a dependency does not make its transitive dependencies available for import in your own source. If you call into a type or function that lives in a package your dependency uses internally, you must add that package to your own `[dependencies]` and import it directly.

### Published versions are immutable

Once a version of a package is published to the registry, it cannot be changed. You can publish a new version, but the content of any existing version is fixed. This guarantee is what makes lockfiles meaningful — `forge.lock` pinning `Astra.Data = "1.0.0.0"` always refers to exactly the same code.

## Understanding version components

When choosing which version of a dependency to declare, use the `Major.Minor.Build.Candidate` breakdown as a guide:

| Component     | Meaning                                                | Action for consumers                                              |
| ------------- | ------------------------------------------------------ | ----------------------------------------------------------------- |
| **Major**     | Breaking change — public API has changed incompatibly. | Review release notes; expect code changes before upgrading.       |
| **Minor**     | Additive change — new functionality, no breakage.      | Safe to upgrade; no source changes expected.                      |
| **Build**     | Correction — bug fixes, no API changes.                | Safe to upgrade; recommended for stability.                       |
| **Candidate** | Pre-release iteration (RC, internal build).            | `0` in a final release. Pin only when testing pre-release builds. |

```toml theme={null}
[dependencies]
# Pinned to a specific correction release:
Astra.Data = "1.2.4.0"

# Pinned to a release candidate for testing:
Astra.Http = "3.0.0.2"
```

<Tip>
  When upgrading a dependency to a new **Major** version, use `forge check`
  after updating `kairo.toml` and running `forge restore` to surface any
  breaking-change diagnostics before attempting a full build.
</Tip>

## Next steps

<CardGroup cols={2}>
  <Card title="Forge" icon="hammer" href="/toolchain/forge">
    Learn all Forge commands, including `forge restore`, `forge build`, and
    `forge publish`.
  </Card>

  <Card title="Manifest" icon="file-lines" href="/packages/manifest">
    Review the full `kairo.toml` field reference, including version format
    details.
  </Card>
</CardGroup>
