Skip to main content

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.rank from that directory's manifest.
  • If a directory has no rank.toml, the CLI falls back to ./main.rank.
  • Provider packages also use rank.toml at the provider package root.
  • The language server uses the same upward search to determine the project root.

Top-Level Shape

KeyRequiredMeaning
manifestVersionYesMust be 1.
[package]Yes for project and package rootsDeclares package metadata and source root.
[dependencies]NoImported Rank package dependencies.
[providers]NoImported provider registrations.
[registries]NoRegistry alias to URL mapping.
[registryScopes]NoScope-to-registry defaults for scoped package names.
[security]NoProject security defaults merged with CLI flags.
[provider]NoProvider-package metadata.
[[provider.exports]]Required when [provider] existsHost-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"
FieldRequiredMeaning
nameYesPackage name for humans and registry metadata.
versionYesPackage version string.
sourceYesSource 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, or git.
  • Each provider entry must contain exactly one of path or version.
  • path values are resolved relative to the manifest directory.
  • registry may only appear on registry-backed entries.
  • package may only appear on registry-backed entries.
  • git may appear only under [dependencies] in this slice.
  • Git-backed dependencies must declare exactly one of rev or tag.
  • subdir is optional and may appear only with git.
  • subdir must remain within the fetched repository root after normalization.
  • If package is omitted, the package name defaults to the table key.
  • If registry is omitted, Rank uses the default registry; [registryScopes] can override that default for scoped package names.
  • [dependencies] aliases define imported package namespaces such as shapes::....
  • [providers] aliases define imported provider namespaces such as faker::....
  • For providers, the alias should match the provider package's [provider].namespace.

Git dependency lock and cache behavior

  • { git, rev } treats rev as the initial resolved identity, but Rank still writes requestedRev and resolvedRev to rank.lock.
  • { git, tag } resolves the tag to a commit and writes requestedTag and resolvedRev to rank.lock.
  • rank sync, rank check, rank deps, and ordinary evaluation reuse the locked commit and cached snapshot after the first successful materialization.
  • --frozen-lockfile rejects any git dependency that does not already have a matching lock entry.
  • --offline requires 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 .rank modules alongside their provider exports

[registries]

[registries] defines named registry aliases.

[registries]
company = { url = "https://registry.example.com" }
FieldRequiredMeaning
urlYesBase 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 concrete resolvedRev used for loading.
  • rank.lock is part of the reproducibility contract. Commit it alongside rank.toml.
  • rank sync is 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
FieldTypeMeaning
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-msnumberNon-negative timeout in milliseconds for provider invocations.
offlineboolReuse 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-env yields an empty admitted environment view.
  • A bare "*" in allow-env is 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"
FieldRequiredMeaning
namespaceYesNamespace Rank programs import, such as use greeter::{ Greet }.
runtimeYesOne of native, node, deno, or bun.
entryYesProvider 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 = []
FieldRequiredMeaning
nameYesPublic export name.
kindYesOne of backend, function, or mutation.
typeParametersNoGeneric parameter clauses declared by this export. Each entry uses Name, Name extends Type, Name = Type, or Name extends Type = Default.
inputSchemaYesInput type expression in the provider package namespace.
outputSchemaYesOutput type expression in the provider package namespace.
capabilitiesYesDeclared provider capabilities.
reproducibilityRequired for backendExplicit reproducibility metadata for backend exports.
fulfillmentFieldRequired for mutationTop-level input field fulfilled later by the mutation commit path.

Kind-specific rules:

  • backend exports must declare reproducibility.
  • function exports must declare capabilities = [].
  • function exports may not declare reproducibility or fulfillmentField.
  • mutation exports must declare fulfillmentField.
  • mutation exports may not declare reproducibility.
  • typeParameters, when present, may not contain duplicates.
  • Later typeParameters entries may reference earlier parameters in bounds and defaults.
  • Defaulted typeParameters entries must stay trailing so omitted type arguments form a suffix.

Resolution Rules

  • rank.toml is 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-lockfile workflows.
  • Provider packages may combine ordinary pub source modules under [package].source with host-implemented exports declared in [[provider.exports]].

See also: