Projects & shape.toml
shape.toml is the project-level source of truth for module resolution, dependencies, extensions, and build behavior.
Minimal Example
Section titled “Minimal Example”[project]name = "demo"version = "0.1.0"entry = "src/main.shape"
[modules]paths = ["lib"]
[dependencies]utils = { path = "../utils" }
[[extensions]]name = "python"path = "./extensions/libshape_ext_python.so"autoload = true
[build]target = "bytecode"opt_level = 1output = "dist/"
[build.external]mode = "update" # or "frozen"Key Sections
Section titled “Key Sections”[project]
Section titled “[project]”Project metadata and required entrypoint for project execution.
When shape.toml exists, shape requires [project].entry (no implicit REPL fallback).
| Field | Type | Description |
|---|---|---|
name | string | Package name (required if other fields set) |
version | string | Semver version |
entry | string | Entry script path |
authors | string[] | Author names |
shape-version | string | Minimum Shape version |
license | string | SPDX license identifier |
repository | string | Repository URL |
[modules]
Section titled “[modules]”Additional module search roots.
[dependencies]
Section titled “[dependencies]”Shape module dependencies.
Supported forms:
{ path = "..." }— local path (also supports.shapecbundles){ git = "...", tag = "..." }(orbranch/rev)"^1.2"or{ version = "^1.2" }— semver registry dependency
Bundle dependencies: if the path points to a .shapec file, or a .shapec file exists alongside the directory, the pre-compiled bundle is used. See Packages & Building.
Registry resolution is semver-based and includes transitive constraint solving.
By default it uses ~/.shape/registry/index and ~/.shape/registry/src, and can be
overridden with SHAPE_REGISTRY_INDEX / SHAPE_REGISTRY_SRC.
[[extensions]]
Section titled “[[extensions]]”Loadable runtime extensions (.so modules), discovered through the unified loader.
Required fields:
namepath
Optional:
autoload = true|false[extensions.config](module-specific options)
[build]
Section titled “[build]”Build configuration for shape build.
| Field | Type | Default | Description |
|---|---|---|---|
target | string | "bytecode" | Build target ("bytecode" or "native") |
opt_level | integer | 0 | Optimization level (0-3) |
output | string | — | Output directory |
[build.external]
Section titled “[build.external]”Controls external artifact refresh in unified lockflow:
update: allow refresh and lock updatesfrozen: require existing lock artifacts
Extension Sections
Section titled “Extension Sections”Extensions can claim custom TOML sections in shape.toml. Any section not recognized as a built-in ([project], [modules], [dependencies], [dev-dependencies], [build], [[extensions]]) is captured as an extension section.
[project]name = "my-project"version = "1.0.0"
[native-dependencies]libcurl = { linux = "libcurl.so.4", macos = "libcurl.dylib" }
[custom-config]api_key_env = "MY_API_KEY"Extensions declare which sections they handle through the ABI. Unclaimed sections produce validation warnings. See Extensions for the claiming mechanism.
For native ABI resolution and lock guarantees, use the canonical Native C Interop chapter.
That chapter defines provider semantics (system/path/vendored),
target-qualified targets entries (os-arch[-env]), host resolution, and
frozen-mode safety requirements for [native-dependencies].
Lockfiles
Section titled “Lockfiles”- Project mode uses
shape.lockin the project root. - Standalone scripts use
<script>.lock. - Native artifacts in those lockfiles are host-target- and fingerprint-specific, so one committed lockfile may contain multiple variants for different machines.
Both include dependency pinning and compile-time artifacts.
Frontmatter Interop
Section titled “Frontmatter Interop”Project shape.toml and script frontmatter are mutually exclusive during execution. If a script is inside a project, use shape.toml only.
The Shape LSP validates shape.toml directly and provides completion, hover, and diagnostics for known sections and keys.