Skip to main content
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:
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.

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

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

Create a library package

Run sifr init --lib with your package name:
This generates:
2

Create an app package

Use --bin instead to scaffold an application:
The generated layout uses src/main.sifr in place of src/__init__.sifr.
3

Fetch dependencies

Move into your new package directory and fetch its initial dependency set:
The generated Cargo.toml includes the metadata pointer that Sifr uses to locate your manifest at runtime:
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.