The conf.d merge model
This is the core of PolyForge’s architecture. Everything else is convention; this is mechanism.
Two merges, used together
Section titled “Two merges, used together”mise composes configuration in two independent ways. PolyForge uses both, for different jobs.
1. Fragment merge — .config/mise/conf.d/*.toml
Section titled “1. Fragment merge — .config/mise/conf.d/*.toml”Every .toml file in conf.d/ is loaded, in alphabetical order. The numeric
prefixes are not decoration — they are the load order, and they encode intent:
Directory.config/mise/conf.d/
- 00-settings.toml global behaviour — jobs,
auto_install = false - 10-core-tools.toml interpreters — python, node, go, rust, java, dart, flutter
- 20-cli-tools.toml the toolbelt — eza, bat, ripgrep, fd, jq, zoxide, delta, btm
- 30-package-managers.toml bun, deno, pnpm, uv, zig, cmake, ninja
- 00-settings.toml global behaviour — jobs,
Settings land first so everything after inherits them. Interpreters before the
package managers that depend on them. New categories slot into the gaps —
40-elixir.toml, 25-database-tools.toml — without touching an existing file.
2. Tree merge — up the directory hierarchy
Section titled “2. Tree merge — up the directory hierarchy”mise walks up from your current directory, collecting configuration as it
goes. Because conf.d/ sits at the workspace root, its tools are in scope in
every subfolder — Workspace/Go/, Dev/Learn/python/day04-decorators/,
everywhere.
A deeper mise.toml then inherits its ancestors’ tasks and environment and
overrides only what it names:
polyforge/├── .config/mise/conf.d/*.toml ← base toolchain, workspace-wide├── mise.toml ← root orchestration: env, hooks, tasks└── Workspace/ └── Go/ └── mise.toml ← inherits the above, overrides Go specificsWhy not includes?
Section titled “Why not includes?”The obvious design would be one mise.toml that imports fragments. mise
2026.6.x does not support includes or import.
Rather than work around a missing feature with a build step or a generated file, PolyForge uses the two merges mise does guarantee. The result is arguably better than the import version would have been: there is no generated artifact to keep in sync, and adding a language is genuinely a single new file.
Consequences you should know about
Section titled “Consequences you should know about”Alphabetical order is real order. A fragment named 05-experimental.toml
loads before 10-core-tools.toml and can be overridden by it. Name files for
where you want them in the sequence.
Later fragments win on conflict. If two fragments declare the same tool, the one that loads later takes precedence. Keep each tool in exactly one fragment.
Scope follows the tree, not the project. A tool is available because of where
you are standing, not because a project declared it. If you want a tool
available only inside one language area, declare it in that area’s mise.toml,
not in conf.d/.
Depth costs nothing. Being ten directories deep inside a project does not change what is available — mise still walks all the way up to the workspace root.
Adding to the toolchain
Section titled “Adding to the toolchain”The whole procedure:
- Create a fragment in
.config/mise/conf.d/, numbered for its category. - Optionally add
Workspace/<Lang>/mise.tomlfor language-specific env or tasks. - Run
polyforge install.
Step-by-step in adding a language; the file schema is in the conf.d reference.