Manifest Reference
rank.toml is the project manifest for Rank programs, packages, and providers. It declares the source root, dependency and provider registrations, registry aliases, security defaults, provider-package metadata, and git-backed dependency sources.
Synopsis
Minimal project manifest:
manifestVersion = 1
[package]
name = "hello-rank"
version = "0.1.0"
source = "src"
Project manifest with dependencies, providers, registry aliases, and security defaults:
manifestVersion = 1
[package]
name = "acme-app"
version = "0.1.0"
source = "src"
[registries]
company = { url = "https://registry.example.com" }
[registryScopes]
"@acme" = "company"
[dependencies]
collections = { registry = "npm", package = "@rank-lang/lib-collections", version = "1.2.0" }
shapes = { path = "./vendor/shapes" }
shared = { git = "https://github.com/acme/shared.git", rev = "8d91b7c4e5d0c1a2b3f4e5d6c7b8a9b0c1d2e3f4" }
[providers]
faker = { registry = "npm", package = "@rank-lang/plugin-faker", version = "0.1.0" }
vault = { path = "./providers/vault" }
[security]
allow-provider-capabilities = ["network"]
allow-http-hosts = ["api.example.com"]
allow-env = ["API_*", "AWS_REGION"]
provider-timeout-ms = 30000
offline = false
Provider package manifest:
manifestVersion = 1
[package]
name = "acme-provider"
version = "0.4.0"
source = "src"
[provider]
namespace = "acme"
runtime = "node"
entry = "./dist/provider.js"
[[provider.exports]]
name = "Lookup"
kind = "backend"
inputSchema = "types::LookupInput"
outputSchema = "types::LookupOutput"
reproducibility = ["service", "key", "cacheKey"]
capabilities = ["network"]
File Location And Discovery
The manifest filename is exactly rank.toml.
- Project commands walk upward from a file entry until they find
rank.toml. - When you pass a directory, Rank resolves
[package].source/main.rankfrom that directory's manifest. - If a directory has no
rank.toml, the CLI falls back to./main.rank. - Provider packages also use
rank.tomlat the provider package root. - The language server uses the same upward search to determine the project root.
Top-Level Shape
| Key | Required | Meaning |
|---|---|---|
manifestVersion | Yes | Must be 1. |
[package] | Yes for project and package roots | Declares package metadata and source root. |
[dependencies] | No | Imported Rank package dependencies. |
[providers] | No | Imported provider registrations. |
[registries] | No | Registry alias to URL mapping. |
[registryScopes] | No | Scope-to-registry defaults for scoped package names. |
[security] | No | Project security defaults merged with CLI flags. |
[provider] | No | Provider-package metadata. |
[[provider.exports]] | Required when [provider] exists | Host-implemented exports declared by a provider package. |
[package]
Every ordinary project or installable package needs a [package] table.
[package]
name = "inventory"
version = "0.1.0"
source = "src"
| Field | Required | Meaning |
|---|---|---|
name | Yes | Package name for humans and registry metadata. |
version | Yes | Package version string. |
source | Yes | Source root directory, resolved relative to the manifest. |
source becomes the canonical root:: module tree for ordinary project imports. If source = "src", then src/main.rank is imported as root::main.
Inside that project-local module tree, nearby imports may also use contextual relative anchors: self::... resolves from the current module namespace, and super::... resolves from the parent namespace.
[dependencies] And [providers]
Dependency and provider entries overlap, but they do not share the exact same reference shape. The table key is the import alias used in Rank source.
Dependencies can be distributed through local paths, npm-compatible registries, or git repositories. Providers can be distributed through local paths or npm-compatible registries. For package publication workflows, see Dependencies and Provider authoring.
Path-based reference:
[dependencies]
shapes = { path = "./vendor/shapes" }
[providers]
vault = { path = "./providers/vault" }
Registry-backed reference:
[dependencies]
collections = { registry = "npm", package = "@rank-lang/lib-collections", version = "1.2.0" }
[providers]
faker = { registry = "npm", package = "@rank-lang/plugin-faker", version = "0.1.0" }
Git-backed dependency reference:
[dependencies]
shared = { git = "https://github.com/acme/shared.git", rev = "8d91b7c4e5d0c1a2b3f4e5d6c7b8a9b0c1d2e3f4" }
theme = { git = "https://github.com/acme/theme.git", tag = "v1.4.2" }
ui = { git = "ssh://git@github.com/acme/mono.git", rev = "6a1f0d9a8b7c6e5d4c3b2a190817161514131211", subdir = "packages/ui" }
Reference rules:
- Each dependency entry must contain exactly one of
path,version, orgit. - Each provider entry must contain exactly one of
pathorversion. pathvalues are resolved relative to the manifest directory.registrymay only appear on registry-backed entries.packagemay only appear on registry-backed entries.gitmay appear only under[dependencies]in this slice.- Git-backed dependencies must declare exactly one of
revortag. subdiris optional and may appear only withgit.subdirmust remain within the fetched repository root after normalization.- If
packageis omitted, the package name defaults to the table key. - If
registryis omitted, Rank uses the default registry;[registryScopes]can override that default for scoped package names. [dependencies]aliases define imported package namespaces such asshapes::....[providers]aliases define imported provider namespaces such asfaker::....- For providers, the alias should match the provider package's
[provider].namespace.
Git dependency lock and cache behavior
{ git, rev }treatsrevas the initial resolved identity, but Rank still writesrequestedRevandresolvedRevtorank.lock.{ git, tag }resolves the tag to a commit and writesrequestedTagandresolvedRevtorank.lock.rank sync,rank check,rank deps, and ordinary evaluation reuse the locked commit and cached snapshot after the first successful materialization.--frozen-lockfilerejects any git dependency that does not already have a matching lock entry.--offlinerequires both a matching lock entry and a cached snapshot for every git dependency.
Dependency vs provider
A dependency is a regular Rank package. Rank loads its .rank source modules from that package's [package].source tree, and you use it for pure reusable code such as types, helper functions, transforms, and shared schemas.
A provider is a host extension. In addition to the ordinary package manifest, it also declares [provider] and [[provider.exports]] metadata for host-implemented operations. Use a provider when the package needs capabilities or behavior that ordinary Rank source cannot provide by itself, such as external backends, network calls, filesystem access, or commit-time mutations.
In practice:
- dependencies are library code
- providers are manifest-declared host operations
- dependencies do not have a provider runtime entrypoint or capability surface
- providers do have a runtime entrypoint, export metadata, and capability/security controls
- provider packages may still ship ordinary
.rankmodules alongside their provider exports
[registries]
[registries] defines named registry aliases.
[registries]
company = { url = "https://registry.example.com" }
| Field | Required | Meaning |
|---|---|---|
url | Yes | Base URL for the registry alias. |
Use registry aliases from dependency or provider references:
[dependencies]
ui = { registry = "company", package = "@acme/ui", version = "1.4.0" }
[registryScopes]
[registryScopes] maps npm-style package scopes to registry aliases.
[registryScopes]
"@acme" = "company"
This lets a scoped package pick up a registry alias automatically when the reference omits registry:
[dependencies]
ui = { package = "@acme/ui", version = "1.4.0" }
With the scope mapping above, Rank resolves @acme/ui through the company registry alias.
rank.lock
External dependency materialization writes rank.lock. Registry-backed packages, providers, and git-backed dependencies all use the same explicit version-2 lockfile envelope.
version = 2
[[packages]]
kind = "registry"
registry = "npm"
registryUrl = "https://registry.npmjs.org"
package = "@rank-lang/lib-collections"
requestedVersion = "1.2.0"
resolvedVersion = "1.2.0"
resolvedTarballUrl = "https://registry.npmjs.org/@rank-lang/lib-collections/-/lib-collections-1.2.0.tgz"
integrity = "sha512-..."
[[packages]]
kind = "git"
git = "https://github.com/acme/theme.git"
requestedTag = "v1.4.2"
resolvedRev = "4e8d2c4c9b7a6d5e1f3c2a190817161514131211"
[[packages]]
kind = "git"
git = "ssh://git@github.com/acme/mono.git"
requestedRev = "6a1f0d9a8b7c6e5d4c3b2a190817161514131211"
resolvedRev = "6a1f0d9a8b7c6e5d4c3b2a190817161514131211"
subdir = "packages/ui"
Lockfile rules:
- Registry entries use
kind = "registry"and record the resolved tarball identity. - Git entries use
kind = "git"and record the requested selector plus the concreteresolvedRevused for loading. rank.lockis part of the reproducibility contract. Commit it alongsiderank.toml.rank syncis the explicit prefetch workflow for writing or refreshing lock entries without evaluating the entrypoint.
[security]
[security] stores project defaults for the same security controls exposed by CLI flags.
[security]
allow-provider-capabilities = ["network"]
allow-provider-mutation-exports = ["aws::PutObject"]
allow-http-hosts = ["api.example.com"]
allow-env = ["API_*", "AWS_REGION"]
provider-timeout-ms = 30000
offline = false
| Field | Type | Meaning |
|---|---|---|
allow-provider-capabilities | [string] | Provider capability allowlist. Standardized values include network and filesystem. |
allow-provider-mutation-exports | [string] | Exact-name allowlist for reachable mutation provider exports. |
allow-http-hosts | [string] | Static host allowlist for HTTP::Fetch. |
allow-env | [string] | Runtime environment-variable allowlist for serve startup Env<T> and request-time providers. |
provider-timeout-ms | number | Non-negative timeout in milliseconds for provider invocations. |
offline | bool | Reuse cached artifacts only; block live network fetches. |
Merge behavior:
- Additive settings are unioned with CLI flags.
- Scalar settings use CLI values when provided.
- For runtime-bearing hosts, omitting
allow-envyields an empty admitted environment view. - A bare
"*"inallow-envis the explicit allow-all escape hatch and should be used deliberately.
[provider]
Provider packages use the same root manifest and add a [provider] table.
[provider]
namespace = "greeter"
runtime = "node"
entry = "./src/provider.js"
| Field | Required | Meaning |
|---|---|---|
namespace | Yes | Namespace Rank programs import, such as use greeter::{ Greet }. |
runtime | Yes | One of native, node, deno, or bun. |
entry | Yes | Provider runtime entry point, resolved relative to the manifest. |
When [provider] is present, the manifest must also declare one or more [[provider.exports]] entries.
[[provider.exports]]
Each [[provider.exports]] block declares one host-implemented export.
[[provider.exports]]
name = "Lookup"
kind = "function"
typeParameters = ["T", "K extends keyof T = `id`"]
inputSchema = "types::LookupInput<T, K>"
outputSchema = "T[K]"
capabilities = []
| Field | Required | Meaning |
|---|---|---|
name | Yes | Public export name. |
kind | Yes | One of backend, function, or mutation. |
typeParameters | No | Generic parameter clauses declared by this export. Each entry uses Name, Name extends Type, Name = Type, or Name extends Type = Default. |
inputSchema | Yes | Input type expression in the provider package namespace. |
outputSchema | Yes | Output type expression in the provider package namespace. |
capabilities | Yes | Declared provider capabilities. |
reproducibility | Required for backend | Explicit reproducibility metadata for backend exports. |
fulfillmentField | Required for mutation | Top-level input field fulfilled later by the mutation commit path. |
Kind-specific rules:
backendexports must declarereproducibility.functionexports must declarecapabilities = [].functionexports may not declarereproducibilityorfulfillmentField.mutationexports must declarefulfillmentField.mutationexports may not declarereproducibility.typeParameters, when present, may not contain duplicates.- Later
typeParametersentries may reference earlier parameters in bounds and defaults. - Defaulted
typeParametersentries must stay trailing so omitted type arguments form a suffix.
Resolution Rules
rank.tomlis versioned, source-controlled project state. Treat it as part of the program, not as an incidental local config file.- All manifest-relative paths are resolved from the directory that contains the manifest.
- Registry-backed dependencies and providers, plus git-backed dependencies, participate in
rank sync,rank.lock,--offline, and--frozen-lockfileworkflows. - Provider packages may combine ordinary
pubsource modules under[package].sourcewith host-implemented exports declared in[[provider.exports]].
See also: