> ## 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.

# Sifr Package Management: Libraries, Apps, and Init

> Learn how Sifr packages work — from single-file scripts to full library and app projects — and how sifr.toml and Cargo.toml divide responsibilities.

Sifr packages let you organize, share, and reuse code across projects. Every Sifr package is backed by Cargo, the Rust package manager, which handles distribution, dependency resolution, lockfiles, and registries. Sifr then layers its own concerns on top: compiler semantics, source layout, edition, and the public API surface declared in your `.sifr` files. Understanding where each tool's responsibility begins and ends will save you a lot of time as your project grows.

## Package layouts

Sifr supports two production layouts depending on whether you are building a reusable library or a runnable application.

### Library layout

A library package exposes a public API that other packages can import. The minimum required files are:

```text theme={null}
sifr-http/
  Cargo.toml
  Cargo.lock
  sifr.toml
  src/
    __init__.sifr
    client.sifr
    lib.rs
```

`src/__init__.sifr` is the public API entry point. Any name you define or re-export there becomes available to packages that depend on `sifr-http`.

### App layout

An app package produces one or more runnable binaries. The default entry point is `src/main.sifr`, and additional targets are discovered automatically from `src/bin/*.sifr`.

```text theme={null}
sifr-app/
  Cargo.toml
  Cargo.lock
  sifr.toml
  src/
    main.sifr
    bin/
      admin.sifr
    lib.rs
```

## How sifr.toml and Cargo.toml divide responsibilities

Both manifests live at the project root and are always required for a production package. They do not overlap.

| Concern                                                        | Owned by     |
| -------------------------------------------------------------- | ------------ |
| Package name, edition, compiler version, source root           | `sifr.toml`  |
| Sifr scripts, privacy settings, native trust policy            | `sifr.toml`  |
| Distribution metadata, registry, publishing credentials        | `Cargo.toml` |
| Dependency resolution, lockfiles, Git/path sources, workspaces | `Cargo.toml` |
| include/exclude archive rules                                  | `Cargo.toml` |

<Note>
  Cargo package names generated by `sifr init` follow the `sifr-<kebab-case-name>` convention. The `sifr.toml` name uses the plain package name (for example, `demo_json`) while the Cargo package name would be `sifr-demo-json`.
</Note>

## Manifest-less mode

You do not need a package at all for quick experiments or standalone scripts. When no `sifr.toml` exists in the current directory or any of its parents, Sifr runs in manifest-less mode. The file's parent directory becomes the source root and no dependency graph is loaded.

```bash theme={null}
sifr run path/to/file.sifr
sifr check path/to/file.sifr
sifr emit path/to/file.sifr
```

<Tip>
  Manifest-less mode is ideal for learning and one-off scripts. Switch to a full project with `sifr init` as soon as you need dependencies or want to share code.
</Tip>

When you run these commands inside a package directory, the explicit `.sifr` file must reside under the package source root (usually `src/`). Sifr rejects files outside the source root to avoid ambiguous package membership.

## Creating a new package with `sifr init`

`sifr init` scaffolds a complete, canonical package for you — including both `sifr.toml` and the correctly configured `Cargo.toml`.

<Steps>
  <Step title="Create a library package">
    Run `sifr init --lib` with your package name:

    ```bash theme={null}
    sifr init --lib demo_json --name demo_json
    ```

    This generates:

    ```text theme={null}
    demo_json/
      Cargo.toml
      sifr.toml
      src/
        __init__.sifr
        lib.rs
    ```
  </Step>

  <Step title="Create an app package">
    Use `--bin` instead to scaffold an application:

    ```bash theme={null}
    sifr init --bin demo_app --name demo_app
    ```

    The generated layout uses `src/main.sifr` in place of `src/__init__.sifr`.
  </Step>

  <Step title="Fetch dependencies">
    Move into your new package directory and fetch its initial dependency set:

    ```bash theme={null}
    cd demo_json
    sifr fetch
    ```
  </Step>
</Steps>

The generated `Cargo.toml` includes the metadata pointer that Sifr uses to locate your manifest at runtime:

```toml theme={null}
# sifr-managed
[package.metadata.sifr]
manifest = "sifr.toml"
# end sifr-managed
```

Do not remove the `# sifr-managed` markers. Sifr uses them to identify and update its managed entries in `Cargo.toml`.

## How commands use your package context

Every package-aware command resolves your project context once at startup — finding the workspace root, your `sifr.toml`, and the source root — and keeps that context stable for the lifetime of the command. The active lock mode you pass (`--locked`, `--offline`, or `--frozen`) applies automatically to all underlying operations, including dependency fetches and tree inspection. You do not need to pass lock flags separately for each step.

This means that when you run `sifr fetch --locked`, `sifr tree`, or `sifr check`, Sifr forwards your lock and network settings consistently throughout the command without extra configuration.
