Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ a lot easier than figuring out mise's rules.
Notes:

- Paths which start with `mise` can be dotfiles, e.g.: `.mise.toml` or `.mise/config.toml`.
- This list doesn't include [Configuration Environments](/configuration/environments) which allow for environment-specific config files like `mise.development.toml`—set with `MISE_ENV=development`.
- This list doesn't include [Configuration Environments](/configuration/environments) which allow for environment-specific config files like `mise.development.toml`—set with `MISE_ENV=development`. Platform-specific environments like `mise.windows.toml` or `mise.macos-arm64.toml` can be enabled automatically with the [`auto_env` setting](/configuration/environments.html#platform-environments).
- See [`LOCAL_CONFIG_FILENAMES` in `src/config/mod.rs`](https://github.com/jdx/mise/blob/main/src/config/mod.rs) for the actual code for these paths and their precedence. Some legacy paths are not listed here for brevity.

## Configuration Hierarchy
Expand Down
42 changes: 42 additions & 0 deletions docs/configuration/environments.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,45 @@ The rules around which file is written are different because we ultimately need
the docs for [`mise use`](/cli/use.html) for more information.

Multiple environments can be specified, e.g. `MISE_ENV=ci,test` with the last one taking precedence.

## Platform environments

With the [`auto_env` setting](/configuration/settings.html#auto_env) enabled, mise automatically
treats the following as active config environments, based on the current platform:

| Environment | Values |
| ------------- | ---------------------------------------------- |
| `{os_family}` | `unix` (not defined on Windows—use `windows`) |
| `{os}` | `linux`, `macos`, `windows` |
| `{os}-{arch}` | e.g. `linux-x64`, `macos-arm64`, `windows-x64` |

Architectures use mise's remapped names: `x86_64` → `x64` and `aarch64` → `arm64`.

This makes config files like `mise.windows.toml`, `mise.macos-arm64.toml`, or `mise.unix.toml`
load automatically, and matching lockfiles like `mise.windows.lock` get selected. All of the
usual config file locations and `.local.toml` variants work.

Platform environments have lower precedence than explicit `MISE_ENV` entries. The full order is
(later overrides earlier): `unix` < `{os}` < `{os}-{arch}` < explicit `MISE_ENV` entries.

Platform environments only affect config file discovery and lockfile selection. They are not
added to `MISE_ENV` itself: the `{{ mise_env }}` template variable and the `MISE_ENV` variable
passed to subprocesses and tasks only reflect explicit environments.

### Rollout

`auto_env` is currently **disabled by default**. Starting with mise `2027.6.0` it will default
to enabled; from `2026.12.0` until then, mise warns if it finds a platform-specific config file
that would be newly loaded. To control the behavior explicitly:

```toml
# .miserc.toml
auto_env = true # adopt the new behavior now
# or
auto_env = false # keep the old behavior and silence the warning
```

or set `MISE_AUTO_ENV=true` / `MISE_AUTO_ENV=false`. Like `MISE_ENV`, this is an early-init
setting: it must be set in `.miserc.toml` or via the environment variable — setting it in
`mise.toml` has no effect because config file discovery has already happened by the time
`mise.toml` is read.
69 changes: 69 additions & 0 deletions e2e/config/test_config_auto_env
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
#!/usr/bin/env bash

# Test auto_env: platform environments (unix, {os}, {os}-{arch}) are
# automatically active for config file discovery when enabled

os="$(uname -s)"
case "$os" in
Darwin) os=macos ;;
Linux) os=linux ;;
esac
arch="$(uname -m)"
case "$arch" in
x86_64) arch=x64 ;;
aarch64 | arm64) arch=arm64 ;;
esac

echo 'env.AAA = "base"
env.BBB = "base"' >mise.toml
echo 'env.AAA = "unix"
env.UNIX_LOADED = "1"' >mise.unix.toml
echo "env.AAA = \"$os\"" >"mise.$os.toml"
echo "env.AAA = \"$os-$arch\"" >"mise.$os-$arch.toml"
echo 'env.AAA = "prod"' >mise.prod.toml

# default: off, platform configs are not loaded
assert "mise env --json | jq -r .AAA" "base"

# no rollout warning at the current version (this assertion flips when the
# phase-2 warning activates in 2026.12.0 — see warn_if_auto_env_files_exist)
assert_not_contains "mise env 2>&1" "load automatically"

# opt in: all platform configs load, most specific wins (unix < os < os-arch)
MISE_AUTO_ENV=true assert "mise env --json | jq -r .AAA" "$os-$arch"
MISE_AUTO_ENV=true assert "mise env --json | jq -r .UNIX_LOADED" "1"
Comment thread
greptile-apps[bot] marked this conversation as resolved.
MISE_AUTO_ENV=true assert "mise env --json | jq -r .BBB" "base"

# explicit MISE_ENV entries take precedence over auto platform envs
MISE_AUTO_ENV=true MISE_ENV=prod assert "mise env --json | jq -r .AAA" "prod"

# explicit MISE_ENV listing a platform env dedupes (file loaded once) and
# keeps its user-specified (higher) precedence
MISE_AUTO_ENV=true MISE_ENV=$os assert "mise env --json | jq -r .AAA" "$os"
MISE_AUTO_ENV=true MISE_ENV=$os assert "mise config ls | grep -c \"mise.$os.toml\"" "1"

# explicit opt-out
MISE_AUTO_ENV=false assert "mise env --json | jq -r .AAA" "base"

# auto envs are not added to MISE_ENV itself: {{ mise_env }} and MISE_ENV
# propagation to subprocesses only reflect explicit environments
cat <<'EOF' >>mise.toml
[tasks.print]
run = '{% if mise_env %}echo {{mise_env}}{% endif %}'
EOF
MISE_AUTO_ENV=true assert "mise run print" ""
MISE_AUTO_ENV=true MISE_ENV=prod assert "mise run print" "[prod]"

