Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

12. Packages

A package is a git repository containing Korrin source that another program can import. This section is the normative description of the manifest, the lockfile, how a bare import specifier resolves once packages exist, and the korrin pkg command that manages them (ADR 0031, ADR 0032).

Packages are pure Korrin source. There is no way, as of this milestone, to write a package in Rust and ship it — that is future work.

12.1 The manifest: korrin.toml

A directory with a korrin.toml and a src/lib.kor is a package.

[package]
name = "requests"
version = "0.3.0"

[dependencies]
json = { git = "https://github.com/alice/korrin-json", tag = "v1.2.0" }
  • [package].name and [package].version are the package's own declared identity. They play no role in how a dependent resolves import — see §12.3.
  • [dependencies] is a table of local name → source. Each entry needs a git URL and exactly one of tag, branch, or rev. A package's own [dependencies] table must be empty — see §12.4.
  • The entry file is always src/lib.kor, regardless of [package].name.

12.2 The lockfile: korrin.lock

# @generated by `korrin pkg` — do not edit by hand.
version = 1

[[package]]
name = "json"
git = "https://github.com/alice/korrin-json"
rev = "a1b2c3d4e5f6..."
path = ".korrin/packages/json"

korrin.lock pins the exact commit resolved for every dependency, even one specified in korrin.toml by tag or branch. korrin pkg install writes it; korrin pkg update is the only command that moves an existing pin. An application commits korrin.lock; a package intended to be depended on does not.

Fetched packages are checked out locally at .korrin/packages/<name>/, next to the korrin.toml that declares them.

12.3 Resolution: one merged namespace

import_statement = "import" , STRING , [ "as" , NAME ] ;

Extends §11.1's resolution rule with a third outcome for a bare (non-./) specifier:

  • ./… or ../… — a file, as §11.1 describes. Unchanged.
  • anything else — checked against the built-in module table (§11.4, §11.5) first, then against the current package's installed dependencies. No new syntax distinguishes the two — import "math" and import "requests" are written identically. A name cannot appear in both tables: korrin pkg add/install refuses to add a dependency whose local name collides with a built-in module's name (ADR 0032). A name in neither table is E0314.
import "not_a_real_package"
# error: E0314

A package's own bare imports resolve against that package's installed dependencies (from its own korrin.toml/korrin.lock), not the top-level program's — but since packages are leaf-only (§12.4), a package's own [dependencies] table is always empty, so in practice a package's bare imports can only ever reach built-in modules. A package's relative (./) imports resolve against its own directory, exactly like any other file's.

12.4 Leaf-only packages

A package's own korrin.toml must declare an empty (or absent) [dependencies] table. korrin pkg add/install rejects a package that declares one:

korrin pkg: "json" (https://github.com/alice/korrin-json) declares
dependencies of its own — packages with dependencies are not supported
in Milestone 5

A package may depend on nothing. Depending on another package is not yet possible for a package itself, only for a top-level program.

12.5 The korrin pkg command

CommandEffect
korrin pkg add <git-url> [--tag T | --branch B | --rev R] [--name NAME]Adds a dependency to korrin.toml and resolves it into korrin.lock. NAME defaults to the repository's basename.
korrin pkg remove <name>Removes a dependency and re-resolves korrin.lock.
korrin pkg installFetches everything korrin.toml declares that isn't already checked out at its pinned commit; writes or refreshes korrin.lock.
korrin pkg update [name]Re-resolves a tag- or branch-pinned dependency to its current tip commit. Updates every dependency if name is omitted.
korrin pkg listPrints each resolved dependency: name, git URL, pinned commit, local path.

korrin pkg operations that fail (an unreachable git URL, a malformed manifest, a rejected leaf-only or name-collision dependency) print a message to standard error and exit non-zero. They are not Korrin diagnostics — there is no source span to point at, since nothing runs a Korrin program during korrin pkg add/install/update.

12.6 Errors

An installed-package import that cannot be resolved — no such name in the lockfile, the checkout is missing on disk, or the package's src/lib.kor fails to compile — is E0314, the same code a bad ./ or built-in specifier already raises: all three are the same category of problem ("this import could not be resolved, read, or compiled"), not three different ones. A cycle that crosses from a program into a package and back is E0315, exactly as for files (§11.6).