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

# Adding and Managing Dependencies in Your Sifr Package

> Manage Sifr package dependencies with Cargo-backed resolution, lock modes, sifr fetch, sifr tree, and trust policy for backend Rust crates.

Sifr delegates all dependency resolution, lockfile management, and registry communication to Cargo. When you add a dependency to your `Cargo.toml`, Sifr reads the resolved package graph via `cargo metadata` and constructs its own Sifr package graph on top of it. This means the full power of Cargo's ecosystem — version ranges, Git sources, path dependencies, private registries — is available to every Sifr project without Sifr having to reimplement a resolver.

## Declaring dependencies

Add dependencies to `Cargo.toml` exactly as you would in any Rust project. Runtime dependencies go in `[dependencies]`; dependencies used only for tests or development tooling go in `[dev-dependencies]`.

```toml theme={null}
[dependencies]
sifr-http = "0.2"
serde_json = "1"

[dev-dependencies]
sifr-testkit = "0.1"
```

<Note>
  Normal `sifr run`, `sifr check`, `sifr package`, and `sifr publish` commands only expose runtime `[dependencies]` as import roots. Dev dependencies are available only in test contexts. Use `sifr tree --edges dev` if you want to inspect the dev dependency graph explicitly.
</Note>

## Fetching dependencies with `sifr fetch`

After adding or changing a dependency, run `sifr fetch` to resolve and download it:

```bash theme={null}
sifr fetch
```

In CI or any environment where you need a reproducible build, use `--locked` to prevent the lockfile from being updated:

```bash theme={null}
sifr fetch --locked
```

`sifr fetch` delegates to Cargo under the hood and forwards your lock and network flags automatically through the package session.

## Inspecting the dependency tree with `sifr tree`

Visualize your full dependency graph with `sifr tree`:

```bash theme={null}
sifr tree --locked
```

To include dev dependencies in the output:

```bash theme={null}
sifr tree --locked --edges dev
```

Workspace-level tree inspection works the same way — run from the workspace root and pass `--workspace` if needed.

## Lock modes

Sifr passes lock and network semantics directly to Cargo. Use these flags consistently across all package commands for reproducible results.

| Flag        | Effect                                                                                          |
| ----------- | ----------------------------------------------------------------------------------------------- |
| `--locked`  | Cargo rejects any lockfile updates. Fails if the lockfile is out of date.                       |
| `--offline` | Cargo does not access the network. All required package sources must already be cached locally. |
| `--frozen`  | Combines `--locked` and `--offline`. No lockfile updates and no network access.                 |

<Tip>
  Use `--locked` in CI pipelines and `--frozen` in air-gapped or vendor-only environments. Use neither flag during local development when you intentionally want to update dependencies.
</Tip>

These flags apply uniformly across all Sifr commands that touch the package graph:

```bash theme={null}
sifr check --locked --offline
sifr run --locked
sifr tree --locked
```

## Pure Sifr packages

A pure Sifr package contains no non-trivial Rust code — all behavior is expressed in `.sifr` files. Because Cargo requires at least one build target, Sifr generates a minimal marker file at `src/lib.rs`:

```rust theme={null}
// Pure Sifr package marker. Sifr source lives in sifr.toml source roots.
```

Sifr validates this marker and rejects any package that contains non-trivial Rust in `src/lib.rs` but does not declare Rust-backed behavior. Do not add Rust logic to `lib.rs` in a pure Sifr package.

## Trust policy for Rust interop

Some Sifr packages expose Rust crates or local bridge modules through `@rust(...)` declarations. Sifr enforces trust policy for build scripts, proc macros, native links, unsafe local bridge files, no-panic assertions, and panic-abort opt-ins. This policy is configured in `sifr.toml` and validated by `sifr bridge check`, `sifr check`, `sifr package`, and `sifr publish`.

Packages that exceed their declared trust boundary are rejected with `SIFR-RUST-TRUST-*` diagnostics before the final Rust-backed package build is accepted.

See [Rust Interop](/rust-interop) for direct bindings, local bridges, shared bridge crates, opaque handles, async, zero-copy, callbacks, and trust examples.

<Warning>
  Sifr wraps Cargo process failures in diagnostic code [`SIFR-PACKAGE-0101`](/errors/SIFR-PACKAGE-0101). If a dependency fetch, tree command, or other Cargo-delegated operation fails, run `sifr --explain SIFR-PACKAGE-0101` for structured diagnostic help on [`SIFR-PACKAGE-0101`](/errors/SIFR-PACKAGE-0101). The explainer does not perform any package operations — it is safe to run at any time.
</Warning>

## Python package requirements

Sifr does not resolve Python dependencies. Python packages are installed by the root application's uv environment, and Sifr verifies the final interpreter/probe before compile or run. Dependency packages may declare:

```toml theme={null}
[python]
requires-imports = ["pydantic", "httpx"]
```

For normal uv layout, Sifr discovers the root project's `pyproject.toml`,
`uv.lock`, `.venv`, and interpreter. The root application must authorize every
required import root, and separately authorize native-extension roots it is
willing to execute in process. Dependencies cannot select or authorize the
environment. See [Embedded Python Interop](/python-interop).

## Cross-package imports and public APIs

Only names that a dependency exposes through its public namespace are importable from outside that package. A package's public API is defined by `src/__init__.sifr` and any child namespaces that have their own `__init__.sifr`. Implementation files such as `src/client.sifr` are private to the package unless explicitly re-exported.

```python theme={null}
# src/__init__.sifr in the dependency
from .client import HttpClient
from .errors import HttpError as Error
```

In your consuming package, you import through that public namespace:

```python theme={null}
from sifr_http import HttpClient, Error
```

Local package code may import its own implementation files directly. Attempting to import a dependency's private implementation file is a compile-time error.

## Keeping Cargo.toml in sync with `sifr repair`

After manual edits to `Cargo.toml` or after a merge conflict, the Sifr-managed entries in `Cargo.toml` may drift from the expected state. Check for drift without making any changes:

```bash theme={null}
sifr repair --check
```

To regenerate Sifr-managed `Cargo.toml` entries and restore a missing pure marker:

```bash theme={null}
sifr repair
```