# auto_env can be enabled via .miserc.toml
echo 'auto_env = true' >.miserc.toml
assert "mise env --json | jq -r .AAA" "$os-$arch"
# env var overrides .miserc.toml
MISE_AUTO_ENV=false assert "mise env --json | jq -r .AAA" "base"
rm -f .miserc.toml

# global config dir platform configs load too
mkdir -p "$MISE_CONFIG_DIR"
echo "env.GLOBAL_AUTO = \"$os\"" >"$MISE_CONFIG_DIR/config.$os.toml"
MISE_AUTO_ENV=true assert "mise env --json | jq -r .GLOBAL_AUTO" "$os"
assert "mise env --json | jq -r .GLOBAL_AUTO" "null"
rm -f "$MISE_CONFIG_DIR/config.$os.toml"
40 changes: 40 additions & 0 deletions e2e/lockfile/test_lockfile_auto_env
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#!/usr/bin/env bash

# Test that auto platform environments (auto_env) select matching
# mise.<env>.lock lockfiles, and explicit MISE_ENV lockfiles still win

export MISE_LOCKFILE=1

os="$(uname -s)"
case "$os" in
Darwin) os=macos ;;
Linux) os=linux ;;
esac

cat >"mise.$os.toml" <<'EOF'
[tools]
tiny = "2"
EOF

touch "mise.$os.lock"

assert "mise install tiny@2.1.0"

# with auto_env enabled, mise.$os.toml is active and its lockfile is written
assert "MISE_AUTO_ENV=true mise use tiny@2"
assert_contains "cat mise.$os.lock" '[[tools.tiny]]'
assert_contains "cat mise.$os.lock" 'version = "2.1.0"'

# the locked version is honored when resolving with auto_env enabled
assert "MISE_AUTO_ENV=true mise ls tiny --json | jq -r '.[0].version'" "2.1.0"

# explicit env lockfile takes precedence over the auto platform one
cat >mise.prod.toml <<'EOF'
[tools]
tiny = "1"
EOF
touch mise.prod.lock
assert "mise install tiny@1.0.1"
assert "MISE_ENV=prod mise use tiny@1"
assert_contains "cat mise.prod.lock" 'version = "1.0.1"'
assert "MISE_AUTO_ENV=true MISE_ENV=prod mise ls tiny --json | jq -r '.[0].version'" "1.0.1"
4 changes: 4 additions & 0 deletions schema/mise.json
Original file line number Diff line number Diff line change
Expand Up @@ -538,6 +538,10 @@
"type": "boolean",
"deprecated": true
},
"auto_env": {
"description": "Automatically enable platform config environments (unix, {os}, {os}-{arch}).",
"type": "boolean"
},
"auto_install": {
"default": true,
"description": "Automatically install missing tools when running `mise x`, `mise run`, or as part of the 'not found' handler.",
Expand Down
4 changes: 4 additions & 0 deletions schema/miserc.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

30 changes: 30 additions & 0 deletions settings.toml
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,36 @@ env = "MISE_ASDF_COMPAT"
hide = true
type = "Bool"

[auto_env]
description = "Automatically enable platform config environments (unix, {os}, {os}-{arch})."
docs = """
When enabled, mise treats the following as active config environments (in addition
to any explicit `MISE_ENV`): `unix` (on unix-family platforms), the OS name
(`linux`/`macos`/`windows`), and `{os}-{arch}` (e.g. `macos-arm64`, `windows-x64`,
using mise's remapped arch names: `x86_64` -> `x64`, `aarch64` -> `arm64`).

This causes config files such as `mise.windows.toml`, `mise/config.macos-arm64.toml`,
or `mise.unix.toml` to be loaded automatically, and matching `mise.<env>.lock`
lockfiles to be selected. Platform environments have lower precedence than explicit
`MISE_ENV` entries; the full precedence order is `unix` < `{os}` < `{os}-{arch}` <
explicit `MISE_ENV` entries. Platform environments do not affect the
`{{ mise_env }}` template variable or the `MISE_ENV` variable passed to subprocesses.

When unset, this currently defaults to `false`. Starting with mise 2027.6.0 it will
default to `true`; set it to `false` to keep the old behavior, or `true` to adopt
the new behavior early.

This is an early-init setting: it must be set in `.miserc.toml` or via the
`MISE_AUTO_ENV` environment variable. Setting it in `mise.toml` will have no effect
because config file discovery has already occurred by the time `mise.toml` is read.

See [Configuration Environments](/configuration/environments.html) for more details.
"""
env = "MISE_AUTO_ENV"
optional = true
rc = true
type = "Bool"

[auto_install]
default = true
description = "Automatically install missing tools when running `mise x`, `mise run`, or as part of the 'not found' handler."
Expand Down
8 changes: 8 additions & 0 deletions src/config/miserc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,11 @@ pub fn get_env() -> Option<&'static Vec<String>> {
get().env.as_ref()
}

/// Get the auto_env value from miserc, if set.
pub fn get_auto_env() -> Option<bool> {
get().auto_env
}

/// Get the ceiling_paths value from miserc, if set.
pub fn get_ceiling_paths() -> Option<&'static BTreeSet<PathBuf>> {
get().ceiling_paths.as_ref()
Expand Down Expand Up @@ -148,6 +153,9 @@ fn merge_settings(target: &mut MisercSettings, source: MisercSettings) {
if source.env.is_some() {
target.env = source.env;
}
if source.auto_env.is_some() {
target.auto_env = source.auto_env;
}
if source.ceiling_paths.is_some() {
target.ceiling_paths = source.ceiling_paths;
}
Expand Down
Loading
Loading