Project configuration (incan.toml)¶
This is the reference for the incan.toml project manifest format. For a practical guide to managing dependencies, see:
Managing dependencies.
Overview¶
incan.toml is an optional project manifest that lives at your project root. It declares project metadata, Rust crate
dependencies, and build configuration. The compiler discovers it by walking upward from the source file's directory.
my_project/
├── src/
│ └── main.incn
├── tests/
│ └── test_main.incn
├── incan.toml # Project manifest
└── incan.lock # Generated lock file (commit to VCS)
You can scaffold a full project (manifest, entry point, and starter test) with incan init.
[project]¶
Project metadata. All fields are optional.
[project]
name = "my_app"
version = "0.1.0"
description = "A short description of what this project does"
authors = ["Alice <alice@example.com>"]
license = "MIT"
readme = "README.md"
requires-incan = ">=0.2"
[project.scripts]¶
Named entry points for CLI commands:
[project.scripts]
main = "src/main.incn" # This is the default entry point if no other is set
migrate = "src/migrate.incn" # This is a example of a named entry point called "migrate"
incan init sets main = "src/main.incn" by default. When main is set, incan lock can run without
a FILE argument.
[project.features]¶
Optional feature flags that can enable optional dependencies:
[project.features]
full = ["fancy_logging", "metrics"]
[build]¶
Build configuration. All fields are optional.
[build]
rust-edition = "2021" # Rust edition for the generated Cargo.toml (default: compiler-chosen)
profile = "release" # Cargo build profile
target = "x86_64-unknown-linux-gnu" # Cross-compilation target
source-root = "src" # Source root for module resolution (default: convention-based)
source-root¶
The directory where the compiler and test runner look for user modules. Resolution order:
- Explicit: if
source-rootis set, that directory is used (relative to project root) - Convention: if a
src/directory exists at the project root, it is used automatically - Fallback: the project root itself (flat layout)
Most projects use the conventional src/ layout and don't need to set this field. It exists for projects that keep
their source in a different directory (e.g. lib/).
[dependencies]¶
Rust crate dependencies available in all contexts (build, run, test).
String shorthand¶
For simple registry dependencies with just a version:
[dependencies]
serde = "1.0"
rand = "0.8"
Table form¶
For dependencies that need features, sources, or other options:
[dependencies]
tokio = { version = "1.35", features = ["full"] }
serde = { version = "1.0", features = ["derive"], default-features = true }
All fields¶
| Field | Type | Description |
|---|---|---|
version |
string | Cargo SemVer version requirement (required for registry) |
features |
list | Cargo features to enable |
default-features |
bool | Whether to include default features (default: true) |
optional |
bool | Mark as optional (see below) |
package |
string | The actual crate name if renaming (e.g. serde-json) |
git |
string | Git repository URL (mutually exclusive with path) |
branch |
string | Git branch (requires git) |
tag |
string | Git tag (requires git) |
rev |
string | Git commit hash (requires git) |
path |
string | Local path, relative to incan.toml location |
[dev-dependencies]¶
Dependencies available only in test contexts (tests/ directory). Same syntax as [dependencies].
[dev-dependencies]
criterion = "0.5"
test_helpers = { path = "../test-helpers" }
Importing a dev-only crate from production code is a compile-time error:
error: Rust crate `criterion` is dev-only and cannot be imported from production code
hint: Move the dependency to [dependencies], or import it only from tests.
Overlap rules: If the same crate appears in both [dependencies] and [dev-dependencies], the version, source,
and default-features must match. Features are unioned, and the crate is treated as a normal dependency.
[dependencies.optional]¶
Syntactic sugar for declaring optional (rust) dependencies. Entries here are equivalent to setting optional = true:
[dependencies.optional]
fancy_logging = "0.3"
metrics = { version = "1.0", features = ["prometheus"] }
is equivalent to:
[dependencies]
fancy_logging = { version = "0.3", optional = true }
metrics = { version = "1.0", features = ["prometheus"], optional = true }
Optional dependencies generate a Cargo feature gate. Enable them at build time:
incan build src/main.incn --cargo-features fancy_logging
[rust.dependencies] / [rust.dev-dependencies]¶
These are aliases for [dependencies] and [dev-dependencies] respectively. They exist for readability when the
manifest contains non-Rust configuration.
# These two are equivalent:
[dependencies]
serde = "1.0"
[rust.dependencies]
serde = "1.0"
Mutual exclusion
You cannot use both [dependencies] and [rust.dependencies] in the same manifest (same for dev).
The compiler will error if both are present.
Dependency sources¶
Registry (default)¶
The default source is crates.io. Version is required:
[dependencies]
serde = "1.0"
tokio = { version = "1.35", features = ["full"] }
Git¶
Specify a git repository URL with exactly one of branch, tag, or rev:
[dependencies]
my_internal_lib = { git = "https://github.com/company/lib.git", tag = "v1.0.0" }
bleeding_edge = { git = "https://github.com/company/lib.git", branch = "main" }
pinned = { git = "https://github.com/company/lib.git", rev = "abc1234" }
Strict mode and git branches
When building with --locked or --frozen, git dependencies using branch = "..." are rejected
because branches are not reproducible. Use tag or rev instead.
Path¶
Local path dependencies, relative to the incan.toml location:
[dependencies]
shared_utils = { path = "../shared-utils" }
Package renames¶
Use package to use a different crate name than the dependency key. For example:
[dependencies]
json = { package = "serde_json", version = "1.0" }
This lets you import rust::json instead of import rust::serde_json.
Complete example¶
[project]
name = "my_web_app"
version = "0.1.0"
description = "A web application built with Incan"
authors = ["Alice <alice@example.com>"]
[project.scripts]
main = "src/main.incn"
[build]
rust-edition = "2021"
[dependencies]
tokio = { version = "1.35", features = ["full"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
sqlx = { version = "0.7", features = ["runtime-tokio", "postgres"] }
[dependencies.optional]
fancy_logging = "0.3"
[dev-dependencies]
criterion = "0.5"
See also¶
- Managing dependencies - Practical guide
- Rust interop - Inline version annotations
- CLI reference -
incan init,incan lock, and dependency flags