CLI reference¶
This is the authoritative CLI reference for incan (commands, flags, paths, and environment variables).
No-install fallback
If you did not run make install, you can still run the incan binary directly:
- from the repository root:
./target/release/incan ...
- or via an absolute path (from anywhere):
/absolute/path/to/incan run path/to/file.incn
Usage¶
Top-level usage:
incan [OPTIONS] [FILE] [COMMAND]
- If you pass a
FILEwithout a subcommand,incantype-checks it (default action).
Commands:
build- Compile to Rust and build an executablerun- Compile and run a programfmt- Format Incan source filestest- Run tests (pytest-style)new- Create a new Incan project directoryinit- Add a starterincan.tomland project skeleton to an existing directoryversion- Update the project version inincan.tomlenv- List, inspect, or run configured project environmentslock- Generate or updateincan.locktools- Inspect local toolchain, editor integration state, and checked metadata
Global options¶
--no-banner: suppress the ASCII logo banner when a command would otherwise show it (also viaINCAN_NO_BANNER=1).--color=auto|always|never: control ANSI color output (respectsNO_COLOR).
Banner policy:
- The banner is shown only for interactive
incan buildandincan runcommands. - Utility commands such as
new,init,version,env,lock,fmt, andteststay quiet by default.
Global options (debug)¶
These flags take a file and run a debug pipeline stage:
incan --lex path/to/file.incn
incan --parse path/to/file.incn
incan --check path/to/file.incn
incan --emit-rust path/to/file.incn
Strict mode:
incan --strict --emit-rust path/to/file.incn
Commands¶
incan build¶
Usage:
incan build [OPTIONS] <FILE> [OUTPUT_DIR]
incan build --lib [OPTIONS] [OUTPUT_DIR]
Behavior:
- Default mode compiles a source file into an executable.
--libbuilds the current project as a library. In this mode,src/lib.incnis required andFILEis optional.- Prints the generated Rust project path (example):
target/incan/<name>/ - Builds the generated Rust project and prints the binary path (example):
target/incan/.cargo-target/release/<name> - In
--libmode, also emits a library artifact undertarget/lib/(including<name>.incnlib).
Dependency flags:
--offline: Pass--offlineto Cargo subprocesses so dependency resolution/fetching fails instead of using the network.--locked: Requireincan.lockto exist and be up to date. Also passes--lockedto Cargo.--frozen: Like--locked, plus passes--frozento Cargo (offline + locked).--no-offline,--no-locked,--no-frozen: Disable matching environment defaults for this invocation.--cargo-args <ARG>...: Forward additional arguments to Cargo after policy and feature flags. Arguments after--are also treated as Cargo arguments.--cargo-features <FEATURES>: Enable specific Cargo features (comma-separated).--cargo-no-default-features: Disable default Cargo features.--cargo-all-features: Enable all Cargo features.
Without --locked or --frozen, incan build creates incan.lock when it is missing. If an existing lockfile is stale, the command warns and reuses the embedded Cargo.lock payload without rewriting incan.lock; run incan lock to refresh the committed lockfile intentionally.
Environment defaults:
INCAN_OFFLINE=1,INCAN_LOCKED=1, andINCAN_FROZEN=1behave like their matching flags.INCAN_FROZEN=1implies offline and locked mode.- CLI flags take precedence over these defaults. Use the
--no-*forms to disable a policy default set by the environment. INCAN_CARGO_ARGS="..."is split on whitespace and used when no Cargo args were supplied on the CLI.
Examples:
incan build examples/simple/hello.incn
incan build src/main.incn --offline
incan build src/main.incn --locked
incan build src/main.incn --frozen
incan build src/main.incn --cargo-features fancy_logging
incan build src/main.incn -- --timings
incan build --lib
incan run¶
Usage:
incan run [OPTIONS] [FILE]
Run a file:
incan run path/to/file.incn
Run the project's configured main script:
incan run
Run inline code:
incan run -c "import this"
If FILE is omitted, incan run uses [project.scripts].main from the nearest incan.toml. Outside a project, you must pass FILE or -c.
Dependency flags (same as build):
--offline,--locked,--frozen,--no-offline,--no-locked,--no-frozen,--cargo-args,--cargo-features,--cargo-no-default-features,--cargo-all-features
incan fmt¶
Usage:
incan fmt [OPTIONS] [PATH]
Examples:
# Format files in place
incan fmt .
# Check formatting without modifying (CI mode)
incan fmt --check .
# Show what would change without modifying files
incan fmt --diff path/to/file.incn
incan test¶
Usage:
incan test [OPTIONS] [PATH]
Test runner flags:
| Flag | Description |
|---|---|
-k <KEYWORD> |
Filter tests by stable test id substring |
-m <EXPR> / --markers <EXPR> |
Filter tests by marker expression (and, or, not, parentheses) |
-v |
Verbose output, including per-test timing and generated-harness preheat diagnostics |
-x |
Stop on first failure |
--slow |
Include slow tests (marked @slow) |
--strict-markers |
Reject unknown marker names during collection unless registered in TEST_MARKERS |
-j <N> / --jobs <N> |
Run up to N generated worker batches concurrently (single-threaded libtest execution per batch) |
--feature <NAME> |
Enable collection-time std.testing.feature("NAME") probe for skipif / xfailif |
--timeout <DURATION> |
Fail a test batch exceeding a duration (e.g., 250ms, 5s, 2m) |
--nocapture |
Print child test output even for passing tests |
--fail-on-empty |
Return exit code 1 if no tests are collected |
--list |
List collected tests after filters without executing them |
--format console\|json |
Choose human console output or JSON Lines result output (schema_version: "incan.test.v1") |
--junit <PATH> |
Write a JUnit XML report |
--durations <N> |
Print the slowest N test durations |
--shuffle |
Shuffle test execution order |
--seed <N> |
Seed for --shuffle |
--run-xfail |
Run @xfail tests as ordinary tests |
Dependency flags (same as build):
--offline,--locked,--frozen,--no-offline,--no-locked,--no-frozen,--cargo-args,--cargo-features,--cargo-no-default-features,--cargo-all-features
Without --locked or --frozen, incan test creates incan.lock when it is missing. If an existing lockfile is stale, the command warns and reuses the embedded Cargo.lock payload without rewriting incan.lock; run incan lock to refresh the committed lockfile intentionally.
Timeouts apply to generated test batches. --timeout sets the default batch timeout and @timeout("duration") from std.testing can override the batch containing one test. Fixtures, including async fixtures, do not have separate per-fixture timeout configuration. The runner awaits async fixture teardown after ordinary assertion failures and panics while the worker remains alive. If timeout enforcement terminates a worker process, remaining teardown is best-effort.
Before executing a stale generated test harness, incan test preheats it with cargo test --no-run and stores a fingerprint next to the generated project. A normal console run prints a preheat line only when this work is needed; -v also shows the preheat phase timing and whether another Incan process was already doing the same preheat. Lock generation also preheats non-trivial dependency graphs into the same generated test target domain before writing incan.lock, so the next harness run can reuse dependency artifacts instead of discovering a subzero Cargo graph on the hot path.
Examples:
# Run all tests in a directory
incan test tests/
# Run all tests under a path (default: .)
incan test .
# Filter tests by keyword expression
incan test -k "addition"
# List matching tests without running them
incan test --list -k "test_math"
# Verbose output (include timing)
incan test -v
# Stop on first failure
incan test -x
# Include slow tests
incan test --slow
# Select marker-tagged tests
incan test -m "smoke and not slow" tests/
# Validate marker names in CI
incan test --strict-markers tests/
# Enforce a default timeout
incan test --timeout 5s tests/
# Show passing-test output
incan test --nocapture tests/
# Fail if no tests are collected
incan test --fail-on-empty
# Emit JSON Lines and a JUnit report for CI
incan test --format json --junit reports/junit.xml tests/
# Reproduce a shuffled run
incan test --shuffle --seed 12345 tests/
# Strict mode for CI
incan test --frozen
incan new¶
Usage:
incan new [OPTIONS] [NAME]
Creates a new project directory with incan.toml, src/main.incn, tests/test_main.incn, README.md, and .gitignore. When run in an interactive terminal without --yes, it prompts for project metadata. In non-interactive contexts, pass NAME or --dir.
Options:
NAME: Project name. If omitted in an interactive terminal,incan newprompts for it.--dir <PATH>: Directory to create or reuse. Defaults to./<name>.--description <TEXT>: Project description written to[project].descriptionandREADME.md.--author <AUTHOR>: Author string, usuallyName <email>, written to[project].authors.--license <LICENSE>: License identifier or expression written to[project].license.--force: Reuse a non-empty directory and overwrite existing manifest/source/test scaffold files.-y,--yes: Use defaults and provided flags without interactive prompts.
Examples:
# Interactive metadata prompts
incan new
# Script-friendly project creation
incan new greeter --description "A small greeting command" --license MIT --yes
# Create the project in a different directory from its name
incan new greeter --dir examples/greeter --yes
incan init¶
Usage:
incan init [OPTIONS] [PATH]
Adds Incan project files to an existing directory. Use this when you already have a directory and want to add incan.toml, src/main.incn, tests/test_main.incn, README.md, and .gitignore. New projects usually start with incan new instead.
Options:
--name <NAME>: Project name (default: directory name).--version <VERSION>: Project version (default:"0.1.0").--description <TEXT>: Project description written to[project].descriptionandREADME.md.--author <AUTHOR>: Author string, usuallyName <email>, written to[project].authors.--license <LICENSE>: License identifier or expression written to[project].license.--force: Overwrite existing manifest/source/test scaffold files.--detect: Preserve an existingsrc/main.incnand, when the placeholder project name is still in use, derive the project name from the directory.-y,--yes: Use defaults and provided flags without interactive prompts.
Examples:
incan init
incan init --name my_app --description "My app" --license MIT my_project/
incan init --detect --yes
See: Project configuration reference for the full manifest format.
incan version¶
Usage:
incan version [OPTIONS] [BUMP]
Updates [project].version in incan.toml. BUMP is one of major, minor, patch, alpha, beta, rc, or dev. Use --set when you need an exact SemVer value instead of a bump.
Options:
BUMP: Version bump to apply.--set <VERSION>: Explicit SemVer version to write.--dry-run: Print the planned change without writingincan.toml.--keep-prerelease: Keep prerelease metadata when applyingmajor,minor, orpatch.--project <PATH>: Project root containingincan.toml.
Examples:
incan version patch
incan version rc --dry-run
incan version --set 1.2.3
incan version minor --project examples/greeter
incan env¶
Project environments are declared in [tool.incan.envs] in incan.toml. The ambient default environment is always available, and the env command lists available environments, shows a Hatch-style overview table, prints a compact resolved summary for one environment, or runs a named script from an environment.
Treat envs as named command contexts for repeatable workflows such as local testing, CI, docs, or release checks. They are not shell sessions or virtual environments.
Usage:
incan env list [OPTIONS]
incan env show [OPTIONS] [ENV]
incan env run [OPTIONS] <ENV> <SCRIPT> [-- <ARGS>...]
Shared options:
--format text|json: Output format forlistandshow(default:text).--project <PATH>: Project root containingincan.toml.
Run options:
--dry-run: Print the resolved command without executing it.-- <ARGS>...: Extra arguments appended to the configured script.
Examples:
incan env list
incan env show
incan env show default
incan env show dev --format json
incan env run dev test
incan env run dev test -- --fail-on-empty
incan env run release build --dry-run
For a fuller explanation of the mental model and a realistic default / unit / ci / docs configuration, see: Project lifecycle.
incan lock¶
Usage:
incan lock [OPTIONS] [FILE]
Resolves all dependencies (manifest + inline + test files) and generates or updates incan.lock.
If FILE is omitted, uses the [project.scripts].main entry from incan.toml.
Options:
--cargo-features <FEATURES>: Enable specific Cargo features for resolution.--cargo-no-default-features: Disable default Cargo features.--cargo-all-features: Enable all Cargo features.
Example:
incan lock src/main.incn
incan lock # uses [project.scripts].main
incan lock --cargo-features metrics # include optional deps in lock
The generated incan.lock contains an embedded Cargo.lock payload and a fingerprint of your dependency
inputs. Commit it to version control for reproducible builds.
See: Managing dependencies for practical guidance.
incan tools doctor¶
Usage:
incan tools doctor [OPTIONS]
Inspects local CLI/LSP/editor pathing and offline-readiness signals. Use this when the terminal and editor appear to be using different incan or incan-lsp binaries, when diagnostics look stale after rebuilding, or before a restricted/offline build where Cargo may be unable to fetch missing dependency inputs.
Options:
--format text|json: Output format (default:text).
The report includes:
- the running
incanversion and executable path incanandincan-lspresolution fromPATH~/.cargo/bin/incanand~/.cargo/bin/incan-lspexistence, executable status, and symlink targets- editor setup guidance for
incan.lsp.path,incan.compiler.path, and reload behavior
Offline-readiness:
- The doctor report is the supported preflight path for restricted or offline environments.
- The offline-readiness section is advisory. It checks local signals that affect whether Cargo can satisfy
--frozenpolicy without fetching, but it does not guarantee a laterincan build --frozenorincan test --frozenwill succeed. - Offline/locked policy constrains dependency resolution and fetching. Projects may still depend on Rust crates; those crates must already be available through Cargo's local inputs for an offline build to proceed.
- Use
--format jsonwhen an editor, CI preflight, or issue template needs the same information in a machine-readable form.
Examples:
incan tools doctor
incan tools doctor --format json
incan tools metadata api¶
Usage:
incan tools metadata api [PATH] [OPTIONS]
Emits checked public API metadata for an Incan source file or project directory. The command parses and type-checks the target before producing JSON, so the output describes the checked API surface rather than source text alone.
If PATH is omitted, the current directory is inspected. If PATH is a directory, src/lib.incn is preferred and src/main.incn is used as a fallback.
This command is source/project inspection, not artifact inspection. It does not build the project, emit generated Rust, or read an existing .incnlib; use incan build --lib for library artifact emission.
Options:
--format json: Output checked API metadata JSON (default).
The JSON package contains:
schema_version: numeric schema version for the package payloadpackage: project name and version fromincan.toml, when availablemodules: checked metadata documents for the entry module and imported local modulesdeclarations: public functions, models, classes, traits, enums, newtypes, type aliases, consts, statics, and public import aliasesanchor: stable declaration ids plus source byte spansdocstring: raw declaration or method docstring text when presentdocstring_sections: parsed summary, parameter, return, field, alias, and decorator sections when a docstring is presentdecorators: resolved decorator paths and safe literal, type, or const-reference arguments
Docstring validation is strict for mechanically checkable drift. If Args:, Returns:, Fields:, Aliases:, or Decorators: contradict checked source structure, the command reports diagnostics and does not print JSON.
Examples:
incan tools metadata api
incan tools metadata api src/lib.incn --format json
incan tools metadata api path/to/project
See: Checked API metadata for the JSON contract.
incan tools metadata model¶
Usage:
incan tools metadata model PATH MODEL [OPTIONS]
Emits one contract-backed model from project-declared bundle metadata, a bundle JSON file, or a built .incnlib artifact. MODEL may be the bundle logical_type_name or stable_model_id.
Options:
--format incan: Output formatted Incanmodelsource (default).--format json: Output the selected canonical model bundle JSON.
Examples:
incan tools metadata model . OrderSummary --format incan
incan tools metadata model contracts/order_summary.json orders.summary --format json
incan tools metadata model target/lib/orders.incnlib OrderSummary
See: Checked contract metadata for bundle schema, materialization, artifact inspection, and the matching LSP command.
Outputs and paths¶
Build outputs:
- Generated Rust project:
target/incan/<name>/ - Built binary:
target/incan/.cargo-target/release/<name> - Built library artifact (
--lib):target/lib/<name>.incnlibplus the generated library crate output
Cleaning:
rm -rf target/incan/
Environment variables¶
INCAN_STDLIB: override the stdlib directory (usually auto-detected; set only if detection fails).INCAN_FANCY_ERRORS: enable “fancy” diagnostics rendering (presence-based; output may change).INCAN_EMIT_SERVICE=1: toggle codegen emit mode (internal/debug; not stable).INCAN_NO_BANNER=1: disable the ASCII logo banner.NO_COLOR: disable ANSI color output (standard convention).
Exit codes¶
General rule: success is exit code 0; errors are non-zero.
Specific behavior:
incan run: returns the program’s exit code.incan test:- returns 0 if all tests pass
- returns 0 if test files exist but no tests are collected
- returns 1 if
--fail-on-emptyis set and no tests are collected - returns 1 if no test files are discovered under the provided path
- returns 1 if any tests fail or an xfail unexpectedly passes (XPASS)
incan fmt --check: returns 1 if any files would be reformatted.incan build/incan --check/ debug flags: return 1 on compile/build errors.
Drift prevention (maintainers)¶
Before a release, verify the docs stay aligned with the real CLI surface:
- Compare
incan --helpandincan {build,run,fmt,test,init,lock,tools} --helpagainst this page.