minimal.toml
The minimal.toml file defines the configuration for Minimal in a codebase.
This file must be present at the base of the repository (i.e. ./minimal.toml), or in a .minimal directory at the base of the repository.
Unless -C is specified, the mip CLI searches the directory tree backwards from the current directory till a minimal.toml file is found. This behavior allows minimal to be invoked in project directories.
Example
[upstream]
repo = "https://github.com/gominimal/pkgs"
branch = "main"
locked_commit = "d39aaaa581f983d6b3ba5eaaf383485a602f37f0"
[stack]
use = "pnpm"
build_packages = ["railway"]
[defaults]
state_key = "dev"
[tasks.dev]
exec = "pnpm run dev"
[tasks.preview]
env_vars.PORT = "8080"
bash = "pnpm run build && pnpm run start"
[tasks.deploy]
packages = ["railway"]
exec = "railway up"
[tasks.shell]
interactive = true
packages = ["base", "git", "nano"]
exec = "bash -l"Schema
[upstream] - Where software comes from
The [upstream] section defines the precise source of packages, stacks, and profiles. This represents the preceding link in the software supply chain.
[upstream]
repo = "<git URL>"
branch = "<branch>"
locked_commit = "<commit hash>"locked_commit is automatically updated when mip update is run: it re-resolves branch to its current HEAD and rewrites the locked_commit of the upstream (and of every sideload) in minimal.toml in place — expect a diff on these fields after running it.
[[upstream.sideload]] - Additional software sideloaded into your supply chain
Sideload entries let you load in additional packages, stacks, and profiles from a separate repository, but those packages are built using the version of packages from your upstream.
Each sideload entry is loaded in order from the specified repository, and follows the same schema as [upstream]:
[[upstream.sideload]]
repo = "<git URL>"
branch = "<branch>"
locked_commit = "<commit hash>" # Updated via `mip update`Sideload repositories have the same layout as an upstream: that is having a minimal.toml file, and packages/ / stacks/ / profiles/ directories as needed.
[stack] - How to build code in your repo
[stack]
use = "<stack name>"
build_packages = ["<additional build package>"] # optional
runtime_packages = ["<additional runtime package>"] # optionalThe [stack] section configures the stack to use for building code, if any. See stack specs for how stacks themselves are defined.
[harness] is accepted as a deprecated alias for [stack], pending removal after July 2026; prefer [stack] in new configs.
The environment variables and packages configured on a stack are inherited on all tasks in this repository.
build_packages and runtime_packages are optional fields that allow you to declare additional package dependencies for build time or run time respectively.
[defaults] - Settings for all tasks
[defaults]
profile = "<profile name>" # optional
state_key = "<state key>" # optionalWhen set, defaults.profile will set a profile on all tasks which do not set a profile.
When set, defaults.state_key will set a state key on all tasks which do not set state_key.
[tasks.*] - Run tasks, scripts, & dev tooling
See: tasks.
[outputs.*] - Artifacts produced by mip materialize
Each [outputs.<name>] section defines an artifact that can be produced with mip materialize <name> -o <path>.
[outputs.<name>]
type = "<output type>" # required; alias: `ty`
packages = ["<package>", ...] # optional; defaults to ["base"] when empty
arch = "<arch>" # optional; e.g. "amd64", "arm64"
path = "<path>" # raw-file only; required there, invalid for oci-image
entrypoint = "<cmd>" # oci-image only; string or list of strings
cmd = ["<arg>", ...] # oci-image only; string or list of strings
vars = { KEY = "value" } # oci-image only; alias: `env_vars`Output types
type | Description |
|---|---|
oci-image | A Linux OCI image archive built from packages. Compatible with docker load and OCI-compatible registries. |
raw-file | A single file extracted from packages at the given path. Useful for pulling one artifact (a kernel image, a rootfs image, …) out of a package's file tree. |
Fields
type(alias:ty) — The output kind, eitheroci-imageorraw-file. Defaults tooci-imagewhen omitted.packages— Packages to include in the materialized output. When omitted or empty, defaults to["base"].arch— Target architecture for OCI images. Common values:amd64,arm64. The CLI flag--archoverrides this; if neither is set, the host architecture is used.path— (raw-fileonly) Path, relative to the package file tree, of the single file to extract. Required forraw-fileoutputs; supplying it on anoci-imageoutput is an error.entrypoint— (oci-imageonly) OCI image entrypoint. May be a string ("/app/server") or a list (["/bin/sh", "-c"]).cmd— (oci-imageonly) OCI image default command. Same string-or-list shape asentrypoint.vars(alias:env_vars) — (oci-imageonly) Environment variables baked into the image as aKEY = "value"table.
Setting an oci-image-only field (entrypoint, cmd, vars) on a raw-file output — or setting path on an oci-image output — is rejected when the minimal.toml is parsed.
Examples
A minimal OCI image of just the base packages, useful for ad-hoc shells:
[outputs.base-image]
type = "oci-image"mip materialize base-image -o ./base.tarA server image with extra packages, an entrypoint, and an env var:
[outputs.app]
type = "oci-image"
arch = "arm64"
packages = ["base", "openssl"]
entrypoint = "/app/server"
vars = { PORT = "8080" }mip materialize app -o ./app.tarOverride the architecture at the command line:
mip materialize app --arch amd64 -o ./app-amd64.tarA raw-file output extracts a single file from a package. Here the kernel Image is pulled out of the virtio-kernel-raw package:
[outputs.virtio-kernel]
type = "raw-file"
packages = ["virtio-kernel-raw"]
path = "usr/share/virtio-linux/Image"mip materialize virtio-kernel -o ./Image