{"owner":"jdx","repo":"mise","hasSkills":true,"totalSkillsCount":39,"totalTokensCount":30216,"categories":["project-spec","subagent-persona","codex-rule","plugin-manifest","root-instruction","cursor-rule","anthropic-skill"],"hasMcp":false,"mcpConfig":null,"found":["docs/architecture.md",".claude/agents/test-runner.md",".codex/hooks.json","schema/mise.plugin.json",".codex/config.toml","llms.txt","AGENTS.md",".cursor/rules/conventional_commits.mdc",".cursor/rules/testing.mdc",".cursor/rules/development.mdc","crates/vfox/plugins/.luarc.json","docs/bootstrap/packages/apk.md","docs/bootstrap/packages/apt.md","docs/bootstrap/packages/brew.md","docs/bootstrap/packages/dnf.md","docs/bootstrap/packages/flatpak.md","docs/bootstrap/packages/index.md","docs/bootstrap/packages/mas.md","docs/bootstrap/packages/pacman.md","docs/bootstrap/packages/plugins.md","docs/cli/plugins/install.md","docs/cli/plugins/link.md","docs/cli/plugins/ls.md","docs/cli/plugins/ls-remote.md","docs/cli/plugins/uninstall.md","docs/cli/plugins/update.md","test/plugins/vfox-npm/README.md","crates/vfox/plugins/dummy/README.md","docs/cli/bootstrap/packages/apply.md","docs/cli/bootstrap/packages/brew.md","docs/cli/bootstrap/packages/import.md","docs/cli/bootstrap/packages/prune.md","docs/cli/bootstrap/packages/status.md","docs/cli/bootstrap/packages/upgrade.md","docs/cli/bootstrap/packages/use.md","docs/cli/bootstrap/plugins/apply.md","docs/cli/bootstrap/plugins/status.md","docs/cli/bootstrap/packages/brew/tap.md","docs/cli/bootstrap/packages/brew/untap.md"],"skills":{"docs/architecture.md":"---\ndescription: \"Find where commands, configuration, backends, tasks, environments, and bootstrap live in the mise source tree.\"\noutline: [2, 3]\n---\n\n# Codebase architecture\n\nUse this map to find the code that owns a behavior before you change it. For\nsetup, checks, and how to submit a change, see [Contributing](/contributing.html).\n\n## Library, binary, and crates {#library-binary-and-crates}\n\nThe `mise` package builds two targets. The library, `src/lib.rs`, holds\neverything except the command line: configuration, toolsets, backends, tasks,\nenvironments, and bootstrap. The binary, `src/main.rs` plus `src/cli/`, sits on\ntop of it. `src/main.rs` imports the library's root with `use mise::*`, so code\nin `src/cli/` still writes `crate::config::…`. A change confined to `src/cli/`\nrecompiles only the binary.\n\nLibrary code must not refer to `crate::cli`. When core code needs command\nbehavior, it calls a hook in\n[`src/frontend.rs`](https://github.com/jdx/mise/blob/main/src/frontend.rs),\nwhich the binary fills in at startup with `cli::register_frontend`. The hooks\ncover running `mise lock` after an install adds versions and listing subcommand\nnames for \"did you mean\" suggestions. When `cli` needs a core item, make that\nitem `pub`. The library denies `unreachable_pub`, so everything else stays\n`pub(crate)`.\n\n`cfg(test)` is set for the binary's tests but not for the library they call, so\ncore code that behaves differently under tests checks\n`mise_util::testing::in_tests()` instead.\n\nThe workspace crates under `crates/` cannot depend on the `mise` package.\n`register_util_hooks` in `src/lib.rs` gives them what they need from mise, such\nas the settings loader and the build identity used in cache keys, before\nanything else runs.\n\n| Crate                     | Contents                                                                                                   |\n| ------------------------- | ---------------------------------------------------------------------------------------------------------- |\n| `mise-util`               | Environment, directory, file, HTTP, cache, template, and `EnvDiff`/`PathEnv` helpers                       |\n| `mise-daemons`            | Daemon declarations, ports, presets, and the supervisor runtime (the toolset glue stays in `src/daemons/`) |\n| `mise-oci`                | The OCI registry client, layers, and image layout (the image builder stays in `src/oci/`)                  |\n| `mise-system`             | The bootstrap, dotfiles, and history modules                                                               |\n| `mise-config`             | The `mise.toml` declaration types, so far for `[bootstrap]`, `[dotfiles]`, and `[history]`                 |\n| `mise-system-packages`    | System package manager drivers: apt, dnf, brew, brew-cask, and more                                        |\n| `mise-ui`                 | Progress reports, prompts, and themes for the terminal                                                     |\n| `mise-settings`           | The `Settings` types, generated from `settings.toml`, and the process-wide settings cache                  |\n| `vfox`                    | The embedded Lua runtime and the hook and module interfaces for vfox plugins                               |\n| `aqua-registry`           | Parsing, package lookup, and cache formats for aqua registries                                             |\n| `mise-bootstrap`          | Bootstrap resource planning and dependency ordering                                                        |\n| `mise-lsp`                | The language server behind `mise lsp`; mise passes it `schema/mise.json` and the `mise fmt` formatter      |\n| `mise-cache-core`         | The remote task cache protocol, content-addressed storage, authentication, and transport                   |\n| `mise-shim`               | `mise-shim.exe`, the native executable that Windows shims use in the default `exe` mode                    |\n| `mise-sigstore`           | Sigstore verification helpers                                                                              |\n| `mise-tls`                | Root certificate fallback for HTTPS clients when the system trust store is empty                           |\n| `mise-agent-env`          | Detection of AI coding agents from the process environment                                                 |\n| `mise-interactive-config` | The interactive TOML editor behind `mise edit`                                                             |\n| `mise-brew-metadata`      | Homebrew formula metadata models                                                                           |\n| `mise-brew-relocation`    | Homebrew bottle placeholder and binary relocation                                                          |\n| `mise-dotenv`             | A dotenv parser with explicit control over variable substitution                                           |\n\n## Where things live {#where-things-live}\n\n| Behavior                                 | Code                                                                                                               | User docs                                        |\n| ---------------------------------------- | ------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------ |\n| Commands, flags, and help text           | `src/cli/`; `mod.rs` dispatches, and each command has a file or directory such as `use.rs`, `exec.rs`, or `tasks/` | [CLI reference](/cli/)                           |\n| What each command changes                | `src/cli/command_effects.rs`                                                                                       |                                                  |\n| Config discovery, loading, and merging   | `src/config/`; `config_file/` holds `MiseToml`, `ToolVersions`, and `IdiomaticVersionFile`                         | [mise.toml](/configuration.html)                 |\n| Settings                                 | `settings.toml`, generated into `crates/mise-settings`; loading, trust, and CLI flags in `src/config/settings.rs`  | [Settings](/configuration/settings.html)         |\n| Config file schema                       | `schema/mise.json`                                                                                                 | [mise.toml](/configuration.html)                 |\n| Tool requests, resolution, install state | `src/toolset/`                                                                                                     | [Dev tools](/dev-tools/)                         |\n| Backends                                 | `src/backend/`; the `Backend` trait is in `mod.rs` and `BackendType` in `backend_type.rs`                          | [Backends](/dev-tools/backends/)                 |\n| Core tools                               | `src/plugins/core/`                                                                                                | [Core tools](/core-tools.html)                   |\n| Plugins                                  | `src/plugins/` (asdf and vfox adapters) and `crates/vfox`                                                          | [Plugins](/plugins.html)                         |\n| Tool shorthands                          | `registry/*.toml`, compiled in by `build.rs`; lookup in `src/registry.rs`                                          | [Registry](/registry.html)                       |\n| aqua registry                            | `crates/aqua-registry`; the bundled snapshot is `vendor/aqua-registry/`, baked in by `build.rs`                    | [aqua](/dev-tools/backends/aqua.html)            |\n| Lockfile                                 | `src/lockfile.rs` and `src/lockfile/`                                                                              | [Lockfile](/dev-tools/mise-lock.html)            |\n| Environment directives                   | `src/config/env_directive/`; `EnvDiff` and `PathEnv` come from `crates/mise-util`                                  | [Environment variables](/environments/)          |\n| Shell activation                         | `src/shell/` (one file per shell), `src/hook_env.rs`, `src/cli/activate.rs`                                        | [Shell setup](/shell-setup.html)                 |\n| Shims                                    | `src/shims.rs` and `crates/mise-shim`                                                                              | [Shims](/dev-tools/shims.html)                   |\n| Templates                                | `crates/mise-util/src/tera.rs`, re-exported as `src/tera.rs`                                                       | [Tera templates](/templates.html)                |\n| Tasks                                    | `src/task/`                                                                                                        | [Tasks](/tasks/)                                 |\n| Remote task cache                        | `crates/mise-cache-core`                                                                                           | [Remote task cache](/tasks/remote-cache.html)    |\n| Bootstrap and host packages              | `src/cli/bootstrap.rs`, `crates/mise-system` (packages in `crates/mise-system-packages`), `crates/mise-bootstrap`  | [Bootstrap](/bootstrap.html)                     |\n| Dotfiles                                 | `src/cli/dotfiles/`, `crates/mise-system/src/managed_files.rs`, `crates/mise-system/src/history/`                  | [Dotfiles](/dotfiles.html)                       |\n| Daemons                                  | `src/daemons/` (toolset glue), `crates/mise-daemons`                                                               | [Daemons](/daemons.html)                         |\n| Project dependencies                     | `src/deps/`                                                                                                        | [Project dependencies](/dev-tools/deps.html)     |\n| Secrets                                  | `src/secrets/`, `src/sops.rs`, `src/agecrypt.rs`                                                                   | [Secrets](/environments/secrets/)                |\n| Caches                                   | `crates/mise-util/src/cache.rs`: `CacheManager<T>`, MessagePack with zlib, written atomically                      | [Caches](/cache-behavior.html)                   |\n| packslip manifests                       | `src/packslip.rs`, `src/backend/packslip.rs`                                                                       | [packslip](/dev-tools/backends/packslip.html)    |\n| OCI images                               | `src/oci/` (builder), `crates/mise-oci`                                                                            | [OCI images](/dev-tools/mise-oci.html)           |\n| OpenTelemetry                            | `src/otel/`                                                                                                        | [OpenTelemetry](/tasks/opentelemetry.html)       |\n| Identity install layout                  | `src/install_layout/`                                                                                              | [Install layout](/dev-tools/install-layout.html) |\n| Sandboxing                               | `src/sandbox.rs`                                                                                                   | [Sandboxing](/sandboxing.html)                   |\n| Self-update                              | `src/cli/self_update.rs`                                                                                           | [Packaging mise](/packaging.html)                |\n\n## How a command runs {#system-overview}\n\nMost commands load the configuration, resolve the tools it requests, build an\nenvironment from them, and then run a child process or print shell code. Tasks\nand bootstrap start from the same configuration.\n\n```mermaid\nflowchart TD\n    CLI[CLI command] --> Config[Configuration and settings]\n    Config --> Tools[Tool requests and backend resolution]\n    Tools --> Env[Environment and PATH]\n    Env --> Exec[Child command or shell output]\n    Config --> Tasks[Task discovery and dependency graph]\n    Tasks --> Env\n    Config --> Bootstrap[Bootstrap plan and explicit apply]\n```\n\n### Configuration {#configuration-system}\n\n[`src/config`](https://github.com/jdx/mise/tree/main/src/config) finds config\nfiles, loads them through the `ConfigFile` trait, and merges them. Which files\nare found, whether they are trusted, and how each field merges are separate\ndecisions in the code. Settings, tools, environment directives, tasks, and\nbootstrap entries do not merge the same way, and write commands pick their\n[target file](/configuration.html#target-file-for-write-operations) separately.\n\n### Toolsets {#toolset-management}\n\n[`src/toolset`](https://github.com/jdx/mise/tree/main/src/toolset) connects\nversion requests to resolved versions and installation state:\n\n| Type             | Role                                                                                  |\n| ---------------- | ------------------------------------------------------------------------------------- |\n| `ToolRequest`    | A request such as `node@24`, a channel, or a ref, with its backend and options        |\n| `ToolVersion`    | A resolved version and its installation metadata                                      |\n| `Toolset`        | The requests and resolved versions for the current context                            |\n| `ToolsetBuilder` | Combines config, environment variable overrides, and command arguments, then resolves |\n\n### Backends {#backend-system}\n\nThe [`Backend` trait](https://github.com/jdx/mise/blob/main/src/backend/mod.rs)\nsplits shared policy from backend-specific work. Its public wrapper methods\nhandle caching and resolution. A backend implements hooks such as\n`_list_remote_versions`, which returns `VersionInfo` entries, and\n`install_version_`. Core tools in `src/plugins/core/` implement the same trait.\nFor how mise picks a backend for a short name, see\n[how backend selection works](/dev-tools/backends/#how-backend-selection-works);\nto add one, see [Adding a backend](/contributing.html#adding-backends).\n\n### Plugins {#plugins}\n\n[`src/plugins`](https://github.com/jdx/mise/tree/main/src/plugins) installs\nplugin sources and records their metadata.\n[`crates/vfox`](https://github.com/jdx/mise/tree/main/crates/vfox) runs vfox\nplugins in its embedded Lua runtime. Tool plugins install one tool, backend\nplugins handle `plugin:tool` requests, environment plugins return variables and\n`PATH` entries, and package plugins manage batches of host packages. asdf\nadapters run legacy shell scripts. Installing or updating a plugin's source is\nseparate from installing a tool version, and each keeps its own state. See\n[Plugins](/plugins.html).\n\n### Tasks {#task-system}\n\n[`src/task`](https://github.com/jdx/mise/tree/main/src/task) discovers, schedules,\nand runs tasks. `Task` holds a definition, the providers in\n`task_file_providers/` load local and remote task files, `Deps` is the\ndependency graph, and the executor and scheduler run ready tasks under the\nconfigured concurrency and output style. A node in the graph is a task with its\narguments, environment variables, and run phase, so the same task with\ndifferent arguments is a separate node. Read\n[Dependencies and execution order](/tasks/architecture.html) before you change\nhow the graph is built or how `depends`, `depends_post`, and `wait_for` behave.\n\n### Environment and shell activation {#shell-integration}\n\n`src/config/env_directive` evaluates `[env]` directives. Directives marked\n`tools = true` run after tools are resolved, and the rest run before.\n`mise activate` emits a shell hook from `src/shell/` that runs `mise hook-env`\nat each prompt. `hook-env` records an `EnvDiff` so the next run can undo the previous\ndirectory's changes before applying new ones. `mise exec` and `mise run` build\nthe child environment directly and do not need activation.\n\n### Bootstrap and host state {#bootstrap-and-host-state}\n\n`src/cli/bootstrap.rs` builds a plan and runs the selected phases. The code in\n`crates/mise-system` manages packages, files, edits, repositories, services, and\nplatform-specific resources, which live outside any tool's install directory.\nStatus, preview, apply, and prune are separate operations: a status check reads\nthe host and changes nothing. A package batch can be a subset named on the\ncommand line, so never treat a package's absence from a batch as a request to\nremove it.\n\n## Rules to preserve {#rules-to-preserve}\n\n- Treat versions as opaque strings. Resolve a request through the backend\n  (`Backend::latest_version`, `Backend::list_versions_matching`,\n  `ToolRequest::resolve`), never with a semver sort at a new call site.\n- Compare lockfile versions with `==`, keep the backend and checksum of an\n  entry, and never write `latest`, `lts/*`, or a prefix into the lockfile.\n- Do not add installs or network requests to a code path that only reports\n  local state.\n- Build a subprocess's environment from the one mise computed, not the\n  inherited process environment, which can miss earlier directives or select\n  the wrong tool.\n- Include every input that changes a cached result in its cache key, such as\n  options, environment variables, and source metadata. The environment cache\n  (`src/toolset/env_cache.rs`) and the task caches (`src/task/task_cache.rs`)\n  do not use `CacheManager` and have their own formats and invalidation rules.\n- Keep Windows `PATH` in native form inside mise and in child processes.\n  Convert it only when emitting assignments into a running, positively\n  identified MSYS2 or Cygwin shell; the\n  [agent guide](https://github.com/jdx/mise/blob/main/AGENTS.md) has the full\n  rules.\n- Classify every new command in `src/cli/command_effects.rs`; see\n  [Changing a CLI command](/contributing.html#changing-a-cli-command).\n\n## Generated files {#generated-files}\n\nEdit the source, then regenerate. Commit the output with the change that\nproduced it.\n\n| Output                                                                 | Source                                                                                                                                                   | Regenerate with                               |\n| ---------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------- |\n| `mise.usage.kdl`, `docs/cli/`                                          | Command definitions in `src/cli/`, `src/assets/mise-extra.usage.kdl`, and `docs/.vitepress/cli-reference.ts`                                             | `mise run render:usage`                       |\n| `tasks.md`                                                             | The project's tasks in `tasks.toml`, `xtasks/`, and `mise.toml`, through `mise generate task-docs`                                                       | `mise run render:usage`                       |\n| `man/man1/mise.1`                                                      | `mise.usage.kdl`                                                                                                                                         | `mise run render:mangen`                      |\n| `completions/`                                                         | The usage spec, through `mise completion <shell>`                                                                                                        | `mise run render:completions`                 |\n| `docs/.vitepress/cli_commands.ts` and the idiomatic version file table | `src/cli/` and the `idiomatic_files` keys in `registry/*.toml`                                                                                           | `mise run render:help`                        |\n| `schema/mise.json`, `schema/mise-task.json`, `schema/miserc.json`      | The types and doc comments in `crates/mise-config` (`MiseTomlDecl` for the top level) and `settings.toml`, through mise-config's `render-schema` example | `mise run render:schema`                      |\n| `docs/public/llms.txt`                                                 | Page titles and leads, and `docs/.vitepress/sidebar.ts`                                                                                                  | `mise run render:llms`                        |\n| `Settings` types                                                       | `settings.toml`                                                                                                                                          | Every build (`crates/mise-settings/build.rs`) |\n| The registry compiled into mise                                        | `registry/*.toml`                                                                                                                                        | Every build (`build.rs`)                      |\n| The [settings reference](/configuration/settings.html)                 | `settings.toml`                                                                                                                                          | Every docs build                              |\n\n`mise run render` runs every `render:*` task. For the schemas, change the types\nand doc comments in `crates/mise-config`, not the JSON; a `mise-config` test\nfails while the committed files are stale.\n\n## Tests {#tests}\n\nUnit tests sit beside the code they test, E2E tests are Bash scripts under\n`e2e/` run with `mise run test:e2e`, and the Windows E2E tests under `e2e-win/`\nuse Pester. See [Testing](/contributing.html#testing) for the commands and\nprerequisites.\n",".claude/agents/test-runner.md":"---\nname: test-runner\ndescription: Use proactively to run tests and analyze failures for the current task. Returns detailed failure analysis without making fixes.\ntools: Bash, Read, Grep, Glob\ncolor: yellow\n---\n\nYou are a specialized test execution agent. Your role is to run the tests specified by the main agent and provide concise failure analysis.\n\n## Core Responsibilities\n\n1. **Run Specified Tests**: Execute exactly what the main agent requests (specific tests, test files, or full suite)\n2. **Analyze Failures**: Provide actionable failure information\n3. **Return Control**: Never attempt fixes - only analyze and report\n\n## Workflow\n\n1. Run the test command provided by the main agent\n2. Parse and analyze test results\n3. For failures, provide:\n   - Test name and location\n   - Expected vs actual result\n   - Most likely fix location\n   - One-line suggestion for fix approach\n4. Return control to main agent\n\n## Output Format\n\n```\n✅ Passing: X tests\n❌ Failing: Y tests\n\nFailed Test 1: test_name (file:line)\nExpected: [brief description]\nActual: [brief description]\nFix location: path/to/file.rb:line\nSuggested approach: [one line]\n\n[Additional failures...]\n\nReturning control for fixes.\n```\n\n## Important Constraints\n\n- Run exactly what the main agent specifies\n- Keep analysis concise (avoid verbose stack traces)\n- Focus on actionable information\n- Never modify files\n- Return control promptly after analysis\n\n## Example Usage\n\nMain agent might request:\n\n- \"Run the password reset test file\"\n- \"Run only the failing tests from the previous run\"\n- \"Run the full test suite\"\n- \"Run tests matching pattern 'user_auth'\"\n\nYou execute the requested tests and provide focused analysis.\n",".codex/hooks.json":"{\n  \"hooks\": {\n    \"PostToolUse\": [\n      {\n        \"matcher\": null,\n        \"hooks\": [\n          {\n            \"type\": \"command\",\n            \"command\": \"sh -c 'if ! command -v entire >/dev/null 2>&1; then exit 0; fi; exec entire hooks codex post-tool-use'\",\n            \"timeout\": 30\n          }\n        ]\n      }\n    ],\n    \"SessionEnd\": [\n      {\n        \"matcher\": null,\n        \"hooks\": [\n          {\n            \"type\": \"command\",\n            \"command\": \"sh -c 'if ! command -v entire >/dev/null 2>&1; then exit 0; fi; exec entire hooks codex session-end'\",\n            \"timeout\": 3\n          }\n        ]\n      }\n    ],\n    \"SessionStart\": [\n      {\n        \"matcher\": null,\n        \"hooks\": [\n          {\n            \"type\": \"command\",\n            \"command\": \"sh -c 'if ! command -v entire >/dev/null 2>&1; then printf \\\"%s\\\\n\\\" \\\"{\\\\\\\"systemMessage\\\\\\\":\\\\\\\"Entire CLI is enabled but not installed or not on PATH. Installation guide: https://docs.entire.io/cli/installation#installation-methods\\\\\\\"}\\\"; exit 0; fi; exec entire hooks codex session-start'\",\n            \"timeout\": 30\n          }\n        ]\n      }\n    ],\n    \"Stop\": [\n      {\n        \"matcher\": null,\n        \"hooks\": [\n          {\n            \"type\": \"command\",\n            \"command\": \"sh -c 'if ! command -v entire >/dev/null 2>&1; then exit 0; fi; exec entire hooks codex stop'\",\n            \"timeout\": 30\n          }\n        ]\n      }\n    ],\n    \"SubagentStart\": [\n      {\n        \"matcher\": null,\n        \"hooks\": [\n          {\n            \"type\": \"command\",\n            \"command\": \"sh -c 'if ! command -v entire >/dev/null 2>&1; then exit 0; fi; exec entire hooks codex subagent-start'\",\n            \"timeout\": 30\n          }\n        ]\n      }\n    ],\n    \"SubagentStop\": [\n      {\n        \"matcher\": null,\n        \"hooks\": [\n          {\n            \"type\": \"command\",\n            \"command\": \"sh -c 'if ! command -v entire >/dev/null 2>&1; then exit 0; fi; exec entire hooks codex subagent-stop'\",\n            \"timeout\": 30\n          }\n        ]\n      }\n    ],\n    \"UserPromptSubmit\": [\n      {\n        \"matcher\": null,\n        \"hooks\": [\n          {\n            \"type\": \"command\",\n            \"command\": \"sh -c 'if ! command -v entire >/dev/null 2>&1; then exit 0; fi; exec entire hooks codex user-prompt-submit'\",\n            \"timeout\": 30\n          }\n        ]\n      }\n    ]\n  }\n}\n","schema/mise.plugin.json":"{\n  \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n  \"$id\": \"https://mise.jdx.dev/schema/mise.plugin.json\",\n  \"title\": \"mise-plugin\",\n  \"description\": \"config file for a mise plugin\",\n  \"type\": \"object\",\n  \"unevaluatedProperties\": false,\n  \"$defs\": {\n    \"plugin-script-config\": {\n      \"type\": \"object\",\n      \"unevaluatedProperties\": false,\n      \"properties\": {\n        \"cache-key\": {\n          \"description\": \"cache the script results separately based on these values; only consumed for list-bin-paths and exec-env, accepted elsewhere\",\n          \"type\": \"array\",\n          \"items\": {\n            \"type\": \"string\"\n          }\n        },\n        \"data\": {\n          \"description\": \"static data to use instead of executing the script; only consumed for list-aliases, list-idiomatic-filenames, and list-legacy-filenames, accepted elsewhere\",\n          \"type\": \"string\"\n        }\n      }\n    }\n  },\n  \"properties\": {\n    \"list-aliases\": {\n      \"description\": \"configuration for bin/list-aliases script\",\n      \"$ref\": \"#/$defs/plugin-script-config\"\n    },\n    \"list-legacy-filenames\": {\n      \"description\": \"configuration for bin/list-legacy-filenames script\",\n      \"$ref\": \"#/$defs/plugin-script-config\"\n    },\n    \"list-idiomatic-filenames\": {\n      \"description\": \"configuration for idiomatic filename discovery\",\n      \"$ref\": \"#/$defs/plugin-script-config\"\n    },\n    \"list-bin-paths\": {\n      \"description\": \"configuration for bin/list-bin-paths script\",\n      \"$ref\": \"#/$defs/plugin-script-config\"\n    },\n    \"exec-env\": {\n      \"description\": \"configuration for bin/exec-env script\",\n      \"$ref\": \"#/$defs/plugin-script-config\"\n    },\n    \"idiomatic-filenames\": {\n      \"description\": \"legacy key from old plugins that is ignored; when present, mise stops parsing the file entirely\",\n      \"deprecated\": true\n    },\n    \"legacy-filenames\": {\n      \"description\": \"legacy key from old plugins that is ignored; when present, mise stops parsing the file entirely\",\n      \"deprecated\": true\n    },\n    \"package-manager\": {\n      \"description\": \"configuration for a package-manager plugin\",\n      \"type\": \"object\",\n      \"unevaluatedProperties\": false,\n      \"properties\": {\n        \"requires\": {\n          \"description\": \"host binaries required by the package-manager plugin\",\n          \"type\": \"array\",\n          \"items\": {\n            \"type\": \"string\"\n          }\n        },\n        \"supports_version_pins\": {\n          \"description\": \"whether the package manager supports version-pinned requests\",\n          \"type\": \"boolean\"\n        },\n        \"supports-version-pins\": {\n          \"description\": \"whether the package manager supports version-pinned requests\",\n          \"type\": \"boolean\"\n        },\n        \"os\": {\n          \"description\": \"operating systems supported by the package-manager plugin\",\n          \"type\": \"array\",\n          \"items\": {\n            \"type\": \"string\"\n          }\n        }\n      }\n    }\n  }\n}\n",".codex/config.toml":"\n[features]\nhooks = true\n\n[mcp_servers.hk]\ncommand = \"hk\"\nargs = [\"mcp\", \"--root\", \".\"]\n","llms.txt":"# mise (mise-en-place) - Development Environment Tool\n\n## What is mise?\n\nmise (pronounced \"meez\") is a development environment setup tool that manages:\n1. **Dev Tools**: Installing, pinning, and switching programming languages and tools\n2. **Environments**: Loading project-specific environment variables\n3. **Tasks**: Running project automation for build, test, lint, deploy, and everyday workflows\n\nmise supports hundreds of development tools and can automatically switch between different versions based on your project directory.\n\n## Installation\n\n### Quick Install (Linux/macOS)\n```bash\ncurl https://mise.run | sh\n```\n\n### Other Methods\n- **Homebrew**: `brew install mise`\n- **Windows**: `winget install jdx.mise` or `scoop install mise`\n- **Debian/Ubuntu**: Available via apt repository\n- **Fedora**: Available via dnf repository\n\n## Core Configuration\n\n### mise.toml\nThe main configuration file for mise. Can be named:\n- `mise.toml` (project-specific)\n- `mise.local.toml` (local, not committed to git)\n- `~/.config/mise/config.toml` (global)\n\nExample `mise.toml`:\n```toml\n[tools]\nnode = \"20\"\npython = \"3.11\"\nterraform = \"1.0.0\"\ngo = \"latest\"\n\n[env]\nNODE_ENV = \"development\"\nDATABASE_URL = \"postgresql://localhost/myapp\"\n\n[tasks.test]\nrun = \"npm test\"\ndescription = \"Run tests\"\n\n[tasks.build]\nrun = \"npm run build\"\ndeps = [\"test\"]\n```\n\n### .tool-versions (asdf compatibility)\nmise is compatible with asdf's `.tool-versions` format:\n```\nnode 20.0.0\npython 3.11.5\nterraform 1.0.0\n```\n\n## Essential Commands\n\n### Tool Management\n- `mise use node@20` - Install and set node version (updates config)\n- `mise use -g node@20` - Set global default\n- `mise install` - Install all tools from config\n- `mise install node@20` - Install specific version\n- `mise ls` - List installed tools\n- `mise ls-remote node` - List available versions\n\n### Execution\n- `mise exec node@20 -- node script.js` - Run command with specific tool version\n- `mise x node@20 -- node script.js` - Shorthand for exec\n- `mise run test` - Run defined task\n- `mise test` - Shorthand (if no command conflict)\n\n### Environment\n- `mise activate bash` - Activate mise in shell (add to .bashrc)\n- `mise activate zsh` - Activate mise in zsh (add to .zshrc)  \n- `mise activate fish` - Activate mise in fish\n- `mise env` - Show current environment\n- `mise set KEY=value` - Set environment variable\n\n### Information\n- `mise doctor` - Check mise setup\n- `mise config` - Show loaded config files\n- `mise current` - Show active tool versions\n- `mise which node` - Show path to tool\n\n## Key Concepts\n\n### Activation vs Shims vs Exec\n1. **Activation** (`mise activate`): Recommended for interactive shells. Updates PATH automatically when changing directories.\n2. **Shims**: Symlinks that intercept tool calls. Good for CI/CD and IDEs.\n3. **Exec** (`mise exec`): Run commands with mise environment without activation.\n\n### Tool Scopes\n- `node@20.1.0` - Exact version\n- `node@20` - Latest 20.x version\n- `node@latest` - Latest available version\n- `node@lts` - Latest LTS version\n- `ref:master` - Build from git ref\n- `prefix:1.19` - Latest matching prefix\n- `path:/custom/path` - Use custom installation\n\n### Configuration Hierarchy\nConfig files are loaded in order (later overrides earlier):\n1. Global: `~/.config/mise/config.toml`\n2. Parent directories: `mise.toml` files going up the tree\n3. Current directory: `mise.toml`\n4. Local: `mise.local.toml`\n\n## Tasks\n\n### TOML Tasks\n```toml\n[tasks.build]\nrun = \"cargo build\"\ndescription = \"Build the project\"\ndepends = [\"install\"]\n\n[tasks.test]\nrun = \"cargo test\"\ndepends = [\"build\"]\n```\n\n### File Tasks\nCreate executable scripts in `mise-tasks/` directory:\n```bash\n#!/usr/bin/env bash\n#MISE description=\"Run tests\"\ncargo test\n```\n\n### Task Features\n- Parallel execution by default\n- Dependency management\n- File watching (`mise watch`)\n- Environment variable passing\n\n## Environment Variables\n\n### Settings\n- `MISE_DATA_DIR` - Where tools are installed (`~/.local/share/mise`)\n- `MISE_CONFIG_DIR` - Config directory (`~/.config/mise`)\n- `MISE_CACHE_DIR` - Cache directory\n- `MISE_GITHUB_TOKEN` - GitHub token for API access\n\n### Tool-specific\n- `MISE_NODE_VERSION=20` - Override node version\n- `MISE_PYTHON_VERSION=3.11` - Override python version\n\n## Common Patterns\n\n### Project Setup\n```bash\n# Initialize project\ncd my-project\nmise use node@20 python@3.11\nmise install\n\n# Add environment variables\nmise set NODE_ENV=development\nmise set DATABASE_URL=postgresql://localhost/myapp\n```\n\n### Global Tools\n```bash\n# Set global defaults\nmise use -g node@lts python@3.11 go@latest\n```\n\n### CI/CD\n```bash\n# Install mise and tools\ncurl https://mise.run | sh\nexport PATH=\"$HOME/.local/bin:$PATH\"\nmise install\nmise run build\n```\n\n## Troubleshooting\n\n### Common Issues\n- **Rate limiting**: Set `MISE_GITHUB_TOKEN` for GitHub API access\n- **Tool not found**: Run `mise doctor` to check setup\n- **Slow performance**: Check `mise cache clear` if stale\n- **Permission errors**: Ensure proper file permissions\n\n### Debugging\n- `mise doctor` - Comprehensive health check\n- `mise config` - Show config file loading order\n- `mise env` - Show current environment\n- `mise which <tool>` - Show tool path resolution\n\n## Plugin System\n\nmise uses plugins to support different tools:\n- Compatible with asdf plugins\n- Automatic plugin installation\n- Custom plugin repositories supported\n- Plugin shortcuts in registry\n\n## Migration from asdf\n\nmise is largely compatible with asdf:\n- Reads `.tool-versions` files\n- Uses asdf plugins\n- Similar commands (with improvements)\n- Can run alongside asdf temporarily\n\n## Best Practices\n\n1. Use `mise.toml` for committed project configuration\n2. Use `mise.local.toml` for local overrides\n3. Activate mise in shell for interactive use\n4. Use shims for CI/CD and IDE integration\n5. Set `MISE_GITHUB_TOKEN` to avoid rate limits\n6. Use `mise doctor` regularly to check setup\n7. Pin versions in production environments\n8. Use tasks for project automation\n\n## Advanced Features\n\n### Tool Options\n```toml\n[tools]\nnode = { version = \"20\", postinstall = \"corepack enable\" }\npython = { version = \"3.11\", virtualenv = \"myproject\" }\n```\n\n### Hooks\n```toml\n[hooks]\nenter = \"mise install --quiet\"\nleave = \"deactivate\"\n```\n\n### Multiple Versions\n```toml\n[tools]\npython = [\"3.10\", \"3.11\", \"3.12\"]  # Install multiple versions\n```\n\n## Development & Contributing\n\n### Setting Up Development Environment\n\nmise is written in Rust and uses itself for development tasks. To contribute to mise:\n\n#### Prerequisites\n- Rust (latest stable)\n- Node.js\n- `pipx` or `uv` \n- Bash (newer than macOS default)\n\n#### Getting Started\n```bash\n# Clone the repository\ngit clone https://github.com/jdx/mise.git\ncd mise\n\n# Install dependencies and build\nmise run build\n\n# Run sanity check\nmise run build\n```\n\n#### Development Setup\nCreate a development shim to easily run mise during development:\n\n```bash\n# Create ~/.local/bin/@mise\n#!/bin/sh\nexec cargo run -q --all-features --manifest-path ~/src/mise/Cargo.toml -- \"$@\"\n```\n\nThen use `@mise` to run the development version:\n```bash\n@mise --help\neval \"$(@mise activate zsh)\"\n```\n\n### Testing\n\nmise has a comprehensive test suite with multiple types of tests to ensure reliability and functionality across different platforms and scenarios.\n\n#### Unit Tests\nUnit tests are fast, focused tests for individual components and functions:\n\n```bash\n# Run all unit tests\ncargo test --all-features\n\n# Run specific unit tests\ncargo test <test_name>\n\n# Run tests with verbose output\ncargo test --all-features -- --nocapture\n\n# Run tests in series (not parallel)\nRUST_TEST_THREADS=1 cargo test --all-features\n```\n\n**Unit test structure:**\n- Located in `src/` directory alongside source code\n- Use Rust's built-in test framework\n- Test individual functions and modules\n- Fast execution (used for quick feedback during development)\n\n#### E2E Tests\nEnd-to-end tests validate the complete functionality of mise in realistic scenarios:\n\n```bash\n# Run all E2E tests\nmise run test:e2e\n\n# Run specific E2E test\n./e2e/run_test test_name\n\n# Run E2E tests matching pattern\n./e2e/run_test task  # runs tests matching *task*\n\n# Run all tests including slow ones\nTEST_ALL=1 mise run test:e2e\n```\n\n**E2E test structure:**\n- Located in `e2e/` directory\n- Organized by functionality:\n  - `e2e/cli/` - Command-line interface tests\n  - `e2e/core/` - Core functionality tests\n  - `e2e/env/` - Environment variable tests\n  - `e2e/tasks/` - Task runner tests\n  - `e2e/config/` - Configuration tests\n  - `e2e/tools/` - Tool management tests\n  - `e2e/shell/` - Shell integration tests\n  - `e2e/backend/` - Backend tests\n  - `e2e/plugins/` - Plugin tests\n\n**E2E test categories:**\n- **Fast tests** (`test_*`): Run in normal test suites\n- **Slow tests** (`test_*_slow`): Only run when `TEST_ALL=1` is set\n- **Isolated environment**: Each test runs in a clean, isolated environment\n\n#### Coverage Tests\nCoverage tests measure how much of the codebase is covered by tests:\n\n```bash\n# Run coverage tests\nmise run test:coverage\n\n# Coverage tests run in parallel tranches for CI\nTEST_TRANCHE=0 TEST_TRANCHE_COUNT=8 mise run test:coverage\n```\n\n#### Windows E2E Tests\nWindows has its own test suite written in PowerShell:\n\n```powershell\n# Run all Windows E2E tests\npwsh e2e-win\\run.ps1\n\n# Run specific Windows tests\npwsh e2e-win\\run.ps1 task  # run tests matching *task*\n```\n\n#### Plugin Tests\nTest plugin functionality across different backends:\n\n```bash\n# Test specific plugin\nmise test-tool ripgrep\n\n# Test all plugins in registry\nmise test-tool --all\n\n# Test all plugins in config files\nmise test-tool --all-config\n\n# Test with parallel jobs\nmise test-tool --all --jobs 4\n```\n\n#### Test Environment Setup\nTests run in isolated environments to avoid conflicts:\n\n```bash\n# Disable mise during development testing\nexport MISE_DISABLE_TOOLS=1\n\n# Run tests with specific environment\nMISE_TRUSTED_CONFIG_PATHS=$PWD cargo test\n```\n\n#### Test Assertions\nThe E2E tests use a custom assertion framework (`e2e/assert.sh`):\n\n```bash\n# Basic assertions\nassert \"command\" \"expected_output\"\nassert_contains \"command\" \"substring\"\nassert_fail \"command\" \"expected_error\"\n\n# JSON assertions\nassert_json \"command\" '{\"key\": \"value\"}'\nassert_json_partial_array \"command\" \"fields\" '[{...}]'\n\n# File/directory assertions\nassert_directory_exists \"/path/to/dir\"\nassert_directory_not_exists \"/path/to/dir\"\nassert_empty \"command\"\n```\n\n#### Running Specific Test Categories\n\n```bash\n# Run all tests (unit + e2e)\nmise run test\n\n# Run only unit tests\nmise run test:unit\n\n# Run only e2e tests\nmise run test:e2e\n\n# Run tests with shuffle (for detecting order dependencies)\nmise run test:shuffle\n\n# Run nightly tests (with bleeding edge Rust)\nrustup default nightly && mise run test\n```\n\n#### Running Single Tests\n\n**Unit Tests:**\n```bash\n# Run a specific unit test by name\ncargo test test_name\n\n# Run tests matching a pattern\ncargo test pattern\n\n# Run tests in a specific module\ncargo test module_name\n\n# Run a single test with output\ncargo test test_name -- --nocapture\n\n# Run a single test file (if organized by file)\ncargo test --test test_file_name\n```\n\n**E2E Tests:**\n```bash\n# Run a specific E2E test by name\n./e2e/run_test test_name\n\n# Run E2E tests matching a pattern\nmise run test:e2e pattern\n\n# Examples:\n./e2e/run_test test_use                    # Run specific test\n./e2e/run_test test_config_set            # Run config-related test\nmise run test:e2e task                     # Run all tests matching \"task\"\n```\n\n**Plugin Tests:**\n```bash\n# Test a specific plugin\nmise test-tool ripgrep\n\n# Test a plugin with verbose output\nmise test-tool ripgrep --raw\n\n# Test multiple plugins\nmise test-tool ripgrep jq terraform\n```\n\n**Windows Tests:**\n```powershell\n# Run a specific Windows test\npwsh e2e-win\\run.ps1 -TestName \"test_name\"\n\n# Run tests matching a pattern\npwsh e2e-win\\run.ps1 task\n```\n\n#### Test Development Tips\n\n1. **Test naming**: Use descriptive names that explain what's being tested\n2. **Test isolation**: Each test should be independent and clean up after itself\n3. **Use slow tests sparingly**: Mark long-running tests as `_slow` to avoid CI timeouts\n4. **Mock external dependencies**: Use dummy plugins and mock data when possible\n5. **Test edge cases**: Include tests for error conditions and boundary cases\n\n#### Performance Testing\n```bash\n# Run performance benchmarks\nmise run test:perf\n\n# Build performance test workspace\nmise run test:build-perf-workspace\n```\n\n#### Snapshot Testing\nUsed for testing output consistency:\n\n```bash\n# Update test snapshots when output changes\nmise run snapshots\n\n# Use cargo-insta for snapshot testing\ncargo insta test --accept --unreferenced delete\n```\n\n### Available Development Tasks\n\nUse `mise tasks` to see all available development tasks:\n\n#### Common Tasks\n- `mise run build` - Build the project\n- `mise run test` - Run all tests (unit + E2E)\n- `mise run test:unit` - Run unit tests only\n- `mise run test:e2e` - Run E2E tests only\n- `mise run lint` - Run linting\n- `mise run lint:fix` - Run linting with fixes\n- `mise run format` - Format code\n- `mise run clean` - Clean build artifacts\n- `mise run snapshots` - Update test snapshots\n- `mise run render` - Generate documentation and completions\n\n#### Documentation Tasks\n- `mise run docs` - Start documentation development server\n- `mise run docs:build` - Build documentation\n- `mise run render:help` - Generate help documentation\n- `mise run render:completions` - Generate shell completions\n\n#### Release Tasks\n- `mise run ci` - Run CI tasks (format, build, test)\n\n### Project Structure\n\n```\nmise/\n├── src/           # Main Rust source code\n├── e2e/           # End-to-end tests\n├── docs/          # Documentation\n├── tasks.toml     # Development tasks\n├── mise.toml      # Project configuration\n├── Cargo.toml     # Rust project configuration\n└── xtasks/        # Additional build scripts\n```\n\n### Pre-commit Hooks & Code Quality\n\nmise uses multiple approaches for ensuring code quality and running pre-commit hooks:\n\n#### hk (Modern Hook Manager)\nmise uses [hk](https://hk.jdx.dev) (pronounced \"hook\") as its primary hook manager for linting and code quality checks. hk is a modern alternative to lefthook written by the same author as mise.\n\n**hk Configuration:**\nThe project uses `hk.pkl` (written in the Pkl configuration language) to define linting rules:\n\n```bash\n# Run all linting checks\nhk check --all\n\n# Run linting with fixes\nhk fix --all\n\n# Run specific linter\nhk check --step shellcheck\n```\n\n**Available Linters in hk:**\n- **prettier**: Code formatting for multiple languages\n- **clippy**: Rust linting with `cargo clippy`\n- **shellcheck**: Shell script linting\n- **shfmt**: Shell script formatting\n\n**Using hk in Development:**\n```bash\n# Install hk via mise\nmise use hk\n\n# Run linting (used in CI and pre-commit)\nmise run lint  # This runs hk check --all\n\n# Run linting with fixes\nhk fix --all\n\n# Check specific file types\nhk check --step prettier\nhk check --step shellcheck\n```\n\n#### Traditional Pre-commit Hooks (Alternative)\nmise also supports traditional pre-commit hooks through multiple methods:\n\n**Option 1: Using lefthook (Legacy)**\n```bash\n# Install lefthook\nmise use lefthook\n\n# Install the git hooks\nlefthook install\n\n# Run pre-commit manually\nlefthook run pre-commit\n```\n\n**Option 2: Using standard pre-commit framework**\n```bash\n# Install pre-commit\nmise use pre-commit\n\n# Install the git hooks\npre-commit install\n\n# Run pre-commit manually\npre-commit run --all-files\n```\n\n**Option 3: Using mise's built-in git hook generation**\n```bash\n# Generate a git pre-commit hook that runs mise tasks\nmise generate git-pre-commit --write --task=pre-commit\n\n# This creates .git/hooks/pre-commit that runs:\n# mise run pre-commit\n```\n\n#### Pre-commit Task Configuration\nmise defines a `pre-commit` task that runs the main linting checks:\n\n```toml\n[pre-commit]\nenv = { PRE_COMMIT = 1 }\nrun = [\"mise run lint\"]\n```\n\nThis task:\n1. Sets `PRE_COMMIT=1` environment variable\n2. Runs `mise run lint`, which executes `hk check --all`\n\n#### Setting Up Pre-commit Hooks\n**Recommended approach using hk:**\n```bash\n# Install hk\nmise use hk\n\n# Set up git hook to run mise's pre-commit task\nmise generate git-pre-commit --write --task=pre-commit\n\n# Or manually create .git/hooks/pre-commit:\ncat > .git/hooks/pre-commit << 'EOF'\n#!/bin/sh\nexec mise run pre-commit\nEOF\nchmod +x .git/hooks/pre-commit\n```\n\n**Alternative approach using standard pre-commit:**\n```bash\n# Install pre-commit\nmise use pre-commit\n\n# Install hooks defined in .pre-commit-config.yaml\npre-commit install\n```\n\n#### Running Pre-commit Checks Manually\n```bash\n# Run all pre-commit checks\nmise run pre-commit\n\n# Run specific linting checks\nmise run lint\n\n# Run linting with fixes\nhk fix --all\n\n# Run checks on specific files\nhk check --files=\"src/**/*.rs\"\n```\n\n#### Environment Variables for Hooks\nWhen hooks run, they have access to these environment variables:\n- `PRE_COMMIT=1`: Indicates the code is running in pre-commit context\n- `STAGED`: Git staged files (when using mise's git hook generation)\n- `MISE_PRE_COMMIT=1`: Set by mise's generated git hooks\n\n### Testing Configuration\n\n- **Unit tests**: Fast tests for individual components\n- **E2E tests**: Integration tests that test the full application\n- **Slow tests**: Only run with `TEST_ALL=1` environment variable\n- **Windows tests**: Separate PowerShell-based test suite\n\n### Development Tips\n\n1. **Disable mise during development**: If you use mise in your shell, disable it when running tests to avoid conflicts\n2. **Use dev container**: Docker setup available (currently needs fixing)\n3. **Test specific features**: Use `cargo test <test_name>` for targeted testing\n4. **Update snapshots**: Use `mise run snapshots` when changing test outputs\n5. **Rate limiting**: Set `MISE_GITHUB_TOKEN` to avoid GitHub API rate limits during development\n\n### Dependency Management\n\nmise uses several tools to validate dependencies and code quality:\n\n- **cargo-deny**: Validates licenses, security advisories, and dependency duplicates\n- **cargo-msrv**: Verifies minimum supported Rust version compatibility\n- **cargo-machete**: Detects unused dependencies in Cargo.toml\n\nThese checks run automatically in CI and can be run locally:\n```bash\n# Install tools\nmise use cargo-deny cargo-msrv cargo-machete\n\n# Run checks\ncargo deny check\ncargo msrv verify\ncargo machete --with-metadata\n```\n\n### Contributing Guidelines\n\n1. **Before starting**: File an issue or discuss in Discord for non-obvious changes\n2. **Look for issues**: Check \"help wanted\" and \"good first issue\" labels\n3. **Test thoroughly**: Ensure both unit and E2E tests pass\n4. **Follow conventions**: Use existing code style and patterns\n5. **Update documentation**: Add/update docs for new features\n\n#### Pull Request Workflow\n1. **PR titles**: Must follow conventional commit format (validated automatically)\n2. **Auto-formatting**: Code will be automatically formatted by autofix.ci\n3. **CI checks**: All tests must pass across Linux, macOS, and Windows\n4. **Coverage**: New code should maintain or improve test coverage\n5. **Dependencies**: New dependencies are validated with cargo-deny\n\n#### GitHub Actions Development\nIf modifying GitHub Actions workflows:\n- Run `mise run lint` for the repository's configured checks\n- Self-hosted runners are configured for performance testing\n- Run the zizmor workflow for security auditing\n\n### Conventional Commits\n\nmise uses [Conventional Commits](https://www.conventionalcommits.org/) for consistent commit messages and automated changelog generation. All commits should follow this format:\n\n```\n<type>[optional scope]: <description>\n\n[optional body]\n\n[optional footer(s)]\n```\n\n#### Commit Types\n\n- **feat**: New features (🚀 Features)\n- **fix**: Bug fixes (🐛 Bug Fixes)\n- **refactor**: Code refactoring (🚜 Refactor)\n- **doc**: Documentation changes (📚 Documentation)\n- **style**: Code style changes (🎨 Styling)\n- **perf**: Performance improvements (⚡ Performance)\n- **test**: Testing changes (🧪 Testing)\n- **chore**: Maintenance tasks, dependency updates\n- **revert**: Reverting previous changes (◀️ Revert)\n\n#### Examples\n\n```bash\nfeat(cli): add new command for listing plugins\nfix(parser): handle edge case in version parsing\nrefactor(config): simplify configuration loading logic\ndoc(readme): update installation instructions\ntest(e2e): add tests for new plugin functionality\nchore(deps): update dependencies to latest versions\n```\n\n#### Scopes\n\nCommon scopes used in mise:\n- `cli` - Command line interface changes\n- `config` - Configuration system changes\n- `parser` - Parsing logic changes\n- `deps` - Dependency updates\n- `security` - Security-related changes\n\n#### Breaking Changes\n\nFor breaking changes, add `!` after the type or include `BREAKING CHANGE:` in the footer:\n\n```bash\nfeat(api)!: remove deprecated configuration options\n# OR\nfeat(api): remove deprecated configuration options\n\nBREAKING CHANGE: The old configuration format is no longer supported\n```\n\n### Packaging Testing\n\nFor testing package installation:\n\n#### Ubuntu/Debian\n```bash\n# Test apt installation\ndocker run -ti --rm ubuntu\napt update -y && apt install -y curl\n# ... installation steps\n```\n\n#### Fedora\n```bash\n# Test dnf installation  \ndocker run -ti --rm fedora\ndnf install -y dnf-plugins-core\n# ... installation steps\n```\n\n### CI/CD & Pull Request Automation\n\nmise uses several automated workflows to maintain code quality and streamline development:\n\n#### Automated Code Formatting\n- **autofix.ci**: Automatically formats code and fixes linting issues in PRs\n- Runs `mise run render` and `mise run lint-fix` automatically\n- Commits fixes directly to the PR branch\n\n#### PR Title Validation\n- **semantic-pr-lint**: Validates PR titles follow conventional commit format\n- PR titles must match: `<type>[optional scope]: <description>`\n- Example: `feat(cli): add new command for listing plugins`\n\n#### Continuous Integration\n- **Cross-platform testing**: Ubuntu, macOS, and Windows\n- **Unit tests**: Fast component-level tests\n- **E2E tests**: Full integration testing with multiple test tranches\n- **Coverage testing**: Code coverage across 8 parallel test runs\n- **Dependency validation**: `cargo deny`, `cargo msrv`, `cargo machete`\n\n#### Release Automation\n- **release-plz**: Automated release management based on conventional commits\n- Automatically creates release PRs and publishes releases\n- Runs daily via scheduled workflow\n- Handles version bumping and changelog generation\n\n## mise Codebase Architecture\n\n### Overview\n\nmise is a Rust-based tool with a modular architecture designed around three main concepts:\n1. **Tool Version Management** - Managing different versions of development tools\n2. **Environment Management** - Setting up environment variables and project contexts\n3. **Task Running** - Executing project tasks with dependency management\n\n### Core Architecture Components\n\n#### 1. **Main Entry Point** (`src/main.rs`)\n- Asynchronous Tokio runtime with multi-threading\n- Global error handling and panic hooks\n- CLI argument parsing and routing\n- Multi-progress reporting system\n\n#### 2. **CLI Layer** (`src/cli/`)\n- **Command Structure**: Each command is a separate module (e.g., `install.rs`, `use.rs`, `run.rs`)\n- **Argument Parsing**: Uses `clap` for command-line argument handling\n- **Command Execution**: Async command execution with proper error handling\n- **Key Commands**:\n  - `install` - Install tool versions\n  - `use` - Add tools to configuration\n  - `run` - Execute tasks\n  - `env` - Environment management\n  - `shell` - Shell integration\n\n#### 3. **Backend System** (`src/backend/`)\nThe backend system is the core abstraction for tool management:\n\n**Backend Trait**: Common interface for all tool backends\n```rust\npub trait Backend: Debug + Send + Sync {\n    async fn list_remote_versions(&self) -> Result<Vec<String>>;\n    async fn install_version(&self, ctx: &InstallContext, tv: &ToolVersion) -> Result<()>;\n    async fn uninstall_version(&self, tv: &ToolVersion) -> Result<()>;\n    // ... other methods\n}\n```\n\n**Backend Types**:\n- **Core Backends**: Built-in support (Node.js, Python, etc.)\n- **ASDF Backends**: External plugin system compatibility\n- **Aqua Backends**: Package manager integration\n- **Language-specific**: npm, cargo, pipx, gem, go, etc.\n- **Universal**: ubi (GitHub releases)\n\n#### 4. **Configuration System** (`src/config/`)\n**Hierarchical Configuration**:\n- `Config` struct manages all configuration sources\n- `ConfigFile` trait for different config formats:\n  - `MiseToml` - Main configuration format\n  - `ToolVersions` - ASDF compatibility\n  - `IdiomaticVersion` - Language-specific files (`.nvmrc`, `.python-version`)\n\n**Configuration Hierarchy**:\n1. System config (`/etc/mise/config.toml`)\n2. Global config (`~/.config/mise/config.toml`)\n3. Project configs (searched up directory tree)\n4. Environment-specific configs (`mise.dev.toml`)\n\n#### 5. **Toolset Management** (`src/toolset/`)\n**Core Components**:\n- `Toolset` - Collection of tools for a specific context\n- `ToolVersion` - Represents a specific version of a tool\n- `ToolRequest` - User request for a tool (e.g., `node@18`)\n- `ToolsetBuilder` - Constructs toolsets from configuration\n\n**Tool Resolution Flow**:\n1. Parse configuration files\n2. Resolve version specifications\n3. Build toolset with dependencies\n4. Install missing tools\n5. Set up environment\n\n#### 6. **Task System** (`src/task/`)\n**Task Components**:\n- `Task` struct with metadata, dependencies, and execution info\n- `Deps` - Dependency graph management using petgraph\n- `TaskFileProvider` - Discovers tasks from files and configuration\n- Parallel execution with dependency resolution\n\n**Task Types**:\n- **TOML Tasks**: Defined in `mise.toml`\n- **File Tasks**: Executable scripts in task directories\n- **Command Tasks**: Simple command execution\n- **Script Tasks**: Inline script execution\n\n#### 7. **Plugin System** (`src/plugins/`)\n**Plugin Architecture**:\n- `Plugin` trait for extensibility\n- `AsdfPlugin` - ASDF plugin compatibility\n- `VfoxPlugin` - Vfox plugin system\n- `ScriptManager` - Manages plugin scripts\n\n**Plugin Types**:\n- **Core Plugins**: Built into mise\n- **External Plugins**: Downloaded from repositories\n- **Local Plugins**: Custom local implementations\n\n#### 8. **Shell Integration** (`src/shell/`)\n**Shell Support**:\n- Bash, Zsh, Fish, PowerShell support\n- `Shell` trait for shell-specific behavior\n- Activation scripts for environment setup\n- Hook system for directory changes\n\n#### 9. **Environment Management** (`src/env*.rs`)\n**Environment Components**:\n- `EnvDiff` - Tracks environment changes\n- `EnvDirective` - Configuration for environment variables\n- `PathEnv` - PATH management\n- Context-aware environment resolution\n\n#### 10. **Caching System** (`src/cache.rs`)\n**Cache Management**:\n- `CacheManager` - Generic caching with TTL\n- File-based caching for versions, metadata\n- Automatic cache invalidation\n- Per-backend cache isolation\n\n### Key Design Patterns\n\n#### 1. **Trait-Based Architecture**\n- `Backend` trait for tool management\n- `ConfigFile` trait for configuration formats\n- `Shell` trait for shell integration\n- `Plugin` trait for extensibility\n\n#### 2. **Async/Await Throughout**\n- Tokio runtime for async operations\n- Parallel tool installations\n- Concurrent task execution\n- Non-blocking I/O operations\n\n#### 3. **Error Handling**\n- `eyre` crate for error management\n- Structured error types\n- Context-aware error reporting\n- Graceful fallback behavior\n\n#### 4. **Configuration Hierarchy**\n- Multiple configuration sources\n- Inheritance and overrides\n- Environment-specific configurations\n- Validation and trust system\n\n#### 5. **Dependency Management**\n- Tool dependencies (e.g., Node.js for npm tools)\n- Task dependencies with DAG resolution\n- Parallel execution with proper ordering\n- Circular dependency detection\n\n### Data Flow\n\n1. **Initialization**: Load configuration hierarchy\n2. **Tool Discovery**: Find available backends and versions\n3. **Resolution**: Resolve tool requests to specific versions\n4. **Installation**: Install missing tools in dependency order\n5. **Environment Setup**: Configure PATH and environment variables\n6. **Execution**: Run tasks or provide shell integration\n\n### Testing Architecture\n\n**Test Structure**:\n- **Unit Tests**: Component-level testing with mocks\n- **Integration Tests**: End-to-end CLI testing\n- **E2E Tests**: Real-world scenario testing\n- **Snapshot Tests**: Output comparison testing\n\n**Test Organization**:\n- `src/` - Unit tests alongside source code\n- `e2e/` - End-to-end test scripts\n- `test/` - Test fixtures and utilities\n- `src/snapshots/` - Snapshot test data\n\nThis architecture provides a flexible, extensible foundation for managing development environments while maintaining compatibility with existing tools and workflows.\n\nThis covers the essential information about mise for LLMs to help users effectively use the tool for development environment management and contribute to its development.\n","AGENTS.md":"# Repository Agent Guide\n\nThis file is the canonical agent guide. `CLAUDE.md` is a symlink to `AGENTS.md` for compatibility with existing tooling.\n\nTask-specific procedures live as skills in `.agents/skills/` (`.claude/skills` is a symlink to it). Load the named skill when this guide points to one; agents without skill support can read its `SKILL.md` directly.\n\n## Discussions and Issues: Restricted AI Replies\n\n**Do not use AI to reply to a mise Discussion or Issue unless the user (a) created that Discussion or Issue, (b) opened a PR that fixes it, or (c) has already had a contribution merged into the default branch of mise.** Otherwise they are not allowed to use AI to respond to it. Drive-by AI replies are spam, the problem is getting worse, and **doing it is an instant ban across all of jdx's projects** (mise, hk, pitchfork, usage, fnox, and the rest).\n\n- If the user asks you to answer, comment on, or \"help with\" a Discussion or Issue, confirm one of the three conditions first. If you cannot confirm one, **do not post**.\n  - (a) Compare the thread author to the authenticated user (`gh api user --jq .login`). For an Issue, use `gh api repos/jdx/mise/issues/<number> --jq .user.login`. Discussions have no REST endpoint, so use GraphQL: `gh api graphql -f query='query{repository(owner:\"jdx\",name:\"mise\"){discussion(number:<number>){author{login}}}}' --jq .data.repository.discussion.author.login`.\n  - (b) Check that the user's PR actually fixes the problem described in the thread. A closing keyword such as `Fixes #<number>` is good evidence, but a link is not required, and a PR that merely mentions an unrelated thread does not count.\n  - (c) Look for any contribution merged into the default branch that is tied to the user's GitHub account, not just a matching name or email: a PR authored by the user that was merged into the default branch (`gh pr list --repo jdx/mise --author @me --state merged --base main --limit 1`), commits on the default branch that GitHub attributes to their login (`gh api 'repos/jdx/mise/commits?author=<login>&per_page=1'` lists the default branch), never commits on a local or unmerged branch, or a PR from someone else, merged into the default branch, that credits them with a `Co-authored-by` trailer whose email is their GitHub noreply address or one verified on their account. Do not accept `git log --author` output, which includes local unmerged commits, or a trailer matched only by display name. Both queries filter by author on the server, so one matching result is enough to qualify and no pagination is needed.\n- If none of the three apply, **do not post a reply, even a short one.** Tell them this project does not allow AI replies from people who have not contributed, and offer to explain the answer to them in chat instead.\n- Never batch-post, loop over, or sweep Discussions or Issues to answer several of them, even for a merged contributor.\n- Lightly edited, human-reviewed, or disclosed model output does not create an exception. The disclosure footer does not make an AI reply acceptable on its own.\n- Permitted replies may be AI-assisted. The user must review and verify the reply before it is posted.\n- Creating a new Discussion or Issue with AI assistance is fine and is not restricted. The user must review it before it is posted, and it needs the AI disclosure below.\n\nWhen you post AI-contributed GitHub content, including a new Discussion or Issue, a reply, or a PR description or comment, append this disclosure: `*AI-assisted — Tool: <tool>; model: <provider>/<model>; version: <version-or-unavailable>.*` Use the exact model and version identifiers exposed by the runtime, never guessed values, and `unavailable` when one is not exposed.\n\n## Registry Submissions: READ THIS FIRST\n\n**Most new registry additions from agents get rejected.** mise's `registry/` is curated for tools that are already widely used — generally thousands of GitHub stars, not hundreds. jdx closes PRs that miss the bar without giving a reason.\n\nBefore adding a **new** tool or shorthand to `registry/`, follow the `registry-submission` skill ([`.agents/skills/registry-submission/SKILL.md`](.agents/skills/registry-submission/SKILL.md)). In short:\n\n- Warn the user about the bar, look up real popularity numbers, and stop if the tool is personal, internal, a fork, or niche.\n- Put a `## Popularity` section with those numbers in the PR description.\n- Confirm `mise ls-remote <backend>` lists installable versions.\n- Prefer `packslip:`, then `aqua:`, `github:`, or `gitlab:`. `conda:` has a high bar; `npm:`, `pipx:`, `gem:`, `cargo:`, `go:`, and `dotnet:` are almost never accepted. New `asdf:`, `vfox:`, and `ubi:` entries are not accepted.\n- Users can install any tool without a registry entry (`mise use github:owner/repo`, `mise use cargo:name`, …); the registry only adds a shorthand.\n\nNone of this applies to editing an existing registry entry; do not ask the user about popularity for maintenance or fixes.\n\n## Development Commands\n\n### Building and Testing\n- `mise run build` or `mise run b` - Build the project with cargo\n- `target/debug/mise` - Run the built binary directly\n- `mise run test` or `mise run t` - Run all tests (unit + e2e)\n- `mise run test:unit` - Run unit tests only\n- `mise run test:e2e` - Run end-to-end tests only\n- `mise run snapshots` - Update test snapshots with `cargo insta`\n\n### Debugging\n- Use `MISE_DEBUG=1` or `MISE_TRACE=1` environment variables to enable debug output (not `RUST_LOG`)\n\n### Code Quality and Testing\n- `mise run lint` - Run all linting tasks (hk; does not run clippy — see below)\n- `mise run lint-fix` - Run linting and automatically fix issues\n- `mise run format` - Format code (part of CI task)\n- `mise run ci` - Run format, build, and test\n- `mise run test:e2e [test_filename]...` - Run specific e2e tests (use this instead of executing test files directly)\n- `mise --cd crates/vfox run test` - Run tests for the vfox crate\n- `mise --cd crates/vfox run lint` - Run linting for the vfox crate\n- `mise --cd crates/vfox run lint-fix` - Run linting and fix issues for the vfox crate\n- `mise task ls` - List all available tasks\n\n### Clippy Exclusions\n\n- Do not add `#[allow(clippy::...)]`, `#[expect(clippy::...)]`, Cargo lint levels set to `allow`, or `-A clippy::...` command-line flags.\n- Refactor the code so `cargo clippy --workspace --all-features --all-targets -- -D warnings` passes without exclusions.\n- `mise run lint` does not cover this: the clippy step in `hk.pkl` is disabled, and `cargo check` does not enforce `-D warnings`. CI runs clippy separately, so run the command above yourself before pushing Rust changes.\n- If a feature or fix needs a preparatory refactor to satisfy Clippy cleanly, put that refactor in a prerequisite PR and stack the behavior change on top of it.\n\n### Documentation and Generation\n- `mise run render` - Generate all documentation and completions\n- `mise run render:usage` - Generate CLI usage documentation\n- `mise run render:completions` - Generate shell completions\n- `mise run docs` - Start documentation dev server\n- `mise run docs:build` - Build documentation\n\n### Development\n- `mise run install-dev` - Install development version locally\n- `mise run clean` - Clean cargo build artifacts\n\n## Code Architecture\n\n### High-Level Structure\nMise is a Rust CLI tool that manages development environments, tools, tasks, and environment variables. The codebase follows a modular architecture:\n\nThe `mise` package has two targets. The library (`src/lib.rs`) is everything except the command line; the binary (`src/main.rs` plus `src/cli/`) sits on top of it and glob-imports its root, so `cli` code still writes `crate::config::…`. An edit under `src/cli/` recompiles only the binary. Core code must not refer to `crate::cli`: it reaches command behavior through the hooks in `src/frontend.rs`. When `cli` needs a core item, make that item `pub`; `unreachable_pub` keeps everything else `pub(crate)`. `cfg(test)` does not reach the library from the binary's tests, so core code that behaves differently under tests checks `mise_util::testing::in_tests()` instead.\n\n**Core Components:**\n- `src/main.rs` - Binary entry point\n- `src/lib.rs` - Library root: module list and the hooks lower crates need\n- `src/cli/` - Command-line interface implementation with subcommands (binary only)\n- `src/config/` - Configuration file parsing and management\n- `src/backend/` - Tool backend implementations (aqua, github, cargo, npm, asdf, vfox, …)\n- `src/toolset/` - Tool version management and installation logic\n- `src/task/` - Task execution system\n- `src/plugins/` - Plugin system for extending tool support\n\n**Key Backend Systems** (`src/backend/`):\n- `packslip.rs` — Signed release manifests (preferred for new registry entries)\n- `aqua.rs` — Aqua registry\n- `github.rs` — GitHub / GitLab / Forgejo releases\n- `http.rs`, `s3.rs` — HTTP and S3 backends\n- `cargo.rs`, `npm.rs` (plus embedded aube), `pipx.rs`, `gem.rs`, `go.rs`, `dotnet.rs`, `conda.rs`, `spm.rs`\n- `asdf.rs`, `vfox.rs` — plugin compatibility layers\n- `ubi.rs` — deprecated; do not add new registry entries\n\n**Core Tools (Built-in):**\n- `src/plugins/core/` — Node, Python, Go, Ruby, Java, Bun, Deno, Elixir, Erlang, Dotnet, Swift, Zig, Rust\n\n**Configuration System:**\n- `mise.toml` files for project configuration\n- `.tool-versions` files for ASDF compatibility\n- Environment variable management and templating\n- Task definition and execution\n\n### Key Design Patterns\n1. **Backend Architecture**: Tools are implemented through a unified backend interface, allowing multiple sources (ASDF plugins, vfox plugins, cargo, npm, etc.)\n2. **Toolset Management**: The `Toolset` manages collections of tool versions and their installation state\n3. **Configuration Layering**: Config files are loaded hierarchically from system → global → local with environment-specific overrides\n4. **Task System**: Tasks can be defined in TOML files with dependencies, environment variables, and multiple execution modes\n\n### Configuration Files\n- `mise.toml` - Main configuration file format\n- `settings.toml` - Global settings definitions (generates code/docs)\n- `registry/` - Tool registry mappings\n- `tasks.toml` - Project task definitions\n\n### Test Structure\n- Unit tests within source files\n- E2E tests in `e2e/` directory organized by feature area (e.g., `e2e/cli/`, `e2e/backend/`)\n- E2E tests are bash scripts using assertion helpers from `e2e/assert.sh` (e.g., `assert`, `assert_contains`, `assert_fail`)\n- E2E tests do not need cleanup steps (rm, etc.) — the test harness handles that\n- Snapshot tests using `insta` crate for CLI output verification\n- Windows-specific tests in `e2e-win/`\n\n### Build System\n- Rust project using a Cargo workspace; member crates live in `crates/` (`vfox`, `aqua-registry`, `mise-shim`, `mise-sigstore`, `mise-cache-core`, `mise-tls`, `mise-brew-relocation`, `mise-brew-metadata`, `mise-agent-env`, `mise-interactive-config`, `mise-settings`, `mise-util`, `mise-ui`, `mise-system-packages`, `mise-config`, `mise-system`, `mise-oci`, `mise-daemons`, `mise-lsp`)\n- Custom build script in `build.rs` for generating metadata\n- Multiple build profiles including `release` and `serious` (with LTO)\n- Cross-compilation support via `Cross.toml`\n\n## Development Guidelines\n\n### Conventional Commits (REQUIRED)\nPR titles MUST follow conventional commit format. Intermediate commit subjects\nSHOULD use the same format:\n\n**Format:** `<type>[optional scope][optional !]: <description>`\n\n**Types:**\n- `feat:` - New features\n- `fix:` - Bug fixes that affect the CLI behavior (not CI, docs, or infrastructure)\n- `refactor:` - Code refactoring\n- `docs:` - Documentation changes\n- `style:` - Code style/formatting (no logic changes)\n- `perf:` - Performance improvements\n- `test:` - Testing changes\n- `chore:` - Maintenance tasks, releases, dependency updates, CI/infrastructure changes\n- `security:` - Security-related changes\n- `registry:` - Any changes to `registry/` (do not add a scope)\n- `ci:` - CI and automation changes\n- `revert:` - Reverting a previous change\n\n**Scopes:**\n- For command-specific changes, use the command name: `install`, `activate`, `use`, `exec`, etc.\n- For subsystem changes: `config`, `backend`, `env`, `task`, `vfox`, `python`, `github`, `release`, `completions`, `http`, `schema`, `doctor`, `shim`, `core`, `deps`, `ci`\n- Use `task` (not `run`) for task-related changes, even if the code lives in `src/cli/run.rs` or `src/cmd.rs`\n\n**Description Style:**\n- Start the description with a lowercase character, or with an acronym such as `PGO` or `CLI`\n- Use imperative mood (\"add feature\" not \"added feature\")\n- Keep it concise but descriptive\n\n**Examples:**\n- `fix(install): resolve version mismatch for previously installed tools`\n- `feat(activate): add fish shell support`\n- `feat(vfox): add semver Lua module for version sorting`\n- `feat(env): add environment caching with module cacheability support`\n- `docs(contributing): update hk usages`\n- `chore: release 2026.1.6`\n- `chore(ci): add FORGEJO_TOKEN for API authentication`\n- `registry: add miller`\n\nCI validates the pull request title and re-runs when it is edited. Intermediate\ncommit subjects are not checked because pull requests are squash-merged. CI\nmechanically checks the allowed type, syntax, and lowercase- or acronym-leading description;\nimperative mood and breaking-change details remain review rules.\n\n### PR titles and descriptions are release-note inputs\n\nCommunique generates release notes from PR titles and descriptions, so write them for a mise user who has not read the diff: lead with the user-visible problem and outcome, show a concrete example, and keep them in sync with the final diff. Follow the `pr-description` skill ([`.agents/skills/pr-description/SKILL.md`](.agents/skills/pr-description/SKILL.md)) when opening or revising a PR.\n\n### Pre-commit Process\n1. Run `mise run lint-fix` and `git add` any lint fixes before committing\n2. Use `mise run test:e2e [test_filename]...` for running specific e2e tests\n3. Never run e2e tests by executing them directly — always use the mise task\n\n`hk.pkl` defines `check` and `fix` steps and a git `pre-commit` hook that runs the same linters with auto-fix (`stash = \"git\"` preserves unstaged work). `hk install --mise` installs that hook. You can still run `mise run lint` / `mise run lint-fix` by hand; on Linux and macOS they run hk, but on Windows `lint-fix` runs only Clippy, oxfmt, and `cargo fmt`, so the other hk steps do not run there.\n\n### hk Agent Workflow\n\n- Prefer the hk MCP server for effect-aware plans, checks, fixes, logs, and captured diffs.\n- When invoking hk directly, use `hk run check --safe --format json` for a complete machine-readable result or `--format jsonl` for streaming lifecycle events.\n- Scope checks to changed files. For an exact file list, pass NUL-delimited paths with `--files0-from`; use `--cd` to target another project directory.\n- Never run a command classified as unknown or destructive without explicit user approval. Review the resulting diff after fixes.\n\n### Dependency Updates\n\n- Use the lowest-specificity dependency requirement that expresses compatibility in `Cargo.toml` (for example, prefer `\"1\"` over `\"1.2.3\"`, and `\"0.12\"` over `\"0.12.1\"` for a pre-1.0 crate).\n- Routine dependency updates should only change `Cargo.lock`. If the existing `Cargo.toml` requirement accepts the target version, do not change it merely to force or record the update; use `cargo update -p <crate> --precise <version>` instead.\n- Keep lockfile updates focused on the requested dependency and its required transitive changes. Remove unrelated resolver churn before committing.\n\nWhen updating the embedded `aube` crates, follow the `update-aube` skill ([`.agents/skills/update-aube/SKILL.md`](.agents/skills/update-aube/SKILL.md)).\n\n## Deprecation Policy\n\nWhen deprecating a feature, backend, or implicit behavior:\n\n1. **Immediately**: Mark it as deprecated in docs (add a warning banner) and display a CLI warning using the `deprecated_at!` macro from `src/output.rs` (`warn_at` is the current version).\n2. **12 months after warn** (`remove_at`): `debug_assert!` in `deprecated_at!` fires, signaling the deprecated code or behavior should be removed.\n\n12 months is the default window, not a hard rule. Some deprecations use a shorter window, such as 6 months, on purpose. Use 12 months for new deprecations unless jdx asks for something else, and do not lengthen an existing shorter window.\n\nDelay the CLI warning for up to 6 months only when migration requires a new setting, syntax, or replacement that older supported mise versions would reject or fail to parse. This compatibility window lets users adopt a configuration that works across old and new clients before warnings begin. Do not delay warnings for a behavior change that requires no new configuration, or when the replacement already works in older clients.\n\nUse mise version format for dates (e.g., `deprecated_at!(\"2026.10.0\", \"2027.10.0\", \"id\", \"message\")`).\n\nIf a compatibility window is required, removal remains 12 months after `warn_at`, not 12 months after the initial documentation notice.\n\nFor temporary code with no user-facing deprecation, such as a migration or a fallback that reads what an older mise wrote, use `remove_by!(\"2027.1.0\", \"id\")` from `src/output.rs`. It is a compile-time assertion, so the build fails once the version reaches `remove_at`; remove every `remove_by!` with that id and the code it guards.\n\n## Important Implementation Notes\n\n### Backend System\nWhen implementing new tool backends, follow the pattern in `src/backend/mod.rs`. Each backend must implement the `Backend` trait with methods for listing versions, installing tools, and managing tool metadata.\n\n### DO NOT ASSUME SEMVER\n**Do not assume tool versions follow semver or any other orderable scheme.** mise manages hundreds of tools with wildly different versioning conventions:\n\n- Date-based: `2024.01.15`, `20241015`\n- Pre-release / ref / tag versions: `tip`, `HEAD`, `nightly`, `edge`, `canary`, `ref:main`, `tag:v1`, `sub-X.Y:...`\n- Non-numeric tags: Python `3.12.0a1`, Ruby `3.2.0-preview1`, Go `1.22rc1`, Node `lts/hydrogen`, `lts-iron`\n- Tool-specific meanings of `latest` (e.g. some exclude pre-releases, some don't)\n\n**Rules:**\n1. Do not call `versions::Versioning::new(...)` (or any other semver comparator) at a new call site to pick the \"newest\" version, \"resolve latest\", or sort a version list. That crate silently returns `None` / arbitrary ordering for non-semver strings, which means wrong versions get chosen for many tools.\n2. To resolve a version request (`latest`, a prefix, a channel name), delegate to the backend via `Backend::latest_version`, `Backend::latest_installed_version`, `Backend::list_versions_matching`, or `ToolRequest::resolve` — the backend knows what \"latest\" means for its tool.\n3. To list installed versions in a meaningful order, use `Backend::list_installed_versions_matching` or the toolset's resolved versions. Do not reorder them yourself.\n4. Lockfile version strings must be treated as opaque — compare with `==`, never with a version ordering. Never write a non-concrete string (`latest`, `lts/*`, a prefix) into the lockfile; resolve first.\n\nA few existing call sites (e.g. runtime symlinks) do use `Versioning` ordering today, but that's legacy behavior and arguably also wrong — do not point at them to justify new semver assumptions.\n\nIf you think you need to pick \"the newest installed version\" at a new call site, stop and ask — that call almost always belongs on the backend, not inline.\n\n### Paranoid mode categories\n`paranoid` is a bool or a list of categories (`config`, `env_files`, `plugins`, `provenance`), defined by `Paranoid` in `crates/mise-settings/src/paranoid.rs`. Any new behavior gated on paranoid mode must belong to one of those categories, or introduce a new named category, so it is individually selectable. New code must never read paranoid as a plain bool: call `settings.paranoid.config()`, `.env_files()`, `.plugins()` or `.provenance()`, and add an e2e test that the category works alone.\n\n### Plugin Development\n- Core tools are implemented in `src/plugins/core/`\n- External plugins use ASDF or vfox compatibility layers\n- Plugin metadata is defined in `mise.plugin.toml` files\n\n### Configuration Parsing\nThe configuration system supports multiple file formats and environment-specific configs. Changes to settings require updating `settings.toml` and running `mise run render:schema`. The `Settings` types are generated from `settings.toml` in `crates/mise-settings`; loading them (config discovery, trust, CLI flags) stays in `src/config/settings.rs`, whose `SettingsExt` trait holds the methods that need the rest of mise.\n\n`schema/mise.json`, `schema/mise-task.json` and `schema/miserc.json` are generated from `crates/mise-config` and `settings.toml`: never edit the JSON. Change the Rust, then run `mise run render:schema`; a `mise-config` test fails while the committed files are stale. The top-level keys are the fields of `MiseTomlDecl` in `crates/mise-config/src/mise_toml.rs`, which `MiseToml` deserializes through: a new key goes in `MiseTomlDecl`, and `MiseToml::from_decl` moves it into `MiseToml`. Sections whose types derive `JsonSchema` (so far `[bootstrap]`, `[daemons_settings]`, `[daemon_groups]`, `[doctor]`, `[history]`, `[monorepo]`, `[oci]`, `[task_config]`, `[tasks]`, `[task_templates]`, `[tool_config]` and `[wrappers]`) are generated from those types and their doc comments. `[env]` and `[vars]` accept shapes a derive cannot parse, so `env.rs` reads them with visitors; their schema is derived from the `Env*` and `Vars*` declaration types in `crates/mise-config/src/env/decl.rs`, which describe the tables and nothing parses into them, and a test checks that the option keys they declare are the fields of `EnvDirectiveOptions`. `[[watch_files]]`, `[tool_alias]` and `min_version` have a hand-written `JsonSchema` impl in `watch_files.rs`, `alias.rs` and `min_version.rs`. Task fields with several accepted shapes (a string or a list, a name or a table, ...) take theirs from the declaration types in `crates/mise-config/src/task/shapes.rs`, which `TaskDecl` and `TaskConfig` attach with `schemars(with = ..)` so the runtime field types stay as they are; nothing parses into those types, so change them together with the parser. `task/schema.rs` composes the rest: the `task` definition, a task's `tools` (which follow the backend table of `[tools]`) and the template schema. `[tools]` picks per-backend options by key pattern: a backend's options are the declaration types in `crates/mise-config/src/tools/decl.rs` (a new option is a field with a doc comment, which is its description), and `crates/mise-config/src/tools/schema.rs` composes them, with one table row per backend and per platform table. mise reads these definitions by name to reject unknown options (`OptionSpec`), so change them together with `ToolVersionOptions::insert_option` and the backend's option reader. `[hooks]` is derived from the `Hook*` declaration types in `crates/mise-config/src/hooks/decl.rs`, which describe the shapes each event accepts, with a test that they name the keys the parser reads. The `[bootstrap]` values that stay raw TOML so newer shapes warn instead of failing (hooks, shell activation, macOS defaults, apt and dnf repositories) are derived from the declaration types in `crates/mise-config/src/bootstrap/decl.rs`; nothing parses into those, and tests in mise-system check the hook phases and the curated macOS keys against the code that reads them. `[daemons]` and `[daemon_providers]` stay raw tables that mise-daemons reads key by key, with their schema derived from the `Daemon*Decl` types in `crates/mise-config/src/daemons.rs`; those types describe a table, and nothing parses into them, so a key added in mise-daemons has to be added to them too. `[deps]` is derived from `DepsDecl` and `DepsProviderDecl`, which also hold the list of built-in providers mise shares; `[secrets]` stays raw TOML like the dotfiles, with its schema derived from `SecretsDecl` and a test in mise that its parser reads the same keys. `[dotfiles]` and `[dotfile_groups]` entries also stay raw TOML until mise-system expands them, but their schema is derived from the declaration types in `crates/mise-config/src/dotfiles.rs`, with the rules between keys written by hand in `dotfiles/schema.rs`; mise-system's `*_keys_match_the_declaration` tests fail until its parsers read the same keys. `[settings]` and `miserc.json` come from `settings.toml` through `crates/mise-config/src/schema/settings.rs`.\n\nThe `schema_matches_parser` unit test (`src/config/config_file/mise_toml/schema_conformance.rs`) validates every `toml` block in `docs/` and every mise config an e2e heredoc writes against both the schema and `MiseToml`'s parser, and fails when they disagree. Fix the schema rather than the corpus. Mark a config that mise refuses on purpose with `# schema: invalid` (e2e) or `<!-- schema: invalid -->` (docs) on the line above it, and an excerpt that is not a whole config with `schema: skip`. List deliberate differences in its `GAPS` with a reason.\n\n### Testing Strategy\n- E2E tests are organized by feature area (cli/, config/, backend/, etc.)\n- Use snapshot testing for CLI output verification\n- Backend-specific tests verify tool installation and version management\n- Slow tests (marked with `_slow` suffix) test actual tool compilation/installation\n\n### Cross-Platform Considerations\n- Windows modules follow one of two conventions:\n  - `*_windows.rs` is a platform-swapped sibling of a same-named module, selected with `#[cfg_attr(windows, path = \"..._windows.rs\")]` (e.g. `src/fake_asdf.rs` / `src/fake_asdf_windows.rs`)\n  - `windows_*.rs` is a single module about Windows with no non-Windows counterpart to swap in. Declare it on every platform and cfg-split it internally when other code calls it on all targets or its tests should run on Linux (e.g. `src/windows_posix.rs`, `src/windows_console.rs`); declare it under `#[cfg(windows)]` when only Windows code uses it (e.g. `src/windows_job.rs`)\n- Platform-specific tool installation logic in core plugins\n- Shim system varies by platform (especially Windows)\n- we don't chmod mise e2e tests to be executable\n\n### Windows PATH boundaries\n\n- Do not invoke subprocesses to translate paths in activation hooks, shims, or `mise x`/task execution.\n- Keep PATH in native Windows form inside mise and when launching child processes, including child MSYS2, Git Bash, or Cygwin processes. Never pre-convert the PATH inherited by a child emulator.\n- Convert PATH only when native Windows mise emits an assignment into an already-running, positively identified MSYS2/Cygwin shell. Only persisted mounts from the runtime defaults, `fstab`, and `fstab.d` are available; session-only `mount` changes cannot be reconstructed without entering the running process.\n- Never infer an emulator from the word `bash` alone. Require MSYS/Cygwin runtime evidence, and explicitly exclude WSL and BusyBox Bash.\n- Windows activation tests must execute a command through the emitted PATH and verify a native Windows grandchild receives a valid semicolon-delimited PATH. Output-shape assertions alone are insufficient.\n\n## GitHub Interactions\n\nNever open pull requests against the `release` branch. Default PRs to `main` unless the user explicitly names a different non-`release` base branch. If a change appears to belong on `release`, stop and ask for the intended branch strategy instead of opening a PR against `release`.\n\nSee [Discussions and Issues: Restricted AI Replies](#discussions-and-issues-restricted-ai-replies) at the top of this file.\n\nWhen AI contributes GitHub content—including a pull request description, review, pull request\ncomment, discussion post, or issue—append this disclosure:\n\n`*AI-assisted — Tool: <tool>; model: <provider>/<model>; version: <version-or-unavailable>.*`\n\nUse the exact model and version identifiers exposed by the runtime. Never infer or guess them; use\n`unavailable` when either value is not exposed.\n\n## Documentation\n\n### URL Structure\nWhen referencing mise documentation URLs, use the correct path structure based on the `docs/` directory layout:\n\n- **Dev tools & backends**: `mise.jdx.dev/dev-tools/backends/<backend>.html` (e.g., `mise.jdx.dev/dev-tools/backends/s3.html`)\n- **Configuration**: `mise.jdx.dev/configuration/...`\n- **Tasks**: `mise.jdx.dev/tasks/...`\n- **Environments**: `mise.jdx.dev/environments/...`\n- **CLI reference**: `mise.jdx.dev/cli/...`\n\nDo NOT use shortened paths like `mise.jdx.dev/backends/...` - always include the full path matching the `docs/` directory structure.\n\n## Cloud agent instructions (Cursor Cloud and Claude Code on the web)\n\nCursor Cloud Agents bootstrap from `.cursor/environment.json`, which runs `.cursor/install.sh`. Claude Code on the web runs the same script from the SessionStart hook in `.claude/settings.json` (`.claude/hooks/session-start.sh`), which runs on session `startup`/`resume`/`fork` (not `/clear` or compaction) with a 30-minute timeout, exits immediately unless `CLAUDE_CODE_REMOTE=true`, sends the bootstrap output to stderr, and adds the mise shims and `/usr/local/bin` to `PATH` through `CLAUDE_ENV_FILE`. The hook runs synchronously, so the session starts after the build finishes. Claude cloud containers do not provide a GitHub token by default; add `GITHUB_TOKEN` as an environment secret to avoid GitHub API rate limits during `mise install` and e2e tests. Use a fine-grained token with public-repository read-only access and no other permissions: any branch a session checks out (its hook, build scripts, tests, and tasks) can read the session environment. Draft environment builds often run as `ubuntu` rather than `root`; the script handles both (passwordless sudo, cargo/rustup permissions, world-writable `/tmp/fslock`).\n\nThe install script:\n\n- cds to the repository root derived from the script path before reading `Cargo.toml` or building\n- installs host packages needed to build mise and to run most e2e tests (openssl, pkg-config, zsh, fish, python3 + venv, jq, git, build-essential, and compile-time libs). It does **not** install a JDK or GUI libraries; those live in `packaging/e2e/Dockerfile`. `apt-get` is invoked as `sudo -n env DEBIAN_FRONTEND=noninteractive apt-get …` so the frontend reaches apt when elevation is required\n- installs and defaults to the latest stable Rust toolchain (not the `Cargo.toml` `rust-version` MSRV), including `rustfmt` and `clippy`, and updates it on reruns\n- gets a bootstrap `mise` and symlinks it to `/usr/local/bin/mise`: an existing `target/debug/mise` refreshes itself with `mise run build`; if it cannot run this checkout's config, a plain `cargo build` goes to `target/bootstrap` (the `mbx` wrapper leaves read-only outputs in `target/`); with no `target/` yet, a plain `cargo build` goes to `target/`\n- keeps `GITHUB_TOKEN`, `MISE_GITHUB_TOKEN`, and `GH_TOKEN` in sync via one `sync_github_tokens` helper (prefer any already-set token; fall back to `gh auth token` only when all three are empty)\n- runs `MISE_SAFE=1 /usr/local/bin/mise install` with the just-built binary so checkout-controlled hooks/templates/`[env]` and tool-level `postinstall` / `install_env` cannot run with those tokens, then `mise trust` for later agent commands\n- runs `mise run build` so `target/` is warm for the `mbx`-wrapped cargo (`[wrappers.cargo]` in `mise.toml`) that agents build with, then points `/usr/local/bin/mise` at `target/debug/mise`. Every build runs with `GITHUB_TOKEN`, `MISE_GITHUB_TOKEN`, `GH_TOKEN`, and `GITHUB_API_TOKEN` unset\n- runs `hk install --mise` (installs the git `pre-commit` hook defined in `hk.pkl`)\n- persists mise shims and token sync in one `/etc/profile.d/mise-dev-env.sh` (shims first, then `sync_github_tokens`) and rewrites the Cloud Agent block in `/etc/bash.bashrc` so non-login interactive bash picks it up after a snapshot. Fish/zsh only get this from login shells (`profile.d`), not from bashrc\n- exposes the mise-installed `node` / `npm` / `npx` / `hk` / `gh` binaries on `/usr/local/bin` (isolated e2e PATH includes that directory, not the agent's shims). Links freeze the version from install time — re-run `.cursor/install.sh` after upgrading those tools\n\nThere is no long-running service to start. Do not put `mise run build` or `mise run test:unit` in `terminals`; those are one-shot commands and would rerun a full build/test on every boot.\n\nThe debug `mise` binary is already on PATH. Prefer `mise run …` for project tasks.\n\n### E2E on Cloud Agents\n\n- Always `mise run test:e2e [test_filename]...` — never execute e2e scripts directly\n- Slow tests (`*_slow`) are skipped unless `TEST_ALL=1`. Do not run the full suite unless asked; pick tests under the feature area you changed\n- Isolated e2e uses `env -i` and a fake `HOME`, so the agent's mise shims are not on PATH. Tests install their own tools. Host packages (zsh, fish, python3, jq, git) still need to be on `/usr/bin`\n- If GitHub API calls 429, run `export GITHUB_TOKEN=\"$(gh auth token)\"; export MISE_GITHUB_TOKEN=\"$GITHUB_TOKEN\"`\n- A leftover `/tmp/mise.toml` will fail the harness; remove it if that error appears\n",".cursor/rules/conventional_commits.mdc":"---\nalwaysApply: false\ndescription: how to write commit and PR titles\n---\n\n## Conventional Commits (REQUIRED)\n\nPR titles MUST follow conventional commit format. Intermediate commit subjects\nSHOULD use the same format:\n\n### Format\n```\n<type>[optional scope][optional !]: <description>\n```\n\n### Types\n- `feat:` - New features\n- `fix:` - Bug fixes that affect CLI behavior (not CI, docs, or infrastructure)\n- `refactor:` - Code refactoring\n- `docs:` - Documentation changes\n- `style:` - Code style/formatting (no logic changes)\n- `perf:` - Performance improvements\n- `test:` - Testing changes\n- `chore:` - Maintenance tasks, releases, dependency updates, CI/infrastructure\n- `ci:` - CI and automation changes\n- `revert:` - Revert a previous change\n- `security:` - Security-related changes\n- `registry:` - Any changes to `registry/` (no extra scope)\n\n### Examples\n```\nfeat(cli): add new command for tool management\nfix(config): resolve parsing issue with nested tables\nrefactor(backend): simplify plugin loading logic\ndocs(contributing): update installation instructions\ntest(e2e): add tests for tool installation\nchore(ci): improve cursor cloud agent environment\nregistry: add miller\n```\n\n### Common Scopes\nCommand names (`install`, `activate`, `use`, `exec`, …) or subsystems:\n`config`, `backend`, `env`, `task`, `vfox`, `python`, `github`, `release`,\n`completions`, `http`, `schema`, `doctor`, `shim`, `core`, `deps`, `ci`.\n\nUse `task` (not `run`) for task-related changes, even if the code lives in\n`src/cli/run.rs` or `src/cmd.rs`.\n\nDescription: start with a lowercase character, use imperative mood, and keep it concise.\n",".cursor/rules/testing.mdc":"---\ndescription: how to test the mise codebase\nalwaysApply: false\n---\n\nTesting and linting commands should be run via `mise run`.\n\n- `mise run test:e2e [test_filename]...` executes an e2e test\n- `mise run test:unit` executes the unit tests\n- `mise run lint` runs the linting commands\n- `mise run lint-fix` runs the linting commands and fixes the issues\n- `mise --cd crates/vfox run test` executes the tests for the vfox crate\n- `mise --cd crates/vfox run lint` runs the linting commands for the vfox crate\n- `mise --cd crates/vfox run lint-fix` runs the linting commands and fixes the issues for the vfox crate\n\nNever execute e2e scripts directly. Slow tests (`*_slow`) are skipped unless `TEST_ALL=1`.\n\nFor GitHub API rate limits during e2e, set `MISE_GITHUB_TOKEN` (or `GITHUB_TOKEN`). Cloud Agents can use `export MISE_GITHUB_TOKEN=\"$(gh auth token)\"` when those are unset.\n\nOther tasks can be found by running `mise task ls`\n",".cursor/rules/development.mdc":"---\nalwaysApply: true\n---\n\n- `cargo build --all-features` - build the project\n- `target/debug/mise` - run the built binary\n- `mise run test:e2e [test_filename]...` - run e2e tests\n- `mise run test:unit` - run unit tests\n- `mise run lint` - run linting\n- `mise run lint-fix` - run linting and fix issues\n\nDon't run e2e tests by trying to execute them directly, always use `mise run test:e2e [test_filename]...`\n\nRun `mise run lint-fix` and `git add` any lint fixes before trying to commit.\n","crates/vfox/plugins/.luarc.json":"{\n  \"$schema\": \"https://raw.githubusercontent.com/LuaLS/vscode-lua/master/setting/schema.json\",\n  \"runtime\": {\n    \"version\": \"Lua 5.1\"\n  },\n  \"diagnostics\": {\n    \"disable\": [\"duplicate-set-field\"]\n  },\n  \"workspace\": {\n    \"checkThirdParty\": false,\n    \"library\": [\"../types\"]\n  }\n}\n","docs/bootstrap/packages/apk.md":"# Packages Skill\n\nPath: `docs/bootstrap/packages/apk.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/bootstrap/packages/apk.md)","docs/bootstrap/packages/apt.md":"# Packages Skill\n\nPath: `docs/bootstrap/packages/apt.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/bootstrap/packages/apt.md)","docs/bootstrap/packages/brew.md":"# Packages Skill\n\nPath: `docs/bootstrap/packages/brew.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/bootstrap/packages/brew.md)","docs/bootstrap/packages/dnf.md":"# Packages Skill\n\nPath: `docs/bootstrap/packages/dnf.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/bootstrap/packages/dnf.md)","docs/bootstrap/packages/flatpak.md":"# Packages Skill\n\nPath: `docs/bootstrap/packages/flatpak.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/bootstrap/packages/flatpak.md)","docs/bootstrap/packages/index.md":"# Packages Skill\n\nPath: `docs/bootstrap/packages/index.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/bootstrap/packages/index.md)","docs/bootstrap/packages/mas.md":"# Packages Skill\n\nPath: `docs/bootstrap/packages/mas.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/bootstrap/packages/mas.md)","docs/bootstrap/packages/pacman.md":"# Packages Skill\n\nPath: `docs/bootstrap/packages/pacman.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/bootstrap/packages/pacman.md)","docs/bootstrap/packages/plugins.md":"# Packages Skill\n\nPath: `docs/bootstrap/packages/plugins.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/bootstrap/packages/plugins.md)","docs/cli/plugins/install.md":"# Plugins Skill\n\nPath: `docs/cli/plugins/install.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/cli/plugins/install.md)","docs/cli/plugins/link.md":"# Plugins Skill\n\nPath: `docs/cli/plugins/link.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/cli/plugins/link.md)","docs/cli/plugins/ls.md":"# Plugins Skill\n\nPath: `docs/cli/plugins/ls.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/cli/plugins/ls.md)","docs/cli/plugins/ls-remote.md":"# Plugins Skill\n\nPath: `docs/cli/plugins/ls-remote.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/cli/plugins/ls-remote.md)","docs/cli/plugins/uninstall.md":"# Plugins Skill\n\nPath: `docs/cli/plugins/uninstall.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/cli/plugins/uninstall.md)","docs/cli/plugins/update.md":"# Plugins Skill\n\nPath: `docs/cli/plugins/update.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/cli/plugins/update.md)","test/plugins/vfox-npm/README.md":"# vfox-npm Documentation\n\nPath: `test/plugins/vfox-npm/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/test/plugins/vfox-npm/README.md)","crates/vfox/plugins/dummy/README.md":"# dummy Documentation\n\nPath: `crates/vfox/plugins/dummy/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/crates/vfox/plugins/dummy/README.md)","docs/cli/bootstrap/packages/apply.md":"# Packages Skill\n\nPath: `docs/cli/bootstrap/packages/apply.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/cli/bootstrap/packages/apply.md)","docs/cli/bootstrap/packages/brew.md":"# Packages Skill\n\nPath: `docs/cli/bootstrap/packages/brew.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/cli/bootstrap/packages/brew.md)","docs/cli/bootstrap/packages/import.md":"# Packages Skill\n\nPath: `docs/cli/bootstrap/packages/import.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/cli/bootstrap/packages/import.md)","docs/cli/bootstrap/packages/prune.md":"# Packages Skill\n\nPath: `docs/cli/bootstrap/packages/prune.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/cli/bootstrap/packages/prune.md)","docs/cli/bootstrap/packages/status.md":"# Packages Skill\n\nPath: `docs/cli/bootstrap/packages/status.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/cli/bootstrap/packages/status.md)","docs/cli/bootstrap/packages/upgrade.md":"# Packages Skill\n\nPath: `docs/cli/bootstrap/packages/upgrade.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/cli/bootstrap/packages/upgrade.md)","docs/cli/bootstrap/packages/use.md":"# Packages Skill\n\nPath: `docs/cli/bootstrap/packages/use.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/cli/bootstrap/packages/use.md)","docs/cli/bootstrap/plugins/apply.md":"# Plugins Skill\n\nPath: `docs/cli/bootstrap/plugins/apply.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/cli/bootstrap/plugins/apply.md)","docs/cli/bootstrap/plugins/status.md":"# Plugins Skill\n\nPath: `docs/cli/bootstrap/plugins/status.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/cli/bootstrap/plugins/status.md)","docs/cli/bootstrap/packages/brew/tap.md":"# Brew Skill\n\nPath: `docs/cli/bootstrap/packages/brew/tap.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/cli/bootstrap/packages/brew/tap.md)","docs/cli/bootstrap/packages/brew/untap.md":"# Brew Skill\n\nPath: `docs/cli/bootstrap/packages/brew/untap.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/cli/bootstrap/packages/brew/untap.md)"},"files":{"docs/architecture.md":"---\ndescription: \"Find where commands, configuration, backends, tasks, environments, and bootstrap live in the mise source tree.\"\noutline: [2, 3]\n---\n\n# Codebase architecture\n\nUse this map to find the code that owns a behavior before you change it. For\nsetup, checks, and how to submit a change, see [Contributing](/contributing.html).\n\n## Library, binary, and crates {#library-binary-and-crates}\n\nThe `mise` package builds two targets. The library, `src/lib.rs`, holds\neverything except the command line: configuration, toolsets, backends, tasks,\nenvironments, and bootstrap. The binary, `src/main.rs` plus `src/cli/`, sits on\ntop of it. `src/main.rs` imports the library's root with `use mise::*`, so code\nin `src/cli/` still writes `crate::config::…`. A change confined to `src/cli/`\nrecompiles only the binary.\n\nLibrary code must not refer to `crate::cli`. When core code needs command\nbehavior, it calls a hook in\n[`src/frontend.rs`](https://github.com/jdx/mise/blob/main/src/frontend.rs),\nwhich the binary fills in at startup with `cli::register_frontend`. The hooks\ncover running `mise lock` after an install adds versions and listing subcommand\nnames for \"did you mean\" suggestions. When `cli` needs a core item, make that\nitem `pub`. The library denies `unreachable_pub`, so everything else stays\n`pub(crate)`.\n\n`cfg(test)` is set for the binary's tests but not for the library they call, so\ncore code that behaves differently under tests checks\n`mise_util::testing::in_tests()` instead.\n\nThe workspace crates under `crates/` cannot depend on the `mise` package.\n`register_util_hooks` in `src/lib.rs` gives them what they need from mise, such\nas the settings loader and the build identity used in cache keys, before\nanything else runs.\n\n| Crate                     | Contents                                                                                                   |\n| ------------------------- | ---------------------------------------------------------------------------------------------------------- |\n| `mise-util`               | Environment, directory, file, HTTP, cache, template, and `EnvDiff`/`PathEnv` helpers                       |\n| `mise-daemons`            | Daemon declarations, ports, presets, and the supervisor runtime (the toolset glue stays in `src/daemons/`) |\n| `mise-oci`                | The OCI registry client, layers, and image layout (the image builder stays in `src/oci/`)                  |\n| `mise-system`             | The bootstrap, dotfiles, and history modules                                                               |\n| `mise-config`             | The `mise.toml` declaration types, so far for `[bootstrap]`, `[dotfiles]`, and `[history]`                 |\n| `mise-system-packages`    | System package manager drivers: apt, dnf, brew, brew-cask, and more                                        |\n| `mise-ui`                 | Progress reports, prompts, and themes for the terminal                                                     |\n| `mise-settings`           | The `Settings` types, generated from `settings.toml`, and the process-wide settings cache                  |\n| `vfox`                    | The embedded Lua runtime and the hook and module interfaces for vfox plugins                               |\n| `aqua-registry`           | Parsing, package lookup, and cache formats for aqua registries                                             |\n| `mise-bootstrap`          | Bootstrap resource planning and dependency ordering                                                        |\n| `mise-lsp`                | The language server behind `mise lsp`; mise passes it `schema/mise.json` and the `mise fmt` formatter      |\n| `mise-cache-core`         | The remote task cache protocol, content-addressed storage, authentication, and transport                   |\n| `mise-shim`               | `mise-shim.exe`, the native executable that Windows shims use in the default `exe` mode                    |\n| `mise-sigstore`           | Sigstore verification helpers                                                                              |\n| `mise-tls`                | Root certificate fallback for HTTPS clients when the system trust store is empty                           |\n| `mise-agent-env`          | Detection of AI coding agents from the process environment                                                 |\n| `mise-interactive-config` | The interactive TOML editor behind `mise edit`                                                             |\n| `mise-brew-metadata`      | Homebrew formula metadata models                                                                           |\n| `mise-brew-relocation`    | Homebrew bottle placeholder and binary relocation                                                          |\n| `mise-dotenv`             | A dotenv parser with explicit control over variable substitution                                           |\n\n## Where things live {#where-things-live}\n\n| Behavior                                 | Code                                                                                                               | User docs                                        |\n| ---------------------------------------- | ------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------ |\n| Commands, flags, and help text           | `src/cli/`; `mod.rs` dispatches, and each command has a file or directory such as `use.rs`, `exec.rs`, or `tasks/` | [CLI reference](/cli/)                           |\n| What each command changes                | `src/cli/command_effects.rs`                                                                                       |                                                  |\n| Config discovery, loading, and merging   | `src/config/`; `config_file/` holds `MiseToml`, `ToolVersions`, and `IdiomaticVersionFile`                         | [mise.toml](/configuration.html)                 |\n| Settings                                 | `settings.toml`, generated into `crates/mise-settings`; loading, trust, and CLI flags in `src/config/settings.rs`  | [Settings](/configuration/settings.html)         |\n| Config file schema                       | `schema/mise.json`                                                                                                 | [mise.toml](/configuration.html)                 |\n| Tool requests, resolution, install state | `src/toolset/`                                                                                                     | [Dev tools](/dev-tools/)                         |\n| Backends                                 | `src/backend/`; the `Backend` trait is in `mod.rs` and `BackendType` in `backend_type.rs`                          | [Backends](/dev-tools/backends/)                 |\n| Core tools                               | `src/plugins/core/`                                                                                                | [Core tools](/core-tools.html)                   |\n| Plugins                                  | `src/plugins/` (asdf and vfox adapters) and `crates/vfox`                                                          | [Plugins](/plugins.html)                         |\n| Tool shorthands                          | `registry/*.toml`, compiled in by `build.rs`; lookup in `src/registry.rs`                                          | [Registry](/registry.html)                       |\n| aqua registry                            | `crates/aqua-registry`; the bundled snapshot is `vendor/aqua-registry/`, baked in by `build.rs`                    | [aqua](/dev-tools/backends/aqua.html)            |\n| Lockfile                                 | `src/lockfile.rs` and `src/lockfile/`                                                                              | [Lockfile](/dev-tools/mise-lock.html)            |\n| Environment directives                   | `src/config/env_directive/`; `EnvDiff` and `PathEnv` come from `crates/mise-util`                                  | [Environment variables](/environments/)          |\n| Shell activation                         | `src/shell/` (one file per shell), `src/hook_env.rs`, `src/cli/activate.rs`                                        | [Shell setup](/shell-setup.html)                 |\n| Shims                                    | `src/shims.rs` and `crates/mise-shim`                                                                              | [Shims](/dev-tools/shims.html)                   |\n| Templates                                | `crates/mise-util/src/tera.rs`, re-exported as `src/tera.rs`                                                       | [Tera templates](/templates.html)                |\n| Tasks                                    | `src/task/`                                                                                                        | [Tasks](/tasks/)                                 |\n| Remote task cache                        | `crates/mise-cache-core`                                                                                           | [Remote task cache](/tasks/remote-cache.html)    |\n| Bootstrap and host packages              | `src/cli/bootstrap.rs`, `crates/mise-system` (packages in `crates/mise-system-packages`), `crates/mise-bootstrap`  | [Bootstrap](/bootstrap.html)                     |\n| Dotfiles                                 | `src/cli/dotfiles/`, `crates/mise-system/src/managed_files.rs`, `crates/mise-system/src/history/`                  | [Dotfiles](/dotfiles.html)                       |\n| Daemons                                  | `src/daemons/` (toolset glue), `crates/mise-daemons`                                                               | [Daemons](/daemons.html)                         |\n| Project dependencies                     | `src/deps/`                                                                                                        | [Project dependencies](/dev-tools/deps.html)     |\n| Secrets                                  | `src/secrets/`, `src/sops.rs`, `src/agecrypt.rs`                                                                   | [Secrets](/environments/secrets/)                |\n| Caches                                   | `crates/mise-util/src/cache.rs`: `CacheManager<T>`, MessagePack with zlib, written atomically                      | [Caches](/cache-behavior.html)                   |\n| packslip manifests                       | `src/packslip.rs`, `src/backend/packslip.rs`                                                                       | [packslip](/dev-tools/backends/packslip.html)    |\n| OCI images                               | `src/oci/` (builder), `crates/mise-oci`                                                                            | [OCI images](/dev-tools/mise-oci.html)           |\n| OpenTelemetry                            | `src/otel/`                                                                                                        | [OpenTelemetry](/tasks/opentelemetry.html)       |\n| Identity install layout                  | `src/install_layout/`                                                                                              | [Install layout](/dev-tools/install-layout.html) |\n| Sandboxing                               | `src/sandbox.rs`                                                                                                   | [Sandboxing](/sandboxing.html)                   |\n| Self-update                              | `src/cli/self_update.rs`                                                                                           | [Packaging mise](/packaging.html)                |\n\n## How a command runs {#system-overview}\n\nMost commands load the configuration, resolve the tools it requests, build an\nenvironment from them, and then run a child process or print shell code. Tasks\nand bootstrap start from the same configuration.\n\n```mermaid\nflowchart TD\n    CLI[CLI command] --> Config[Configuration and settings]\n    Config --> Tools[Tool requests and backend resolution]\n    Tools --> Env[Environment and PATH]\n    Env --> Exec[Child command or shell output]\n    Config --> Tasks[Task discovery and dependency graph]\n    Tasks --> Env\n    Config --> Bootstrap[Bootstrap plan and explicit apply]\n```\n\n### Configuration {#configuration-system}\n\n[`src/config`](https://github.com/jdx/mise/tree/main/src/config) finds config\nfiles, loads them through the `ConfigFile` trait, and merges them. Which files\nare found, whether they are trusted, and how each field merges are separate\ndecisions in the code. Settings, tools, environment directives, tasks, and\nbootstrap entries do not merge the same way, and write commands pick their\n[target file](/configuration.html#target-file-for-write-operations) separately.\n\n### Toolsets {#toolset-management}\n\n[`src/toolset`](https://github.com/jdx/mise/tree/main/src/toolset) connects\nversion requests to resolved versions and installation state:\n\n| Type             | Role                                                                                  |\n| ---------------- | ------------------------------------------------------------------------------------- |\n| `ToolRequest`    | A request such as `node@24`, a channel, or a ref, with its backend and options        |\n| `ToolVersion`    | A resolved version and its installation metadata                                      |\n| `Toolset`        | The requests and resolved versions for the current context                            |\n| `ToolsetBuilder` | Combines config, environment variable overrides, and command arguments, then resolves |\n\n### Backends {#backend-system}\n\nThe [`Backend` trait](https://github.com/jdx/mise/blob/main/src/backend/mod.rs)\nsplits shared policy from backend-specific work. Its public wrapper methods\nhandle caching and resolution. A backend implements hooks such as\n`_list_remote_versions`, which returns `VersionInfo` entries, and\n`install_version_`. Core tools in `src/plugins/core/` implement the same trait.\nFor how mise picks a backend for a short name, see\n[how backend selection works](/dev-tools/backends/#how-backend-selection-works);\nto add one, see [Adding a backend](/contributing.html#adding-backends).\n\n### Plugins {#plugins}\n\n[`src/plugins`](https://github.com/jdx/mise/tree/main/src/plugins) installs\nplugin sources and records their metadata.\n[`crates/vfox`](https://github.com/jdx/mise/tree/main/crates/vfox) runs vfox\nplugins in its embedded Lua runtime. Tool plugins install one tool, backend\nplugins handle `plugin:tool` requests, environment plugins return variables and\n`PATH` entries, and package plugins manage batches of host packages. asdf\nadapters run legacy shell scripts. Installing or updating a plugin's source is\nseparate from installing a tool version, and each keeps its own state. See\n[Plugins](/plugins.html).\n\n### Tasks {#task-system}\n\n[`src/task`](https://github.com/jdx/mise/tree/main/src/task) discovers, schedules,\nand runs tasks. `Task` holds a definition, the providers in\n`task_file_providers/` load local and remote task files, `Deps` is the\ndependency graph, and the executor and scheduler run ready tasks under the\nconfigured concurrency and output style. A node in the graph is a task with its\narguments, environment variables, and run phase, so the same task with\ndifferent arguments is a separate node. Read\n[Dependencies and execution order](/tasks/architecture.html) before you change\nhow the graph is built or how `depends`, `depends_post`, and `wait_for` behave.\n\n### Environment and shell activation {#shell-integration}\n\n`src/config/env_directive` evaluates `[env]` directives. Directives marked\n`tools = true` run after tools are resolved, and the rest run before.\n`mise activate` emits a shell hook from `src/shell/` that runs `mise hook-env`\nat each prompt. `hook-env` records an `EnvDiff` so the next run can undo the previous\ndirectory's changes before applying new ones. `mise exec` and `mise run` build\nthe child environment directly and do not need activation.\n\n### Bootstrap and host state {#bootstrap-and-host-state}\n\n`src/cli/bootstrap.rs` builds a plan and runs the selected phases. The code in\n`crates/mise-system` manages packages, files, edits, repositories, services, and\nplatform-specific resources, which live outside any tool's install directory.\nStatus, preview, apply, and prune are separate operations: a status check reads\nthe host and changes nothing. A package batch can be a subset named on the\ncommand line, so never treat a package's absence from a batch as a request to\nremove it.\n\n## Rules to preserve {#rules-to-preserve}\n\n- Treat versions as opaque strings. Resolve a request through the backend\n  (`Backend::latest_version`, `Backend::list_versions_matching`,\n  `ToolRequest::resolve`), never with a semver sort at a new call site.\n- Compare lockfile versions with `==`, keep the backend and checksum of an\n  entry, and never write `latest`, `lts/*`, or a prefix into the lockfile.\n- Do not add installs or network requests to a code path that only reports\n  local state.\n- Build a subprocess's environment from the one mise computed, not the\n  inherited process environment, which can miss earlier directives or select\n  the wrong tool.\n- Include every input that changes a cached result in its cache key, such as\n  options, environment variables, and source metadata. The environment cache\n  (`src/toolset/env_cache.rs`) and the task caches (`src/task/task_cache.rs`)\n  do not use `CacheManager` and have their own formats and invalidation rules.\n- Keep Windows `PATH` in native form inside mise and in child processes.\n  Convert it only when emitting assignments into a running, positively\n  identified MSYS2 or Cygwin shell; the\n  [agent guide](https://github.com/jdx/mise/blob/main/AGENTS.md) has the full\n  rules.\n- Classify every new command in `src/cli/command_effects.rs`; see\n  [Changing a CLI command](/contributing.html#changing-a-cli-command).\n\n## Generated files {#generated-files}\n\nEdit the source, then regenerate. Commit the output with the change that\nproduced it.\n\n| Output                                                                 | Source                                                                                                                                                   | Regenerate with                               |\n| ---------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------- |\n| `mise.usage.kdl`, `docs/cli/`                                          | Command definitions in `src/cli/`, `src/assets/mise-extra.usage.kdl`, and `docs/.vitepress/cli-reference.ts`                                             | `mise run render:usage`                       |\n| `tasks.md`                                                             | The project's tasks in `tasks.toml`, `xtasks/`, and `mise.toml`, through `mise generate task-docs`                                                       | `mise run render:usage`                       |\n| `man/man1/mise.1`                                                      | `mise.usage.kdl`                                                                                                                                         | `mise run render:mangen`                      |\n| `completions/`                                                         | The usage spec, through `mise completion <shell>`                                                                                                        | `mise run render:completions`                 |\n| `docs/.vitepress/cli_commands.ts` and the idiomatic version file table | `src/cli/` and the `idiomatic_files` keys in `registry/*.toml`                                                                                           | `mise run render:help`                        |\n| `schema/mise.json`, `schema/mise-task.json`, `schema/miserc.json`      | The types and doc comments in `crates/mise-config` (`MiseTomlDecl` for the top level) and `settings.toml`, through mise-config's `render-schema` example | `mise run render:schema`                      |\n| `docs/public/llms.txt`                                                 | Page titles and leads, and `docs/.vitepress/sidebar.ts`                                                                                                  | `mise run render:llms`                        |\n| `Settings` types                                                       | `settings.toml`                                                                                                                                          | Every build (`crates/mise-settings/build.rs`) |\n| The registry compiled into mise                                        | `registry/*.toml`                                                                                                                                        | Every build (`build.rs`)                      |\n| The [settings reference](/configuration/settings.html)                 | `settings.toml`                                                                                                                                          | Every docs build                              |\n\n`mise run render` runs every `render:*` task. For the schemas, change the types\nand doc comments in `crates/mise-config`, not the JSON; a `mise-config` test\nfails while the committed files are stale.\n\n## Tests {#tests}\n\nUnit tests sit beside the code they test, E2E tests are Bash scripts under\n`e2e/` run with `mise run test:e2e`, and the Windows E2E tests under `e2e-win/`\nuse Pester. See [Testing](/contributing.html#testing) for the commands and\nprerequisites.\n",".claude/agents/test-runner.md":"---\nname: test-runner\ndescription: Use proactively to run tests and analyze failures for the current task. Returns detailed failure analysis without making fixes.\ntools: Bash, Read, Grep, Glob\ncolor: yellow\n---\n\nYou are a specialized test execution agent. Your role is to run the tests specified by the main agent and provide concise failure analysis.\n\n## Core Responsibilities\n\n1. **Run Specified Tests**: Execute exactly what the main agent requests (specific tests, test files, or full suite)\n2. **Analyze Failures**: Provide actionable failure information\n3. **Return Control**: Never attempt fixes - only analyze and report\n\n## Workflow\n\n1. Run the test command provided by the main agent\n2. Parse and analyze test results\n3. For failures, provide:\n   - Test name and location\n   - Expected vs actual result\n   - Most likely fix location\n   - One-line suggestion for fix approach\n4. Return control to main agent\n\n## Output Format\n\n```\n✅ Passing: X tests\n❌ Failing: Y tests\n\nFailed Test 1: test_name (file:line)\nExpected: [brief description]\nActual: [brief description]\nFix location: path/to/file.rb:line\nSuggested approach: [one line]\n\n[Additional failures...]\n\nReturning control for fixes.\n```\n\n## Important Constraints\n\n- Run exactly what the main agent specifies\n- Keep analysis concise (avoid verbose stack traces)\n- Focus on actionable information\n- Never modify files\n- Return control promptly after analysis\n\n## Example Usage\n\nMain agent might request:\n\n- \"Run the password reset test file\"\n- \"Run only the failing tests from the previous run\"\n- \"Run the full test suite\"\n- \"Run tests matching pattern 'user_auth'\"\n\nYou execute the requested tests and provide focused analysis.\n",".codex/hooks.json":"{\n  \"hooks\": {\n    \"PostToolUse\": [\n      {\n        \"matcher\": null,\n        \"hooks\": [\n          {\n            \"type\": \"command\",\n            \"command\": \"sh -c 'if ! command -v entire >/dev/null 2>&1; then exit 0; fi; exec entire hooks codex post-tool-use'\",\n            \"timeout\": 30\n          }\n        ]\n      }\n    ],\n    \"SessionEnd\": [\n      {\n        \"matcher\": null,\n        \"hooks\": [\n          {\n            \"type\": \"command\",\n            \"command\": \"sh -c 'if ! command -v entire >/dev/null 2>&1; then exit 0; fi; exec entire hooks codex session-end'\",\n            \"timeout\": 3\n          }\n        ]\n      }\n    ],\n    \"SessionStart\": [\n      {\n        \"matcher\": null,\n        \"hooks\": [\n          {\n            \"type\": \"command\",\n            \"command\": \"sh -c 'if ! command -v entire >/dev/null 2>&1; then printf \\\"%s\\\\n\\\" \\\"{\\\\\\\"systemMessage\\\\\\\":\\\\\\\"Entire CLI is enabled but not installed or not on PATH. Installation guide: https://docs.entire.io/cli/installation#installation-methods\\\\\\\"}\\\"; exit 0; fi; exec entire hooks codex session-start'\",\n            \"timeout\": 30\n          }\n        ]\n      }\n    ],\n    \"Stop\": [\n      {\n        \"matcher\": null,\n        \"hooks\": [\n          {\n            \"type\": \"command\",\n            \"command\": \"sh -c 'if ! command -v entire >/dev/null 2>&1; then exit 0; fi; exec entire hooks codex stop'\",\n            \"timeout\": 30\n          }\n        ]\n      }\n    ],\n    \"SubagentStart\": [\n      {\n        \"matcher\": null,\n        \"hooks\": [\n          {\n            \"type\": \"command\",\n            \"command\": \"sh -c 'if ! command -v entire >/dev/null 2>&1; then exit 0; fi; exec entire hooks codex subagent-start'\",\n            \"timeout\": 30\n          }\n        ]\n      }\n    ],\n    \"SubagentStop\": [\n      {\n        \"matcher\": null,\n        \"hooks\": [\n          {\n            \"type\": \"command\",\n            \"command\": \"sh -c 'if ! command -v entire >/dev/null 2>&1; then exit 0; fi; exec entire hooks codex subagent-stop'\",\n            \"timeout\": 30\n          }\n        ]\n      }\n    ],\n    \"UserPromptSubmit\": [\n      {\n        \"matcher\": null,\n        \"hooks\": [\n          {\n            \"type\": \"command\",\n            \"command\": \"sh -c 'if ! command -v entire >/dev/null 2>&1; then exit 0; fi; exec entire hooks codex user-prompt-submit'\",\n            \"timeout\": 30\n          }\n        ]\n      }\n    ]\n  }\n}\n","schema/mise.plugin.json":"{\n  \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n  \"$id\": \"https://mise.jdx.dev/schema/mise.plugin.json\",\n  \"title\": \"mise-plugin\",\n  \"description\": \"config file for a mise plugin\",\n  \"type\": \"object\",\n  \"unevaluatedProperties\": false,\n  \"$defs\": {\n    \"plugin-script-config\": {\n      \"type\": \"object\",\n      \"unevaluatedProperties\": false,\n      \"properties\": {\n        \"cache-key\": {\n          \"description\": \"cache the script results separately based on these values; only consumed for list-bin-paths and exec-env, accepted elsewhere\",\n          \"type\": \"array\",\n          \"items\": {\n            \"type\": \"string\"\n          }\n        },\n        \"data\": {\n          \"description\": \"static data to use instead of executing the script; only consumed for list-aliases, list-idiomatic-filenames, and list-legacy-filenames, accepted elsewhere\",\n          \"type\": \"string\"\n        }\n      }\n    }\n  },\n  \"properties\": {\n    \"list-aliases\": {\n      \"description\": \"configuration for bin/list-aliases script\",\n      \"$ref\": \"#/$defs/plugin-script-config\"\n    },\n    \"list-legacy-filenames\": {\n      \"description\": \"configuration for bin/list-legacy-filenames script\",\n      \"$ref\": \"#/$defs/plugin-script-config\"\n    },\n    \"list-idiomatic-filenames\": {\n      \"description\": \"configuration for idiomatic filename discovery\",\n      \"$ref\": \"#/$defs/plugin-script-config\"\n    },\n    \"list-bin-paths\": {\n      \"description\": \"configuration for bin/list-bin-paths script\",\n      \"$ref\": \"#/$defs/plugin-script-config\"\n    },\n    \"exec-env\": {\n      \"description\": \"configuration for bin/exec-env script\",\n      \"$ref\": \"#/$defs/plugin-script-config\"\n    },\n    \"idiomatic-filenames\": {\n      \"description\": \"legacy key from old plugins that is ignored; when present, mise stops parsing the file entirely\",\n      \"deprecated\": true\n    },\n    \"legacy-filenames\": {\n      \"description\": \"legacy key from old plugins that is ignored; when present, mise stops parsing the file entirely\",\n      \"deprecated\": true\n    },\n    \"package-manager\": {\n      \"description\": \"configuration for a package-manager plugin\",\n      \"type\": \"object\",\n      \"unevaluatedProperties\": false,\n      \"properties\": {\n        \"requires\": {\n          \"description\": \"host binaries required by the package-manager plugin\",\n          \"type\": \"array\",\n          \"items\": {\n            \"type\": \"string\"\n          }\n        },\n        \"supports_version_pins\": {\n          \"description\": \"whether the package manager supports version-pinned requests\",\n          \"type\": \"boolean\"\n        },\n        \"supports-version-pins\": {\n          \"description\": \"whether the package manager supports version-pinned requests\",\n          \"type\": \"boolean\"\n        },\n        \"os\": {\n          \"description\": \"operating systems supported by the package-manager plugin\",\n          \"type\": \"array\",\n          \"items\": {\n            \"type\": \"string\"\n          }\n        }\n      }\n    }\n  }\n}\n",".codex/config.toml":"\n[features]\nhooks = true\n\n[mcp_servers.hk]\ncommand = \"hk\"\nargs = [\"mcp\", \"--root\", \".\"]\n","llms.txt":"# mise (mise-en-place) - Development Environment Tool\n\n## What is mise?\n\nmise (pronounced \"meez\") is a development environment setup tool that manages:\n1. **Dev Tools**: Installing, pinning, and switching programming languages and tools\n2. **Environments**: Loading project-specific environment variables\n3. **Tasks**: Running project automation for build, test, lint, deploy, and everyday workflows\n\nmise supports hundreds of development tools and can automatically switch between different versions based on your project directory.\n\n## Installation\n\n### Quick Install (Linux/macOS)\n```bash\ncurl https://mise.run | sh\n```\n\n### Other Methods\n- **Homebrew**: `brew install mise`\n- **Windows**: `winget install jdx.mise` or `scoop install mise`\n- **Debian/Ubuntu**: Available via apt repository\n- **Fedora**: Available via dnf repository\n\n## Core Configuration\n\n### mise.toml\nThe main configuration file for mise. Can be named:\n- `mise.toml` (project-specific)\n- `mise.local.toml` (local, not committed to git)\n- `~/.config/mise/config.toml` (global)\n\nExample `mise.toml`:\n```toml\n[tools]\nnode = \"20\"\npython = \"3.11\"\nterraform = \"1.0.0\"\ngo = \"latest\"\n\n[env]\nNODE_ENV = \"development\"\nDATABASE_URL = \"postgresql://localhost/myapp\"\n\n[tasks.test]\nrun = \"npm test\"\ndescription = \"Run tests\"\n\n[tasks.build]\nrun = \"npm run build\"\ndeps = [\"test\"]\n```\n\n### .tool-versions (asdf compatibility)\nmise is compatible with asdf's `.tool-versions` format:\n```\nnode 20.0.0\npython 3.11.5\nterraform 1.0.0\n```\n\n## Essential Commands\n\n### Tool Management\n- `mise use node@20` - Install and set node version (updates config)\n- `mise use -g node@20` - Set global default\n- `mise install` - Install all tools from config\n- `mise install node@20` - Install specific version\n- `mise ls` - List installed tools\n- `mise ls-remote node` - List available versions\n\n### Execution\n- `mise exec node@20 -- node script.js` - Run command with specific tool version\n- `mise x node@20 -- node script.js` - Shorthand for exec\n- `mise run test` - Run defined task\n- `mise test` - Shorthand (if no command conflict)\n\n### Environment\n- `mise activate bash` - Activate mise in shell (add to .bashrc)\n- `mise activate zsh` - Activate mise in zsh (add to .zshrc)  \n- `mise activate fish` - Activate mise in fish\n- `mise env` - Show current environment\n- `mise set KEY=value` - Set environment variable\n\n### Information\n- `mise doctor` - Check mise setup\n- `mise config` - Show loaded config files\n- `mise current` - Show active tool versions\n- `mise which node` - Show path to tool\n\n## Key Concepts\n\n### Activation vs Shims vs Exec\n1. **Activation** (`mise activate`): Recommended for interactive shells. Updates PATH automatically when changing directories.\n2. **Shims**: Symlinks that intercept tool calls. Good for CI/CD and IDEs.\n3. **Exec** (`mise exec`): Run commands with mise environment without activation.\n\n### Tool Scopes\n- `node@20.1.0` - Exact version\n- `node@20` - Latest 20.x version\n- `node@latest` - Latest available version\n- `node@lts` - Latest LTS version\n- `ref:master` - Build from git ref\n- `prefix:1.19` - Latest matching prefix\n- `path:/custom/path` - Use custom installation\n\n### Configuration Hierarchy\nConfig files are loaded in order (later overrides earlier):\n1. Global: `~/.config/mise/config.toml`\n2. Parent directories: `mise.toml` files going up the tree\n3. Current directory: `mise.toml`\n4. Local: `mise.local.toml`\n\n## Tasks\n\n### TOML Tasks\n```toml\n[tasks.build]\nrun = \"cargo build\"\ndescription = \"Build the project\"\ndepends = [\"install\"]\n\n[tasks.test]\nrun = \"cargo test\"\ndepends = [\"build\"]\n```\n\n### File Tasks\nCreate executable scripts in `mise-tasks/` directory:\n```bash\n#!/usr/bin/env bash\n#MISE description=\"Run tests\"\ncargo test\n```\n\n### Task Features\n- Parallel execution by default\n- Dependency management\n- File watching (`mise watch`)\n- Environment variable passing\n\n## Environment Variables\n\n### Settings\n- `MISE_DATA_DIR` - Where tools are installed (`~/.local/share/mise`)\n- `MISE_CONFIG_DIR` - Config directory (`~/.config/mise`)\n- `MISE_CACHE_DIR` - Cache directory\n- `MISE_GITHUB_TOKEN` - GitHub token for API access\n\n### Tool-specific\n- `MISE_NODE_VERSION=20` - Override node version\n- `MISE_PYTHON_VERSION=3.11` - Override python version\n\n## Common Patterns\n\n### Project Setup\n```bash\n# Initialize project\ncd my-project\nmise use node@20 python@3.11\nmise install\n\n# Add environment variables\nmise set NODE_ENV=development\nmise set DATABASE_URL=postgresql://localhost/myapp\n```\n\n### Global Tools\n```bash\n# Set global defaults\nmise use -g node@lts python@3.11 go@latest\n```\n\n### CI/CD\n```bash\n# Install mise and tools\ncurl https://mise.run | sh\nexport PATH=\"$HOME/.local/bin:$PATH\"\nmise install\nmise run build\n```\n\n## Troubleshooting\n\n### Common Issues\n- **Rate limiting**: Set `MISE_GITHUB_TOKEN` for GitHub API access\n- **Tool not found**: Run `mise doctor` to check setup\n- **Slow performance**: Check `mise cache clear` if stale\n- **Permission errors**: Ensure proper file permissions\n\n### Debugging\n- `mise doctor` - Comprehensive health check\n- `mise config` - Show config file loading order\n- `mise env` - Show current environment\n- `mise which <tool>` - Show tool path resolution\n\n## Plugin System\n\nmise uses plugins to support different tools:\n- Compatible with asdf plugins\n- Automatic plugin installation\n- Custom plugin repositories supported\n- Plugin shortcuts in registry\n\n## Migration from asdf\n\nmise is largely compatible with asdf:\n- Reads `.tool-versions` files\n- Uses asdf plugins\n- Similar commands (with improvements)\n- Can run alongside asdf temporarily\n\n## Best Practices\n\n1. Use `mise.toml` for committed project configuration\n2. Use `mise.local.toml` for local overrides\n3. Activate mise in shell for interactive use\n4. Use shims for CI/CD and IDE integration\n5. Set `MISE_GITHUB_TOKEN` to avoid rate limits\n6. Use `mise doctor` regularly to check setup\n7. Pin versions in production environments\n8. Use tasks for project automation\n\n## Advanced Features\n\n### Tool Options\n```toml\n[tools]\nnode = { version = \"20\", postinstall = \"corepack enable\" }\npython = { version = \"3.11\", virtualenv = \"myproject\" }\n```\n\n### Hooks\n```toml\n[hooks]\nenter = \"mise install --quiet\"\nleave = \"deactivate\"\n```\n\n### Multiple Versions\n```toml\n[tools]\npython = [\"3.10\", \"3.11\", \"3.12\"]  # Install multiple versions\n```\n\n## Development & Contributing\n\n### Setting Up Development Environment\n\nmise is written in Rust and uses itself for development tasks. To contribute to mise:\n\n#### Prerequisites\n- Rust (latest stable)\n- Node.js\n- `pipx` or `uv` \n- Bash (newer than macOS default)\n\n#### Getting Started\n```bash\n# Clone the repository\ngit clone https://github.com/jdx/mise.git\ncd mise\n\n# Install dependencies and build\nmise run build\n\n# Run sanity check\nmise run build\n```\n\n#### Development Setup\nCreate a development shim to easily run mise during development:\n\n```bash\n# Create ~/.local/bin/@mise\n#!/bin/sh\nexec cargo run -q --all-features --manifest-path ~/src/mise/Cargo.toml -- \"$@\"\n```\n\nThen use `@mise` to run the development version:\n```bash\n@mise --help\neval \"$(@mise activate zsh)\"\n```\n\n### Testing\n\nmise has a comprehensive test suite with multiple types of tests to ensure reliability and functionality across different platforms and scenarios.\n\n#### Unit Tests\nUnit tests are fast, focused tests for individual components and functions:\n\n```bash\n# Run all unit tests\ncargo test --all-features\n\n# Run specific unit tests\ncargo test <test_name>\n\n# Run tests with verbose output\ncargo test --all-features -- --nocapture\n\n# Run tests in series (not parallel)\nRUST_TEST_THREADS=1 cargo test --all-features\n```\n\n**Unit test structure:**\n- Located in `src/` directory alongside source code\n- Use Rust's built-in test framework\n- Test individual functions and modules\n- Fast execution (used for quick feedback during development)\n\n#### E2E Tests\nEnd-to-end tests validate the complete functionality of mise in realistic scenarios:\n\n```bash\n# Run all E2E tests\nmise run test:e2e\n\n# Run specific E2E test\n./e2e/run_test test_name\n\n# Run E2E tests matching pattern\n./e2e/run_test task  # runs tests matching *task*\n\n# Run all tests including slow ones\nTEST_ALL=1 mise run test:e2e\n```\n\n**E2E test structure:**\n- Located in `e2e/` directory\n- Organized by functionality:\n  - `e2e/cli/` - Command-line interface tests\n  - `e2e/core/` - Core functionality tests\n  - `e2e/env/` - Environment variable tests\n  - `e2e/tasks/` - Task runner tests\n  - `e2e/config/` - Configuration tests\n  - `e2e/tools/` - Tool management tests\n  - `e2e/shell/` - Shell integration tests\n  - `e2e/backend/` - Backend tests\n  - `e2e/plugins/` - Plugin tests\n\n**E2E test categories:**\n- **Fast tests** (`test_*`): Run in normal test suites\n- **Slow tests** (`test_*_slow`): Only run when `TEST_ALL=1` is set\n- **Isolated environment**: Each test runs in a clean, isolated environment\n\n#### Coverage Tests\nCoverage tests measure how much of the codebase is covered by tests:\n\n```bash\n# Run coverage tests\nmise run test:coverage\n\n# Coverage tests run in parallel tranches for CI\nTEST_TRANCHE=0 TEST_TRANCHE_COUNT=8 mise run test:coverage\n```\n\n#### Windows E2E Tests\nWindows has its own test suite written in PowerShell:\n\n```powershell\n# Run all Windows E2E tests\npwsh e2e-win\\run.ps1\n\n# Run specific Windows tests\npwsh e2e-win\\run.ps1 task  # run tests matching *task*\n```\n\n#### Plugin Tests\nTest plugin functionality across different backends:\n\n```bash\n# Test specific plugin\nmise test-tool ripgrep\n\n# Test all plugins in registry\nmise test-tool --all\n\n# Test all plugins in config files\nmise test-tool --all-config\n\n# Test with parallel jobs\nmise test-tool --all --jobs 4\n```\n\n#### Test Environment Setup\nTests run in isolated environments to avoid conflicts:\n\n```bash\n# Disable mise during development testing\nexport MISE_DISABLE_TOOLS=1\n\n# Run tests with specific environment\nMISE_TRUSTED_CONFIG_PATHS=$PWD cargo test\n```\n\n#### Test Assertions\nThe E2E tests use a custom assertion framework (`e2e/assert.sh`):\n\n```bash\n# Basic assertions\nassert \"command\" \"expected_output\"\nassert_contains \"command\" \"substring\"\nassert_fail \"command\" \"expected_error\"\n\n# JSON assertions\nassert_json \"command\" '{\"key\": \"value\"}'\nassert_json_partial_array \"command\" \"fields\" '[{...}]'\n\n# File/directory assertions\nassert_directory_exists \"/path/to/dir\"\nassert_directory_not_exists \"/path/to/dir\"\nassert_empty \"command\"\n```\n\n#### Running Specific Test Categories\n\n```bash\n# Run all tests (unit + e2e)\nmise run test\n\n# Run only unit tests\nmise run test:unit\n\n# Run only e2e tests\nmise run test:e2e\n\n# Run tests with shuffle (for detecting order dependencies)\nmise run test:shuffle\n\n# Run nightly tests (with bleeding edge Rust)\nrustup default nightly && mise run test\n```\n\n#### Running Single Tests\n\n**Unit Tests:**\n```bash\n# Run a specific unit test by name\ncargo test test_name\n\n# Run tests matching a pattern\ncargo test pattern\n\n# Run tests in a specific module\ncargo test module_name\n\n# Run a single test with output\ncargo test test_name -- --nocapture\n\n# Run a single test file (if organized by file)\ncargo test --test test_file_name\n```\n\n**E2E Tests:**\n```bash\n# Run a specific E2E test by name\n./e2e/run_test test_name\n\n# Run E2E tests matching a pattern\nmise run test:e2e pattern\n\n# Examples:\n./e2e/run_test test_use                    # Run specific test\n./e2e/run_test test_config_set            # Run config-related test\nmise run test:e2e task                     # Run all tests matching \"task\"\n```\n\n**Plugin Tests:**\n```bash\n# Test a specific plugin\nmise test-tool ripgrep\n\n# Test a plugin with verbose output\nmise test-tool ripgrep --raw\n\n# Test multiple plugins\nmise test-tool ripgrep jq terraform\n```\n\n**Windows Tests:**\n```powershell\n# Run a specific Windows test\npwsh e2e-win\\run.ps1 -TestName \"test_name\"\n\n# Run tests matching a pattern\npwsh e2e-win\\run.ps1 task\n```\n\n#### Test Development Tips\n\n1. **Test naming**: Use descriptive names that explain what's being tested\n2. **Test isolation**: Each test should be independent and clean up after itself\n3. **Use slow tests sparingly**: Mark long-running tests as `_slow` to avoid CI timeouts\n4. **Mock external dependencies**: Use dummy plugins and mock data when possible\n5. **Test edge cases**: Include tests for error conditions and boundary cases\n\n#### Performance Testing\n```bash\n# Run performance benchmarks\nmise run test:perf\n\n# Build performance test workspace\nmise run test:build-perf-workspace\n```\n\n#### Snapshot Testing\nUsed for testing output consistency:\n\n```bash\n# Update test snapshots when output changes\nmise run snapshots\n\n# Use cargo-insta for snapshot testing\ncargo insta test --accept --unreferenced delete\n```\n\n### Available Development Tasks\n\nUse `mise tasks` to see all available development tasks:\n\n#### Common Tasks\n- `mise run build` - Build the project\n- `mise run test` - Run all tests (unit + E2E)\n- `mise run test:unit` - Run unit tests only\n- `mise run test:e2e` - Run E2E tests only\n- `mise run lint` - Run linting\n- `mise run lint:fix` - Run linting with fixes\n- `mise run format` - Format code\n- `mise run clean` - Clean build artifacts\n- `mise run snapshots` - Update test snapshots\n- `mise run render` - Generate documentation and completions\n\n#### Documentation Tasks\n- `mise run docs` - Start documentation development server\n- `mise run docs:build` - Build documentation\n- `mise run render:help` - Generate help documentation\n- `mise run render:completions` - Generate shell completions\n\n#### Release Tasks\n- `mise run ci` - Run CI tasks (format, build, test)\n\n### Project Structure\n\n```\nmise/\n├── src/           # Main Rust source code\n├── e2e/           # End-to-end tests\n├── docs/          # Documentation\n├── tasks.toml     # Development tasks\n├── mise.toml      # Project configuration\n├── Cargo.toml     # Rust project configuration\n└── xtasks/        # Additional build scripts\n```\n\n### Pre-commit Hooks & Code Quality\n\nmise uses multiple approaches for ensuring code quality and running pre-commit hooks:\n\n#### hk (Modern Hook Manager)\nmise uses [hk](https://hk.jdx.dev) (pronounced \"hook\") as its primary hook manager for linting and code quality checks. hk is a modern alternative to lefthook written by the same author as mise.\n\n**hk Configuration:**\nThe project uses `hk.pkl` (written in the Pkl configuration language) to define linting rules:\n\n```bash\n# Run all linting checks\nhk check --all\n\n# Run linting with fixes\nhk fix --all\n\n# Run specific linter\nhk check --step shellcheck\n```\n\n**Available Linters in hk:**\n- **prettier**: Code formatting for multiple languages\n- **clippy**: Rust linting with `cargo clippy`\n- **shellcheck**: Shell script linting\n- **shfmt**: Shell script formatting\n\n**Using hk in Development:**\n```bash\n# Install hk via mise\nmise use hk\n\n# Run linting (used in CI and pre-commit)\nmise run lint  # This runs hk check --all\n\n# Run linting with fixes\nhk fix --all\n\n# Check specific file types\nhk check --step prettier\nhk check --step shellcheck\n```\n\n#### Traditional Pre-commit Hooks (Alternative)\nmise also supports traditional pre-commit hooks through multiple methods:\n\n**Option 1: Using lefthook (Legacy)**\n```bash\n# Install lefthook\nmise use lefthook\n\n# Install the git hooks\nlefthook install\n\n# Run pre-commit manually\nlefthook run pre-commit\n```\n\n**Option 2: Using standard pre-commit framework**\n```bash\n# Install pre-commit\nmise use pre-commit\n\n# Install the git hooks\npre-commit install\n\n# Run pre-commit manually\npre-commit run --all-files\n```\n\n**Option 3: Using mise's built-in git hook generation**\n```bash\n# Generate a git pre-commit hook that runs mise tasks\nmise generate git-pre-commit --write --task=pre-commit\n\n# This creates .git/hooks/pre-commit that runs:\n# mise run pre-commit\n```\n\n#### Pre-commit Task Configuration\nmise defines a `pre-commit` task that runs the main linting checks:\n\n```toml\n[pre-commit]\nenv = { PRE_COMMIT = 1 }\nrun = [\"mise run lint\"]\n```\n\nThis task:\n1. Sets `PRE_COMMIT=1` environment variable\n2. Runs `mise run lint`, which executes `hk check --all`\n\n#### Setting Up Pre-commit Hooks\n**Recommended approach using hk:**\n```bash\n# Install hk\nmise use hk\n\n# Set up git hook to run mise's pre-commit task\nmise generate git-pre-commit --write --task=pre-commit\n\n# Or manually create .git/hooks/pre-commit:\ncat > .git/hooks/pre-commit << 'EOF'\n#!/bin/sh\nexec mise run pre-commit\nEOF\nchmod +x .git/hooks/pre-commit\n```\n\n**Alternative approach using standard pre-commit:**\n```bash\n# Install pre-commit\nmise use pre-commit\n\n# Install hooks defined in .pre-commit-config.yaml\npre-commit install\n```\n\n#### Running Pre-commit Checks Manually\n```bash\n# Run all pre-commit checks\nmise run pre-commit\n\n# Run specific linting checks\nmise run lint\n\n# Run linting with fixes\nhk fix --all\n\n# Run checks on specific files\nhk check --files=\"src/**/*.rs\"\n```\n\n#### Environment Variables for Hooks\nWhen hooks run, they have access to these environment variables:\n- `PRE_COMMIT=1`: Indicates the code is running in pre-commit context\n- `STAGED`: Git staged files (when using mise's git hook generation)\n- `MISE_PRE_COMMIT=1`: Set by mise's generated git hooks\n\n### Testing Configuration\n\n- **Unit tests**: Fast tests for individual components\n- **E2E tests**: Integration tests that test the full application\n- **Slow tests**: Only run with `TEST_ALL=1` environment variable\n- **Windows tests**: Separate PowerShell-based test suite\n\n### Development Tips\n\n1. **Disable mise during development**: If you use mise in your shell, disable it when running tests to avoid conflicts\n2. **Use dev container**: Docker setup available (currently needs fixing)\n3. **Test specific features**: Use `cargo test <test_name>` for targeted testing\n4. **Update snapshots**: Use `mise run snapshots` when changing test outputs\n5. **Rate limiting**: Set `MISE_GITHUB_TOKEN` to avoid GitHub API rate limits during development\n\n### Dependency Management\n\nmise uses several tools to validate dependencies and code quality:\n\n- **cargo-deny**: Validates licenses, security advisories, and dependency duplicates\n- **cargo-msrv**: Verifies minimum supported Rust version compatibility\n- **cargo-machete**: Detects unused dependencies in Cargo.toml\n\nThese checks run automatically in CI and can be run locally:\n```bash\n# Install tools\nmise use cargo-deny cargo-msrv cargo-machete\n\n# Run checks\ncargo deny check\ncargo msrv verify\ncargo machete --with-metadata\n```\n\n### Contributing Guidelines\n\n1. **Before starting**: File an issue or discuss in Discord for non-obvious changes\n2. **Look for issues**: Check \"help wanted\" and \"good first issue\" labels\n3. **Test thoroughly**: Ensure both unit and E2E tests pass\n4. **Follow conventions**: Use existing code style and patterns\n5. **Update documentation**: Add/update docs for new features\n\n#### Pull Request Workflow\n1. **PR titles**: Must follow conventional commit format (validated automatically)\n2. **Auto-formatting**: Code will be automatically formatted by autofix.ci\n3. **CI checks**: All tests must pass across Linux, macOS, and Windows\n4. **Coverage**: New code should maintain or improve test coverage\n5. **Dependencies**: New dependencies are validated with cargo-deny\n\n#### GitHub Actions Development\nIf modifying GitHub Actions workflows:\n- Run `mise run lint` for the repository's configured checks\n- Self-hosted runners are configured for performance testing\n- Run the zizmor workflow for security auditing\n\n### Conventional Commits\n\nmise uses [Conventional Commits](https://www.conventionalcommits.org/) for consistent commit messages and automated changelog generation. All commits should follow this format:\n\n```\n<type>[optional scope]: <description>\n\n[optional body]\n\n[optional footer(s)]\n```\n\n#### Commit Types\n\n- **feat**: New features (🚀 Features)\n- **fix**: Bug fixes (🐛 Bug Fixes)\n- **refactor**: Code refactoring (🚜 Refactor)\n- **doc**: Documentation changes (📚 Documentation)\n- **style**: Code style changes (🎨 Styling)\n- **perf**: Performance improvements (⚡ Performance)\n- **test**: Testing changes (🧪 Testing)\n- **chore**: Maintenance tasks, dependency updates\n- **revert**: Reverting previous changes (◀️ Revert)\n\n#### Examples\n\n```bash\nfeat(cli): add new command for listing plugins\nfix(parser): handle edge case in version parsing\nrefactor(config): simplify configuration loading logic\ndoc(readme): update installation instructions\ntest(e2e): add tests for new plugin functionality\nchore(deps): update dependencies to latest versions\n```\n\n#### Scopes\n\nCommon scopes used in mise:\n- `cli` - Command line interface changes\n- `config` - Configuration system changes\n- `parser` - Parsing logic changes\n- `deps` - Dependency updates\n- `security` - Security-related changes\n\n#### Breaking Changes\n\nFor breaking changes, add `!` after the type or include `BREAKING CHANGE:` in the footer:\n\n```bash\nfeat(api)!: remove deprecated configuration options\n# OR\nfeat(api): remove deprecated configuration options\n\nBREAKING CHANGE: The old configuration format is no longer supported\n```\n\n### Packaging Testing\n\nFor testing package installation:\n\n#### Ubuntu/Debian\n```bash\n# Test apt installation\ndocker run -ti --rm ubuntu\napt update -y && apt install -y curl\n# ... installation steps\n```\n\n#### Fedora\n```bash\n# Test dnf installation  \ndocker run -ti --rm fedora\ndnf install -y dnf-plugins-core\n# ... installation steps\n```\n\n### CI/CD & Pull Request Automation\n\nmise uses several automated workflows to maintain code quality and streamline development:\n\n#### Automated Code Formatting\n- **autofix.ci**: Automatically formats code and fixes linting issues in PRs\n- Runs `mise run render` and `mise run lint-fix` automatically\n- Commits fixes directly to the PR branch\n\n#### PR Title Validation\n- **semantic-pr-lint**: Validates PR titles follow conventional commit format\n- PR titles must match: `<type>[optional scope]: <description>`\n- Example: `feat(cli): add new command for listing plugins`\n\n#### Continuous Integration\n- **Cross-platform testing**: Ubuntu, macOS, and Windows\n- **Unit tests**: Fast component-level tests\n- **E2E tests**: Full integration testing with multiple test tranches\n- **Coverage testing**: Code coverage across 8 parallel test runs\n- **Dependency validation**: `cargo deny`, `cargo msrv`, `cargo machete`\n\n#### Release Automation\n- **release-plz**: Automated release management based on conventional commits\n- Automatically creates release PRs and publishes releases\n- Runs daily via scheduled workflow\n- Handles version bumping and changelog generation\n\n## mise Codebase Architecture\n\n### Overview\n\nmise is a Rust-based tool with a modular architecture designed around three main concepts:\n1. **Tool Version Management** - Managing different versions of development tools\n2. **Environment Management** - Setting up environment variables and project contexts\n3. **Task Running** - Executing project tasks with dependency management\n\n### Core Architecture Components\n\n#### 1. **Main Entry Point** (`src/main.rs`)\n- Asynchronous Tokio runtime with multi-threading\n- Global error handling and panic hooks\n- CLI argument parsing and routing\n- Multi-progress reporting system\n\n#### 2. **CLI Layer** (`src/cli/`)\n- **Command Structure**: Each command is a separate module (e.g., `install.rs`, `use.rs`, `run.rs`)\n- **Argument Parsing**: Uses `clap` for command-line argument handling\n- **Command Execution**: Async command execution with proper error handling\n- **Key Commands**:\n  - `install` - Install tool versions\n  - `use` - Add tools to configuration\n  - `run` - Execute tasks\n  - `env` - Environment management\n  - `shell` - Shell integration\n\n#### 3. **Backend System** (`src/backend/`)\nThe backend system is the core abstraction for tool management:\n\n**Backend Trait**: Common interface for all tool backends\n```rust\npub trait Backend: Debug + Send + Sync {\n    async fn list_remote_versions(&self) -> Result<Vec<String>>;\n    async fn install_version(&self, ctx: &InstallContext, tv: &ToolVersion) -> Result<()>;\n    async fn uninstall_version(&self, tv: &ToolVersion) -> Result<()>;\n    // ... other methods\n}\n```\n\n**Backend Types**:\n- **Core Backends**: Built-in support (Node.js, Python, etc.)\n- **ASDF Backends**: External plugin system compatibility\n- **Aqua Backends**: Package manager integration\n- **Language-specific**: npm, cargo, pipx, gem, go, etc.\n- **Universal**: ubi (GitHub releases)\n\n#### 4. **Configuration System** (`src/config/`)\n**Hierarchical Configuration**:\n- `Config` struct manages all configuration sources\n- `ConfigFile` trait for different config formats:\n  - `MiseToml` - Main configuration format\n  - `ToolVersions` - ASDF compatibility\n  - `IdiomaticVersion` - Language-specific files (`.nvmrc`, `.python-version`)\n\n**Configuration Hierarchy**:\n1. System config (`/etc/mise/config.toml`)\n2. Global config (`~/.config/mise/config.toml`)\n3. Project configs (searched up directory tree)\n4. Environment-specific configs (`mise.dev.toml`)\n\n#### 5. **Toolset Management** (`src/toolset/`)\n**Core Components**:\n- `Toolset` - Collection of tools for a specific context\n- `ToolVersion` - Represents a specific version of a tool\n- `ToolRequest` - User request for a tool (e.g., `node@18`)\n- `ToolsetBuilder` - Constructs toolsets from configuration\n\n**Tool Resolution Flow**:\n1. Parse configuration files\n2. Resolve version specifications\n3. Build toolset with dependencies\n4. Install missing tools\n5. Set up environment\n\n#### 6. **Task System** (`src/task/`)\n**Task Components**:\n- `Task` struct with metadata, dependencies, and execution info\n- `Deps` - Dependency graph management using petgraph\n- `TaskFileProvider` - Discovers tasks from files and configuration\n- Parallel execution with dependency resolution\n\n**Task Types**:\n- **TOML Tasks**: Defined in `mise.toml`\n- **File Tasks**: Executable scripts in task directories\n- **Command Tasks**: Simple command execution\n- **Script Tasks**: Inline script execution\n\n#### 7. **Plugin System** (`src/plugins/`)\n**Plugin Architecture**:\n- `Plugin` trait for extensibility\n- `AsdfPlugin` - ASDF plugin compatibility\n- `VfoxPlugin` - Vfox plugin system\n- `ScriptManager` - Manages plugin scripts\n\n**Plugin Types**:\n- **Core Plugins**: Built into mise\n- **External Plugins**: Downloaded from repositories\n- **Local Plugins**: Custom local implementations\n\n#### 8. **Shell Integration** (`src/shell/`)\n**Shell Support**:\n- Bash, Zsh, Fish, PowerShell support\n- `Shell` trait for shell-specific behavior\n- Activation scripts for environment setup\n- Hook system for directory changes\n\n#### 9. **Environment Management** (`src/env*.rs`)\n**Environment Components**:\n- `EnvDiff` - Tracks environment changes\n- `EnvDirective` - Configuration for environment variables\n- `PathEnv` - PATH management\n- Context-aware environment resolution\n\n#### 10. **Caching System** (`src/cache.rs`)\n**Cache Management**:\n- `CacheManager` - Generic caching with TTL\n- File-based caching for versions, metadata\n- Automatic cache invalidation\n- Per-backend cache isolation\n\n### Key Design Patterns\n\n#### 1. **Trait-Based Architecture**\n- `Backend` trait for tool management\n- `ConfigFile` trait for configuration formats\n- `Shell` trait for shell integration\n- `Plugin` trait for extensibility\n\n#### 2. **Async/Await Throughout**\n- Tokio runtime for async operations\n- Parallel tool installations\n- Concurrent task execution\n- Non-blocking I/O operations\n\n#### 3. **Error Handling**\n- `eyre` crate for error management\n- Structured error types\n- Context-aware error reporting\n- Graceful fallback behavior\n\n#### 4. **Configuration Hierarchy**\n- Multiple configuration sources\n- Inheritance and overrides\n- Environment-specific configurations\n- Validation and trust system\n\n#### 5. **Dependency Management**\n- Tool dependencies (e.g., Node.js for npm tools)\n- Task dependencies with DAG resolution\n- Parallel execution with proper ordering\n- Circular dependency detection\n\n### Data Flow\n\n1. **Initialization**: Load configuration hierarchy\n2. **Tool Discovery**: Find available backends and versions\n3. **Resolution**: Resolve tool requests to specific versions\n4. **Installation**: Install missing tools in dependency order\n5. **Environment Setup**: Configure PATH and environment variables\n6. **Execution**: Run tasks or provide shell integration\n\n### Testing Architecture\n\n**Test Structure**:\n- **Unit Tests**: Component-level testing with mocks\n- **Integration Tests**: End-to-end CLI testing\n- **E2E Tests**: Real-world scenario testing\n- **Snapshot Tests**: Output comparison testing\n\n**Test Organization**:\n- `src/` - Unit tests alongside source code\n- `e2e/` - End-to-end test scripts\n- `test/` - Test fixtures and utilities\n- `src/snapshots/` - Snapshot test data\n\nThis architecture provides a flexible, extensible foundation for managing development environments while maintaining compatibility with existing tools and workflows.\n\nThis covers the essential information about mise for LLMs to help users effectively use the tool for development environment management and contribute to its development.\n","AGENTS.md":"# Repository Agent Guide\n\nThis file is the canonical agent guide. `CLAUDE.md` is a symlink to `AGENTS.md` for compatibility with existing tooling.\n\nTask-specific procedures live as skills in `.agents/skills/` (`.claude/skills` is a symlink to it). Load the named skill when this guide points to one; agents without skill support can read its `SKILL.md` directly.\n\n## Discussions and Issues: Restricted AI Replies\n\n**Do not use AI to reply to a mise Discussion or Issue unless the user (a) created that Discussion or Issue, (b) opened a PR that fixes it, or (c) has already had a contribution merged into the default branch of mise.** Otherwise they are not allowed to use AI to respond to it. Drive-by AI replies are spam, the problem is getting worse, and **doing it is an instant ban across all of jdx's projects** (mise, hk, pitchfork, usage, fnox, and the rest).\n\n- If the user asks you to answer, comment on, or \"help with\" a Discussion or Issue, confirm one of the three conditions first. If you cannot confirm one, **do not post**.\n  - (a) Compare the thread author to the authenticated user (`gh api user --jq .login`). For an Issue, use `gh api repos/jdx/mise/issues/<number> --jq .user.login`. Discussions have no REST endpoint, so use GraphQL: `gh api graphql -f query='query{repository(owner:\"jdx\",name:\"mise\"){discussion(number:<number>){author{login}}}}' --jq .data.repository.discussion.author.login`.\n  - (b) Check that the user's PR actually fixes the problem described in the thread. A closing keyword such as `Fixes #<number>` is good evidence, but a link is not required, and a PR that merely mentions an unrelated thread does not count.\n  - (c) Look for any contribution merged into the default branch that is tied to the user's GitHub account, not just a matching name or email: a PR authored by the user that was merged into the default branch (`gh pr list --repo jdx/mise --author @me --state merged --base main --limit 1`), commits on the default branch that GitHub attributes to their login (`gh api 'repos/jdx/mise/commits?author=<login>&per_page=1'` lists the default branch), never commits on a local or unmerged branch, or a PR from someone else, merged into the default branch, that credits them with a `Co-authored-by` trailer whose email is their GitHub noreply address or one verified on their account. Do not accept `git log --author` output, which includes local unmerged commits, or a trailer matched only by display name. Both queries filter by author on the server, so one matching result is enough to qualify and no pagination is needed.\n- If none of the three apply, **do not post a reply, even a short one.** Tell them this project does not allow AI replies from people who have not contributed, and offer to explain the answer to them in chat instead.\n- Never batch-post, loop over, or sweep Discussions or Issues to answer several of them, even for a merged contributor.\n- Lightly edited, human-reviewed, or disclosed model output does not create an exception. The disclosure footer does not make an AI reply acceptable on its own.\n- Permitted replies may be AI-assisted. The user must review and verify the reply before it is posted.\n- Creating a new Discussion or Issue with AI assistance is fine and is not restricted. The user must review it before it is posted, and it needs the AI disclosure below.\n\nWhen you post AI-contributed GitHub content, including a new Discussion or Issue, a reply, or a PR description or comment, append this disclosure: `*AI-assisted — Tool: <tool>; model: <provider>/<model>; version: <version-or-unavailable>.*` Use the exact model and version identifiers exposed by the runtime, never guessed values, and `unavailable` when one is not exposed.\n\n## Registry Submissions: READ THIS FIRST\n\n**Most new registry additions from agents get rejected.** mise's `registry/` is curated for tools that are already widely used — generally thousands of GitHub stars, not hundreds. jdx closes PRs that miss the bar without giving a reason.\n\nBefore adding a **new** tool or shorthand to `registry/`, follow the `registry-submission` skill ([`.agents/skills/registry-submission/SKILL.md`](.agents/skills/registry-submission/SKILL.md)). In short:\n\n- Warn the user about the bar, look up real popularity numbers, and stop if the tool is personal, internal, a fork, or niche.\n- Put a `## Popularity` section with those numbers in the PR description.\n- Confirm `mise ls-remote <backend>` lists installable versions.\n- Prefer `packslip:`, then `aqua:`, `github:`, or `gitlab:`. `conda:` has a high bar; `npm:`, `pipx:`, `gem:`, `cargo:`, `go:`, and `dotnet:` are almost never accepted. New `asdf:`, `vfox:`, and `ubi:` entries are not accepted.\n- Users can install any tool without a registry entry (`mise use github:owner/repo`, `mise use cargo:name`, …); the registry only adds a shorthand.\n\nNone of this applies to editing an existing registry entry; do not ask the user about popularity for maintenance or fixes.\n\n## Development Commands\n\n### Building and Testing\n- `mise run build` or `mise run b` - Build the project with cargo\n- `target/debug/mise` - Run the built binary directly\n- `mise run test` or `mise run t` - Run all tests (unit + e2e)\n- `mise run test:unit` - Run unit tests only\n- `mise run test:e2e` - Run end-to-end tests only\n- `mise run snapshots` - Update test snapshots with `cargo insta`\n\n### Debugging\n- Use `MISE_DEBUG=1` or `MISE_TRACE=1` environment variables to enable debug output (not `RUST_LOG`)\n\n### Code Quality and Testing\n- `mise run lint` - Run all linting tasks (hk; does not run clippy — see below)\n- `mise run lint-fix` - Run linting and automatically fix issues\n- `mise run format` - Format code (part of CI task)\n- `mise run ci` - Run format, build, and test\n- `mise run test:e2e [test_filename]...` - Run specific e2e tests (use this instead of executing test files directly)\n- `mise --cd crates/vfox run test` - Run tests for the vfox crate\n- `mise --cd crates/vfox run lint` - Run linting for the vfox crate\n- `mise --cd crates/vfox run lint-fix` - Run linting and fix issues for the vfox crate\n- `mise task ls` - List all available tasks\n\n### Clippy Exclusions\n\n- Do not add `#[allow(clippy::...)]`, `#[expect(clippy::...)]`, Cargo lint levels set to `allow`, or `-A clippy::...` command-line flags.\n- Refactor the code so `cargo clippy --workspace --all-features --all-targets -- -D warnings` passes without exclusions.\n- `mise run lint` does not cover this: the clippy step in `hk.pkl` is disabled, and `cargo check` does not enforce `-D warnings`. CI runs clippy separately, so run the command above yourself before pushing Rust changes.\n- If a feature or fix needs a preparatory refactor to satisfy Clippy cleanly, put that refactor in a prerequisite PR and stack the behavior change on top of it.\n\n### Documentation and Generation\n- `mise run render` - Generate all documentation and completions\n- `mise run render:usage` - Generate CLI usage documentation\n- `mise run render:completions` - Generate shell completions\n- `mise run docs` - Start documentation dev server\n- `mise run docs:build` - Build documentation\n\n### Development\n- `mise run install-dev` - Install development version locally\n- `mise run clean` - Clean cargo build artifacts\n\n## Code Architecture\n\n### High-Level Structure\nMise is a Rust CLI tool that manages development environments, tools, tasks, and environment variables. The codebase follows a modular architecture:\n\nThe `mise` package has two targets. The library (`src/lib.rs`) is everything except the command line; the binary (`src/main.rs` plus `src/cli/`) sits on top of it and glob-imports its root, so `cli` code still writes `crate::config::…`. An edit under `src/cli/` recompiles only the binary. Core code must not refer to `crate::cli`: it reaches command behavior through the hooks in `src/frontend.rs`. When `cli` needs a core item, make that item `pub`; `unreachable_pub` keeps everything else `pub(crate)`. `cfg(test)` does not reach the library from the binary's tests, so core code that behaves differently under tests checks `mise_util::testing::in_tests()` instead.\n\n**Core Components:**\n- `src/main.rs` - Binary entry point\n- `src/lib.rs` - Library root: module list and the hooks lower crates need\n- `src/cli/` - Command-line interface implementation with subcommands (binary only)\n- `src/config/` - Configuration file parsing and management\n- `src/backend/` - Tool backend implementations (aqua, github, cargo, npm, asdf, vfox, …)\n- `src/toolset/` - Tool version management and installation logic\n- `src/task/` - Task execution system\n- `src/plugins/` - Plugin system for extending tool support\n\n**Key Backend Systems** (`src/backend/`):\n- `packslip.rs` — Signed release manifests (preferred for new registry entries)\n- `aqua.rs` — Aqua registry\n- `github.rs` — GitHub / GitLab / Forgejo releases\n- `http.rs`, `s3.rs` — HTTP and S3 backends\n- `cargo.rs`, `npm.rs` (plus embedded aube), `pipx.rs`, `gem.rs`, `go.rs`, `dotnet.rs`, `conda.rs`, `spm.rs`\n- `asdf.rs`, `vfox.rs` — plugin compatibility layers\n- `ubi.rs` — deprecated; do not add new registry entries\n\n**Core Tools (Built-in):**\n- `src/plugins/core/` — Node, Python, Go, Ruby, Java, Bun, Deno, Elixir, Erlang, Dotnet, Swift, Zig, Rust\n\n**Configuration System:**\n- `mise.toml` files for project configuration\n- `.tool-versions` files for ASDF compatibility\n- Environment variable management and templating\n- Task definition and execution\n\n### Key Design Patterns\n1. **Backend Architecture**: Tools are implemented through a unified backend interface, allowing multiple sources (ASDF plugins, vfox plugins, cargo, npm, etc.)\n2. **Toolset Management**: The `Toolset` manages collections of tool versions and their installation state\n3. **Configuration Layering**: Config files are loaded hierarchically from system → global → local with environment-specific overrides\n4. **Task System**: Tasks can be defined in TOML files with dependencies, environment variables, and multiple execution modes\n\n### Configuration Files\n- `mise.toml` - Main configuration file format\n- `settings.toml` - Global settings definitions (generates code/docs)\n- `registry/` - Tool registry mappings\n- `tasks.toml` - Project task definitions\n\n### Test Structure\n- Unit tests within source files\n- E2E tests in `e2e/` directory organized by feature area (e.g., `e2e/cli/`, `e2e/backend/`)\n- E2E tests are bash scripts using assertion helpers from `e2e/assert.sh` (e.g., `assert`, `assert_contains`, `assert_fail`)\n- E2E tests do not need cleanup steps (rm, etc.) — the test harness handles that\n- Snapshot tests using `insta` crate for CLI output verification\n- Windows-specific tests in `e2e-win/`\n\n### Build System\n- Rust project using a Cargo workspace; member crates live in `crates/` (`vfox`, `aqua-registry`, `mise-shim`, `mise-sigstore`, `mise-cache-core`, `mise-tls`, `mise-brew-relocation`, `mise-brew-metadata`, `mise-agent-env`, `mise-interactive-config`, `mise-settings`, `mise-util`, `mise-ui`, `mise-system-packages`, `mise-config`, `mise-system`, `mise-oci`, `mise-daemons`, `mise-lsp`)\n- Custom build script in `build.rs` for generating metadata\n- Multiple build profiles including `release` and `serious` (with LTO)\n- Cross-compilation support via `Cross.toml`\n\n## Development Guidelines\n\n### Conventional Commits (REQUIRED)\nPR titles MUST follow conventional commit format. Intermediate commit subjects\nSHOULD use the same format:\n\n**Format:** `<type>[optional scope][optional !]: <description>`\n\n**Types:**\n- `feat:` - New features\n- `fix:` - Bug fixes that affect the CLI behavior (not CI, docs, or infrastructure)\n- `refactor:` - Code refactoring\n- `docs:` - Documentation changes\n- `style:` - Code style/formatting (no logic changes)\n- `perf:` - Performance improvements\n- `test:` - Testing changes\n- `chore:` - Maintenance tasks, releases, dependency updates, CI/infrastructure changes\n- `security:` - Security-related changes\n- `registry:` - Any changes to `registry/` (do not add a scope)\n- `ci:` - CI and automation changes\n- `revert:` - Reverting a previous change\n\n**Scopes:**\n- For command-specific changes, use the command name: `install`, `activate`, `use`, `exec`, etc.\n- For subsystem changes: `config`, `backend`, `env`, `task`, `vfox`, `python`, `github`, `release`, `completions`, `http`, `schema`, `doctor`, `shim`, `core`, `deps`, `ci`\n- Use `task` (not `run`) for task-related changes, even if the code lives in `src/cli/run.rs` or `src/cmd.rs`\n\n**Description Style:**\n- Start the description with a lowercase character, or with an acronym such as `PGO` or `CLI`\n- Use imperative mood (\"add feature\" not \"added feature\")\n- Keep it concise but descriptive\n\n**Examples:**\n- `fix(install): resolve version mismatch for previously installed tools`\n- `feat(activate): add fish shell support`\n- `feat(vfox): add semver Lua module for version sorting`\n- `feat(env): add environment caching with module cacheability support`\n- `docs(contributing): update hk usages`\n- `chore: release 2026.1.6`\n- `chore(ci): add FORGEJO_TOKEN for API authentication`\n- `registry: add miller`\n\nCI validates the pull request title and re-runs when it is edited. Intermediate\ncommit subjects are not checked because pull requests are squash-merged. CI\nmechanically checks the allowed type, syntax, and lowercase- or acronym-leading description;\nimperative mood and breaking-change details remain review rules.\n\n### PR titles and descriptions are release-note inputs\n\nCommunique generates release notes from PR titles and descriptions, so write them for a mise user who has not read the diff: lead with the user-visible problem and outcome, show a concrete example, and keep them in sync with the final diff. Follow the `pr-description` skill ([`.agents/skills/pr-description/SKILL.md`](.agents/skills/pr-description/SKILL.md)) when opening or revising a PR.\n\n### Pre-commit Process\n1. Run `mise run lint-fix` and `git add` any lint fixes before committing\n2. Use `mise run test:e2e [test_filename]...` for running specific e2e tests\n3. Never run e2e tests by executing them directly — always use the mise task\n\n`hk.pkl` defines `check` and `fix` steps and a git `pre-commit` hook that runs the same linters with auto-fix (`stash = \"git\"` preserves unstaged work). `hk install --mise` installs that hook. You can still run `mise run lint` / `mise run lint-fix` by hand; on Linux and macOS they run hk, but on Windows `lint-fix` runs only Clippy, oxfmt, and `cargo fmt`, so the other hk steps do not run there.\n\n### hk Agent Workflow\n\n- Prefer the hk MCP server for effect-aware plans, checks, fixes, logs, and captured diffs.\n- When invoking hk directly, use `hk run check --safe --format json` for a complete machine-readable result or `--format jsonl` for streaming lifecycle events.\n- Scope checks to changed files. For an exact file list, pass NUL-delimited paths with `--files0-from`; use `--cd` to target another project directory.\n- Never run a command classified as unknown or destructive without explicit user approval. Review the resulting diff after fixes.\n\n### Dependency Updates\n\n- Use the lowest-specificity dependency requirement that expresses compatibility in `Cargo.toml` (for example, prefer `\"1\"` over `\"1.2.3\"`, and `\"0.12\"` over `\"0.12.1\"` for a pre-1.0 crate).\n- Routine dependency updates should only change `Cargo.lock`. If the existing `Cargo.toml` requirement accepts the target version, do not change it merely to force or record the update; use `cargo update -p <crate> --precise <version>` instead.\n- Keep lockfile updates focused on the requested dependency and its required transitive changes. Remove unrelated resolver churn before committing.\n\nWhen updating the embedded `aube` crates, follow the `update-aube` skill ([`.agents/skills/update-aube/SKILL.md`](.agents/skills/update-aube/SKILL.md)).\n\n## Deprecation Policy\n\nWhen deprecating a feature, backend, or implicit behavior:\n\n1. **Immediately**: Mark it as deprecated in docs (add a warning banner) and display a CLI warning using the `deprecated_at!` macro from `src/output.rs` (`warn_at` is the current version).\n2. **12 months after warn** (`remove_at`): `debug_assert!` in `deprecated_at!` fires, signaling the deprecated code or behavior should be removed.\n\n12 months is the default window, not a hard rule. Some deprecations use a shorter window, such as 6 months, on purpose. Use 12 months for new deprecations unless jdx asks for something else, and do not lengthen an existing shorter window.\n\nDelay the CLI warning for up to 6 months only when migration requires a new setting, syntax, or replacement that older supported mise versions would reject or fail to parse. This compatibility window lets users adopt a configuration that works across old and new clients before warnings begin. Do not delay warnings for a behavior change that requires no new configuration, or when the replacement already works in older clients.\n\nUse mise version format for dates (e.g., `deprecated_at!(\"2026.10.0\", \"2027.10.0\", \"id\", \"message\")`).\n\nIf a compatibility window is required, removal remains 12 months after `warn_at`, not 12 months after the initial documentation notice.\n\nFor temporary code with no user-facing deprecation, such as a migration or a fallback that reads what an older mise wrote, use `remove_by!(\"2027.1.0\", \"id\")` from `src/output.rs`. It is a compile-time assertion, so the build fails once the version reaches `remove_at`; remove every `remove_by!` with that id and the code it guards.\n\n## Important Implementation Notes\n\n### Backend System\nWhen implementing new tool backends, follow the pattern in `src/backend/mod.rs`. Each backend must implement the `Backend` trait with methods for listing versions, installing tools, and managing tool metadata.\n\n### DO NOT ASSUME SEMVER\n**Do not assume tool versions follow semver or any other orderable scheme.** mise manages hundreds of tools with wildly different versioning conventions:\n\n- Date-based: `2024.01.15`, `20241015`\n- Pre-release / ref / tag versions: `tip`, `HEAD`, `nightly`, `edge`, `canary`, `ref:main`, `tag:v1`, `sub-X.Y:...`\n- Non-numeric tags: Python `3.12.0a1`, Ruby `3.2.0-preview1`, Go `1.22rc1`, Node `lts/hydrogen`, `lts-iron`\n- Tool-specific meanings of `latest` (e.g. some exclude pre-releases, some don't)\n\n**Rules:**\n1. Do not call `versions::Versioning::new(...)` (or any other semver comparator) at a new call site to pick the \"newest\" version, \"resolve latest\", or sort a version list. That crate silently returns `None` / arbitrary ordering for non-semver strings, which means wrong versions get chosen for many tools.\n2. To resolve a version request (`latest`, a prefix, a channel name), delegate to the backend via `Backend::latest_version`, `Backend::latest_installed_version`, `Backend::list_versions_matching`, or `ToolRequest::resolve` — the backend knows what \"latest\" means for its tool.\n3. To list installed versions in a meaningful order, use `Backend::list_installed_versions_matching` or the toolset's resolved versions. Do not reorder them yourself.\n4. Lockfile version strings must be treated as opaque — compare with `==`, never with a version ordering. Never write a non-concrete string (`latest`, `lts/*`, a prefix) into the lockfile; resolve first.\n\nA few existing call sites (e.g. runtime symlinks) do use `Versioning` ordering today, but that's legacy behavior and arguably also wrong — do not point at them to justify new semver assumptions.\n\nIf you think you need to pick \"the newest installed version\" at a new call site, stop and ask — that call almost always belongs on the backend, not inline.\n\n### Paranoid mode categories\n`paranoid` is a bool or a list of categories (`config`, `env_files`, `plugins`, `provenance`), defined by `Paranoid` in `crates/mise-settings/src/paranoid.rs`. Any new behavior gated on paranoid mode must belong to one of those categories, or introduce a new named category, so it is individually selectable. New code must never read paranoid as a plain bool: call `settings.paranoid.config()`, `.env_files()`, `.plugins()` or `.provenance()`, and add an e2e test that the category works alone.\n\n### Plugin Development\n- Core tools are implemented in `src/plugins/core/`\n- External plugins use ASDF or vfox compatibility layers\n- Plugin metadata is defined in `mise.plugin.toml` files\n\n### Configuration Parsing\nThe configuration system supports multiple file formats and environment-specific configs. Changes to settings require updating `settings.toml` and running `mise run render:schema`. The `Settings` types are generated from `settings.toml` in `crates/mise-settings`; loading them (config discovery, trust, CLI flags) stays in `src/config/settings.rs`, whose `SettingsExt` trait holds the methods that need the rest of mise.\n\n`schema/mise.json`, `schema/mise-task.json` and `schema/miserc.json` are generated from `crates/mise-config` and `settings.toml`: never edit the JSON. Change the Rust, then run `mise run render:schema`; a `mise-config` test fails while the committed files are stale. The top-level keys are the fields of `MiseTomlDecl` in `crates/mise-config/src/mise_toml.rs`, which `MiseToml` deserializes through: a new key goes in `MiseTomlDecl`, and `MiseToml::from_decl` moves it into `MiseToml`. Sections whose types derive `JsonSchema` (so far `[bootstrap]`, `[daemons_settings]`, `[daemon_groups]`, `[doctor]`, `[history]`, `[monorepo]`, `[oci]`, `[task_config]`, `[tasks]`, `[task_templates]`, `[tool_config]` and `[wrappers]`) are generated from those types and their doc comments. `[env]` and `[vars]` accept shapes a derive cannot parse, so `env.rs` reads them with visitors; their schema is derived from the `Env*` and `Vars*` declaration types in `crates/mise-config/src/env/decl.rs`, which describe the tables and nothing parses into them, and a test checks that the option keys they declare are the fields of `EnvDirectiveOptions`. `[[watch_files]]`, `[tool_alias]` and `min_version` have a hand-written `JsonSchema` impl in `watch_files.rs`, `alias.rs` and `min_version.rs`. Task fields with several accepted shapes (a string or a list, a name or a table, ...) take theirs from the declaration types in `crates/mise-config/src/task/shapes.rs`, which `TaskDecl` and `TaskConfig` attach with `schemars(with = ..)` so the runtime field types stay as they are; nothing parses into those types, so change them together with the parser. `task/schema.rs` composes the rest: the `task` definition, a task's `tools` (which follow the backend table of `[tools]`) and the template schema. `[tools]` picks per-backend options by key pattern: a backend's options are the declaration types in `crates/mise-config/src/tools/decl.rs` (a new option is a field with a doc comment, which is its description), and `crates/mise-config/src/tools/schema.rs` composes them, with one table row per backend and per platform table. mise reads these definitions by name to reject unknown options (`OptionSpec`), so change them together with `ToolVersionOptions::insert_option` and the backend's option reader. `[hooks]` is derived from the `Hook*` declaration types in `crates/mise-config/src/hooks/decl.rs`, which describe the shapes each event accepts, with a test that they name the keys the parser reads. The `[bootstrap]` values that stay raw TOML so newer shapes warn instead of failing (hooks, shell activation, macOS defaults, apt and dnf repositories) are derived from the declaration types in `crates/mise-config/src/bootstrap/decl.rs`; nothing parses into those, and tests in mise-system check the hook phases and the curated macOS keys against the code that reads them. `[daemons]` and `[daemon_providers]` stay raw tables that mise-daemons reads key by key, with their schema derived from the `Daemon*Decl` types in `crates/mise-config/src/daemons.rs`; those types describe a table, and nothing parses into them, so a key added in mise-daemons has to be added to them too. `[deps]` is derived from `DepsDecl` and `DepsProviderDecl`, which also hold the list of built-in providers mise shares; `[secrets]` stays raw TOML like the dotfiles, with its schema derived from `SecretsDecl` and a test in mise that its parser reads the same keys. `[dotfiles]` and `[dotfile_groups]` entries also stay raw TOML until mise-system expands them, but their schema is derived from the declaration types in `crates/mise-config/src/dotfiles.rs`, with the rules between keys written by hand in `dotfiles/schema.rs`; mise-system's `*_keys_match_the_declaration` tests fail until its parsers read the same keys. `[settings]` and `miserc.json` come from `settings.toml` through `crates/mise-config/src/schema/settings.rs`.\n\nThe `schema_matches_parser` unit test (`src/config/config_file/mise_toml/schema_conformance.rs`) validates every `toml` block in `docs/` and every mise config an e2e heredoc writes against both the schema and `MiseToml`'s parser, and fails when they disagree. Fix the schema rather than the corpus. Mark a config that mise refuses on purpose with `# schema: invalid` (e2e) or `<!-- schema: invalid -->` (docs) on the line above it, and an excerpt that is not a whole config with `schema: skip`. List deliberate differences in its `GAPS` with a reason.\n\n### Testing Strategy\n- E2E tests are organized by feature area (cli/, config/, backend/, etc.)\n- Use snapshot testing for CLI output verification\n- Backend-specific tests verify tool installation and version management\n- Slow tests (marked with `_slow` suffix) test actual tool compilation/installation\n\n### Cross-Platform Considerations\n- Windows modules follow one of two conventions:\n  - `*_windows.rs` is a platform-swapped sibling of a same-named module, selected with `#[cfg_attr(windows, path = \"..._windows.rs\")]` (e.g. `src/fake_asdf.rs` / `src/fake_asdf_windows.rs`)\n  - `windows_*.rs` is a single module about Windows with no non-Windows counterpart to swap in. Declare it on every platform and cfg-split it internally when other code calls it on all targets or its tests should run on Linux (e.g. `src/windows_posix.rs`, `src/windows_console.rs`); declare it under `#[cfg(windows)]` when only Windows code uses it (e.g. `src/windows_job.rs`)\n- Platform-specific tool installation logic in core plugins\n- Shim system varies by platform (especially Windows)\n- we don't chmod mise e2e tests to be executable\n\n### Windows PATH boundaries\n\n- Do not invoke subprocesses to translate paths in activation hooks, shims, or `mise x`/task execution.\n- Keep PATH in native Windows form inside mise and when launching child processes, including child MSYS2, Git Bash, or Cygwin processes. Never pre-convert the PATH inherited by a child emulator.\n- Convert PATH only when native Windows mise emits an assignment into an already-running, positively identified MSYS2/Cygwin shell. Only persisted mounts from the runtime defaults, `fstab`, and `fstab.d` are available; session-only `mount` changes cannot be reconstructed without entering the running process.\n- Never infer an emulator from the word `bash` alone. Require MSYS/Cygwin runtime evidence, and explicitly exclude WSL and BusyBox Bash.\n- Windows activation tests must execute a command through the emitted PATH and verify a native Windows grandchild receives a valid semicolon-delimited PATH. Output-shape assertions alone are insufficient.\n\n## GitHub Interactions\n\nNever open pull requests against the `release` branch. Default PRs to `main` unless the user explicitly names a different non-`release` base branch. If a change appears to belong on `release`, stop and ask for the intended branch strategy instead of opening a PR against `release`.\n\nSee [Discussions and Issues: Restricted AI Replies](#discussions-and-issues-restricted-ai-replies) at the top of this file.\n\nWhen AI contributes GitHub content—including a pull request description, review, pull request\ncomment, discussion post, or issue—append this disclosure:\n\n`*AI-assisted — Tool: <tool>; model: <provider>/<model>; version: <version-or-unavailable>.*`\n\nUse the exact model and version identifiers exposed by the runtime. Never infer or guess them; use\n`unavailable` when either value is not exposed.\n\n## Documentation\n\n### URL Structure\nWhen referencing mise documentation URLs, use the correct path structure based on the `docs/` directory layout:\n\n- **Dev tools & backends**: `mise.jdx.dev/dev-tools/backends/<backend>.html` (e.g., `mise.jdx.dev/dev-tools/backends/s3.html`)\n- **Configuration**: `mise.jdx.dev/configuration/...`\n- **Tasks**: `mise.jdx.dev/tasks/...`\n- **Environments**: `mise.jdx.dev/environments/...`\n- **CLI reference**: `mise.jdx.dev/cli/...`\n\nDo NOT use shortened paths like `mise.jdx.dev/backends/...` - always include the full path matching the `docs/` directory structure.\n\n## Cloud agent instructions (Cursor Cloud and Claude Code on the web)\n\nCursor Cloud Agents bootstrap from `.cursor/environment.json`, which runs `.cursor/install.sh`. Claude Code on the web runs the same script from the SessionStart hook in `.claude/settings.json` (`.claude/hooks/session-start.sh`), which runs on session `startup`/`resume`/`fork` (not `/clear` or compaction) with a 30-minute timeout, exits immediately unless `CLAUDE_CODE_REMOTE=true`, sends the bootstrap output to stderr, and adds the mise shims and `/usr/local/bin` to `PATH` through `CLAUDE_ENV_FILE`. The hook runs synchronously, so the session starts after the build finishes. Claude cloud containers do not provide a GitHub token by default; add `GITHUB_TOKEN` as an environment secret to avoid GitHub API rate limits during `mise install` and e2e tests. Use a fine-grained token with public-repository read-only access and no other permissions: any branch a session checks out (its hook, build scripts, tests, and tasks) can read the session environment. Draft environment builds often run as `ubuntu` rather than `root`; the script handles both (passwordless sudo, cargo/rustup permissions, world-writable `/tmp/fslock`).\n\nThe install script:\n\n- cds to the repository root derived from the script path before reading `Cargo.toml` or building\n- installs host packages needed to build mise and to run most e2e tests (openssl, pkg-config, zsh, fish, python3 + venv, jq, git, build-essential, and compile-time libs). It does **not** install a JDK or GUI libraries; those live in `packaging/e2e/Dockerfile`. `apt-get` is invoked as `sudo -n env DEBIAN_FRONTEND=noninteractive apt-get …` so the frontend reaches apt when elevation is required\n- installs and defaults to the latest stable Rust toolchain (not the `Cargo.toml` `rust-version` MSRV), including `rustfmt` and `clippy`, and updates it on reruns\n- gets a bootstrap `mise` and symlinks it to `/usr/local/bin/mise`: an existing `target/debug/mise` refreshes itself with `mise run build`; if it cannot run this checkout's config, a plain `cargo build` goes to `target/bootstrap` (the `mbx` wrapper leaves read-only outputs in `target/`); with no `target/` yet, a plain `cargo build` goes to `target/`\n- keeps `GITHUB_TOKEN`, `MISE_GITHUB_TOKEN`, and `GH_TOKEN` in sync via one `sync_github_tokens` helper (prefer any already-set token; fall back to `gh auth token` only when all three are empty)\n- runs `MISE_SAFE=1 /usr/local/bin/mise install` with the just-built binary so checkout-controlled hooks/templates/`[env]` and tool-level `postinstall` / `install_env` cannot run with those tokens, then `mise trust` for later agent commands\n- runs `mise run build` so `target/` is warm for the `mbx`-wrapped cargo (`[wrappers.cargo]` in `mise.toml`) that agents build with, then points `/usr/local/bin/mise` at `target/debug/mise`. Every build runs with `GITHUB_TOKEN`, `MISE_GITHUB_TOKEN`, `GH_TOKEN`, and `GITHUB_API_TOKEN` unset\n- runs `hk install --mise` (installs the git `pre-commit` hook defined in `hk.pkl`)\n- persists mise shims and token sync in one `/etc/profile.d/mise-dev-env.sh` (shims first, then `sync_github_tokens`) and rewrites the Cloud Agent block in `/etc/bash.bashrc` so non-login interactive bash picks it up after a snapshot. Fish/zsh only get this from login shells (`profile.d`), not from bashrc\n- exposes the mise-installed `node` / `npm` / `npx` / `hk` / `gh` binaries on `/usr/local/bin` (isolated e2e PATH includes that directory, not the agent's shims). Links freeze the version from install time — re-run `.cursor/install.sh` after upgrading those tools\n\nThere is no long-running service to start. Do not put `mise run build` or `mise run test:unit` in `terminals`; those are one-shot commands and would rerun a full build/test on every boot.\n\nThe debug `mise` binary is already on PATH. Prefer `mise run …` for project tasks.\n\n### E2E on Cloud Agents\n\n- Always `mise run test:e2e [test_filename]...` — never execute e2e scripts directly\n- Slow tests (`*_slow`) are skipped unless `TEST_ALL=1`. Do not run the full suite unless asked; pick tests under the feature area you changed\n- Isolated e2e uses `env -i` and a fake `HOME`, so the agent's mise shims are not on PATH. Tests install their own tools. Host packages (zsh, fish, python3, jq, git) still need to be on `/usr/bin`\n- If GitHub API calls 429, run `export GITHUB_TOKEN=\"$(gh auth token)\"; export MISE_GITHUB_TOKEN=\"$GITHUB_TOKEN\"`\n- A leftover `/tmp/mise.toml` will fail the harness; remove it if that error appears\n",".cursor/rules/conventional_commits.mdc":"---\nalwaysApply: false\ndescription: how to write commit and PR titles\n---\n\n## Conventional Commits (REQUIRED)\n\nPR titles MUST follow conventional commit format. Intermediate commit subjects\nSHOULD use the same format:\n\n### Format\n```\n<type>[optional scope][optional !]: <description>\n```\n\n### Types\n- `feat:` - New features\n- `fix:` - Bug fixes that affect CLI behavior (not CI, docs, or infrastructure)\n- `refactor:` - Code refactoring\n- `docs:` - Documentation changes\n- `style:` - Code style/formatting (no logic changes)\n- `perf:` - Performance improvements\n- `test:` - Testing changes\n- `chore:` - Maintenance tasks, releases, dependency updates, CI/infrastructure\n- `ci:` - CI and automation changes\n- `revert:` - Revert a previous change\n- `security:` - Security-related changes\n- `registry:` - Any changes to `registry/` (no extra scope)\n\n### Examples\n```\nfeat(cli): add new command for tool management\nfix(config): resolve parsing issue with nested tables\nrefactor(backend): simplify plugin loading logic\ndocs(contributing): update installation instructions\ntest(e2e): add tests for tool installation\nchore(ci): improve cursor cloud agent environment\nregistry: add miller\n```\n\n### Common Scopes\nCommand names (`install`, `activate`, `use`, `exec`, …) or subsystems:\n`config`, `backend`, `env`, `task`, `vfox`, `python`, `github`, `release`,\n`completions`, `http`, `schema`, `doctor`, `shim`, `core`, `deps`, `ci`.\n\nUse `task` (not `run`) for task-related changes, even if the code lives in\n`src/cli/run.rs` or `src/cmd.rs`.\n\nDescription: start with a lowercase character, use imperative mood, and keep it concise.\n",".cursor/rules/testing.mdc":"---\ndescription: how to test the mise codebase\nalwaysApply: false\n---\n\nTesting and linting commands should be run via `mise run`.\n\n- `mise run test:e2e [test_filename]...` executes an e2e test\n- `mise run test:unit` executes the unit tests\n- `mise run lint` runs the linting commands\n- `mise run lint-fix` runs the linting commands and fixes the issues\n- `mise --cd crates/vfox run test` executes the tests for the vfox crate\n- `mise --cd crates/vfox run lint` runs the linting commands for the vfox crate\n- `mise --cd crates/vfox run lint-fix` runs the linting commands and fixes the issues for the vfox crate\n\nNever execute e2e scripts directly. Slow tests (`*_slow`) are skipped unless `TEST_ALL=1`.\n\nFor GitHub API rate limits during e2e, set `MISE_GITHUB_TOKEN` (or `GITHUB_TOKEN`). Cloud Agents can use `export MISE_GITHUB_TOKEN=\"$(gh auth token)\"` when those are unset.\n\nOther tasks can be found by running `mise task ls`\n",".cursor/rules/development.mdc":"---\nalwaysApply: true\n---\n\n- `cargo build --all-features` - build the project\n- `target/debug/mise` - run the built binary\n- `mise run test:e2e [test_filename]...` - run e2e tests\n- `mise run test:unit` - run unit tests\n- `mise run lint` - run linting\n- `mise run lint-fix` - run linting and fix issues\n\nDon't run e2e tests by trying to execute them directly, always use `mise run test:e2e [test_filename]...`\n\nRun `mise run lint-fix` and `git add` any lint fixes before trying to commit.\n","crates/vfox/plugins/.luarc.json":"{\n  \"$schema\": \"https://raw.githubusercontent.com/LuaLS/vscode-lua/master/setting/schema.json\",\n  \"runtime\": {\n    \"version\": \"Lua 5.1\"\n  },\n  \"diagnostics\": {\n    \"disable\": [\"duplicate-set-field\"]\n  },\n  \"workspace\": {\n    \"checkThirdParty\": false,\n    \"library\": [\"../types\"]\n  }\n}\n","docs/bootstrap/packages/apk.md":"# Packages Skill\n\nPath: `docs/bootstrap/packages/apk.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/bootstrap/packages/apk.md)","docs/bootstrap/packages/apt.md":"# Packages Skill\n\nPath: `docs/bootstrap/packages/apt.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/bootstrap/packages/apt.md)","docs/bootstrap/packages/brew.md":"# Packages Skill\n\nPath: `docs/bootstrap/packages/brew.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/bootstrap/packages/brew.md)","docs/bootstrap/packages/dnf.md":"# Packages Skill\n\nPath: `docs/bootstrap/packages/dnf.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/bootstrap/packages/dnf.md)","docs/bootstrap/packages/flatpak.md":"# Packages Skill\n\nPath: `docs/bootstrap/packages/flatpak.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/bootstrap/packages/flatpak.md)","docs/bootstrap/packages/index.md":"# Packages Skill\n\nPath: `docs/bootstrap/packages/index.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/bootstrap/packages/index.md)","docs/bootstrap/packages/mas.md":"# Packages Skill\n\nPath: `docs/bootstrap/packages/mas.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/bootstrap/packages/mas.md)","docs/bootstrap/packages/pacman.md":"# Packages Skill\n\nPath: `docs/bootstrap/packages/pacman.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/bootstrap/packages/pacman.md)","docs/bootstrap/packages/plugins.md":"# Packages Skill\n\nPath: `docs/bootstrap/packages/plugins.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/bootstrap/packages/plugins.md)","docs/cli/plugins/install.md":"# Plugins Skill\n\nPath: `docs/cli/plugins/install.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/cli/plugins/install.md)","docs/cli/plugins/link.md":"# Plugins Skill\n\nPath: `docs/cli/plugins/link.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/cli/plugins/link.md)","docs/cli/plugins/ls.md":"# Plugins Skill\n\nPath: `docs/cli/plugins/ls.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/cli/plugins/ls.md)","docs/cli/plugins/ls-remote.md":"# Plugins Skill\n\nPath: `docs/cli/plugins/ls-remote.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/cli/plugins/ls-remote.md)","docs/cli/plugins/uninstall.md":"# Plugins Skill\n\nPath: `docs/cli/plugins/uninstall.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/cli/plugins/uninstall.md)","docs/cli/plugins/update.md":"# Plugins Skill\n\nPath: `docs/cli/plugins/update.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/cli/plugins/update.md)","test/plugins/vfox-npm/README.md":"# vfox-npm Documentation\n\nPath: `test/plugins/vfox-npm/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/test/plugins/vfox-npm/README.md)","crates/vfox/plugins/dummy/README.md":"# dummy Documentation\n\nPath: `crates/vfox/plugins/dummy/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/crates/vfox/plugins/dummy/README.md)","docs/cli/bootstrap/packages/apply.md":"# Packages Skill\n\nPath: `docs/cli/bootstrap/packages/apply.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/cli/bootstrap/packages/apply.md)","docs/cli/bootstrap/packages/brew.md":"# Packages Skill\n\nPath: `docs/cli/bootstrap/packages/brew.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/cli/bootstrap/packages/brew.md)","docs/cli/bootstrap/packages/import.md":"# Packages Skill\n\nPath: `docs/cli/bootstrap/packages/import.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/cli/bootstrap/packages/import.md)","docs/cli/bootstrap/packages/prune.md":"# Packages Skill\n\nPath: `docs/cli/bootstrap/packages/prune.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/cli/bootstrap/packages/prune.md)","docs/cli/bootstrap/packages/status.md":"# Packages Skill\n\nPath: `docs/cli/bootstrap/packages/status.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/cli/bootstrap/packages/status.md)","docs/cli/bootstrap/packages/upgrade.md":"# Packages Skill\n\nPath: `docs/cli/bootstrap/packages/upgrade.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/cli/bootstrap/packages/upgrade.md)","docs/cli/bootstrap/packages/use.md":"# Packages Skill\n\nPath: `docs/cli/bootstrap/packages/use.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/cli/bootstrap/packages/use.md)","docs/cli/bootstrap/plugins/apply.md":"# Plugins Skill\n\nPath: `docs/cli/bootstrap/plugins/apply.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/cli/bootstrap/plugins/apply.md)","docs/cli/bootstrap/plugins/status.md":"# Plugins Skill\n\nPath: `docs/cli/bootstrap/plugins/status.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/cli/bootstrap/plugins/status.md)","docs/cli/bootstrap/packages/brew/tap.md":"# Brew Skill\n\nPath: `docs/cli/bootstrap/packages/brew/tap.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/cli/bootstrap/packages/brew/tap.md)","docs/cli/bootstrap/packages/brew/untap.md":"# Brew Skill\n\nPath: `docs/cli/bootstrap/packages/brew/untap.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/cli/bootstrap/packages/brew/untap.md)"},"items":[{"name":"AGENTS.md","path":"AGENTS.md","rawUrl":"https://raw.githubusercontent.com/jdx/mise/HEAD/AGENTS.md","title":"AI Agent Protocol & Instructions","category":"root-instruction","format":"markdown","content":"# Repository Agent Guide\n\nThis file is the canonical agent guide. `CLAUDE.md` is a symlink to `AGENTS.md` for compatibility with existing tooling.\n\nTask-specific procedures live as skills in `.agents/skills/` (`.claude/skills` is a symlink to it). Load the named skill when this guide points to one; agents without skill support can read its `SKILL.md` directly.\n\n## Discussions and Issues: Restricted AI Replies\n\n**Do not use AI to reply to a mise Discussion or Issue unless the user (a) created that Discussion or Issue, (b) opened a PR that fixes it, or (c) has already had a contribution merged into the default branch of mise.** Otherwise they are not allowed to use AI to respond to it. Drive-by AI replies are spam, the problem is getting worse, and **doing it is an instant ban across all of jdx's projects** (mise, hk, pitchfork, usage, fnox, and the rest).\n\n- If the user asks you to answer, comment on, or \"help with\" a Discussion or Issue, confirm one of the three conditions first. If you cannot confirm one, **do not post**.\n  - (a) Compare the thread author to the authenticated user (`gh api user --jq .login`). For an Issue, use `gh api repos/jdx/mise/issues/<number> --jq .user.login`. Discussions have no REST endpoint, so use GraphQL: `gh api graphql -f query='query{repository(owner:\"jdx\",name:\"mise\"){discussion(number:<number>){author{login}}}}' --jq .data.repository.discussion.author.login`.\n  - (b) Check that the user's PR actually fixes the problem described in the thread. A closing keyword such as `Fixes #<number>` is good evidence, but a link is not required, and a PR that merely mentions an unrelated thread does not count.\n  - (c) Look for any contribution merged into the default branch that is tied to the user's GitHub account, not just a matching name or email: a PR authored by the user that was merged into the default branch (`gh pr list --repo jdx/mise --author @me --state merged --base main --limit 1`), commits on the default branch that GitHub attributes to their login (`gh api 'repos/jdx/mise/commits?author=<login>&per_page=1'` lists the default branch), never commits on a local or unmerged branch, or a PR from someone else, merged into the default branch, that credits them with a `Co-authored-by` trailer whose email is their GitHub noreply address or one verified on their account. Do not accept `git log --author` output, which includes local unmerged commits, or a trailer matched only by display name. Both queries filter by author on the server, so one matching result is enough to qualify and no pagination is needed.\n- If none of the three apply, **do not post a reply, even a short one.** Tell them this project does not allow AI replies from people who have not contributed, and offer to explain the answer to them in chat instead.\n- Never batch-post, loop over, or sweep Discussions or Issues to answer several of them, even for a merged contributor.\n- Lightly edited, human-reviewed, or disclosed model output does not create an exception. The disclosure footer does not make an AI reply acceptable on its own.\n- Permitted replies may be AI-assisted. The user must review and verify the reply before it is posted.\n- Creating a new Discussion or Issue with AI assistance is fine and is not restricted. The user must review it before it is posted, and it needs the AI disclosure below.\n\nWhen you post AI-contributed GitHub content, including a new Discussion or Issue, a reply, or a PR description or comment, append this disclosure: `*AI-assisted — Tool: <tool>; model: <provider>/<model>; version: <version-or-unavailable>.*` Use the exact model and version identifiers exposed by the runtime, never guessed values, and `unavailable` when one is not exposed.\n\n## Registry Submissions: READ THIS FIRST\n\n**Most new registry additions from agents get rejected.** mise's `registry/` is curated for tools that are already widely used — generally thousands of GitHub stars, not hundreds. jdx closes PRs that miss the bar without giving a reason.\n\nBefore adding a **new** tool or shorthand to `registry/`, follow the `registry-submission` skill ([`.agents/skills/registry-submission/SKILL.md`](.agents/skills/registry-submission/SKILL.md)). In short:\n\n- Warn the user about the bar, look up real popularity numbers, and stop if the tool is personal, internal, a fork, or niche.\n- Put a `## Popularity` section with those numbers in the PR description.\n- Confirm `mise ls-remote <backend>` lists installable versions.\n- Prefer `packslip:`, then `aqua:`, `github:`, or `gitlab:`. `conda:` has a high bar; `npm:`, `pipx:`, `gem:`, `cargo:`, `go:`, and `dotnet:` are almost never accepted. New `asdf:`, `vfox:`, and `ubi:` entries are not accepted.\n- Users can install any tool without a registry entry (`mise use github:owner/repo`, `mise use cargo:name`, …); the registry only adds a shorthand.\n\nNone of this applies to editing an existing registry entry; do not ask the user about popularity for maintenance or fixes.\n\n## Development Commands\n\n### Building and Testing\n- `mise run build` or `mise run b` - Build the project with cargo\n- `target/debug/mise` - Run the built binary directly\n- `mise run test` or `mise run t` - Run all tests (unit + e2e)\n- `mise run test:unit` - Run unit tests only\n- `mise run test:e2e` - Run end-to-end tests only\n- `mise run snapshots` - Update test snapshots with `cargo insta`\n\n### Debugging\n- Use `MISE_DEBUG=1` or `MISE_TRACE=1` environment variables to enable debug output (not `RUST_LOG`)\n\n### Code Quality and Testing\n- `mise run lint` - Run all linting tasks (hk; does not run clippy — see below)\n- `mise run lint-fix` - Run linting and automatically fix issues\n- `mise run format` - Format code (part of CI task)\n- `mise run ci` - Run format, build, and test\n- `mise run test:e2e [test_filename]...` - Run specific e2e tests (use this instead of executing test files directly)\n- `mise --cd crates/vfox run test` - Run tests for the vfox crate\n- `mise --cd crates/vfox run lint` - Run linting for the vfox crate\n- `mise --cd crates/vfox run lint-fix` - Run linting and fix issues for the vfox crate\n- `mise task ls` - List all available tasks\n\n### Clippy Exclusions\n\n- Do not add `#[allow(clippy::...)]`, `#[expect(clippy::...)]`, Cargo lint levels set to `allow`, or `-A clippy::...` command-line flags.\n- Refactor the code so `cargo clippy --workspace --all-features --all-targets -- -D warnings` passes without exclusions.\n- `mise run lint` does not cover this: the clippy step in `hk.pkl` is disabled, and `cargo check` does not enforce `-D warnings`. CI runs clippy separately, so run the command above yourself before pushing Rust changes.\n- If a feature or fix needs a preparatory refactor to satisfy Clippy cleanly, put that refactor in a prerequisite PR and stack the behavior change on top of it.\n\n### Documentation and Generation\n- `mise run render` - Generate all documentation and completions\n- `mise run render:usage` - Generate CLI usage documentation\n- `mise run render:completions` - Generate shell completions\n- `mise run docs` - Start documentation dev server\n- `mise run docs:build` - Build documentation\n\n### Development\n- `mise run install-dev` - Install development version locally\n- `mise run clean` - Clean cargo build artifacts\n\n## Code Architecture\n\n### High-Level Structure\nMise is a Rust CLI tool that manages development environments, tools, tasks, and environment variables. The codebase follows a modular architecture:\n\nThe `mise` package has two targets. The library (`src/lib.rs`) is everything except the command line; the binary (`src/main.rs` plus `src/cli/`) sits on top of it and glob-imports its root, so `cli` code still writes `crate::config::…`. An edit under `src/cli/` recompiles only the binary. Core code must not refer to `crate::cli`: it reaches command behavior through the hooks in `src/frontend.rs`. When `cli` needs a core item, make that item `pub`; `unreachable_pub` keeps everything else `pub(crate)`. `cfg(test)` does not reach the library from the binary's tests, so core code that behaves differently under tests checks `mise_util::testing::in_tests()` instead.\n\n**Core Components:**\n- `src/main.rs` - Binary entry point\n- `src/lib.rs` - Library root: module list and the hooks lower crates need\n- `src/cli/` - Command-line interface implementation with subcommands (binary only)\n- `src/config/` - Configuration file parsing and management\n- `src/backend/` - Tool backend implementations (aqua, github, cargo, npm, asdf, vfox, …)\n- `src/toolset/` - Tool version management and installation logic\n- `src/task/` - Task execution system\n- `src/plugins/` - Plugin system for extending tool support\n\n**Key Backend Systems** (`src/backend/`):\n- `packslip.rs` — Signed release manifests (preferred for new registry entries)\n- `aqua.rs` — Aqua registry\n- `github.rs` — GitHub / GitLab / Forgejo releases\n- `http.rs`, `s3.rs` — HTTP and S3 backends\n- `cargo.rs`, `npm.rs` (plus embedded aube), `pipx.rs`, `gem.rs`, `go.rs`, `dotnet.rs`, `conda.rs`, `spm.rs`\n- `asdf.rs`, `vfox.rs` — plugin compatibility layers\n- `ubi.rs` — deprecated; do not add new registry entries\n\n**Core Tools (Built-in):**\n- `src/plugins/core/` — Node, Python, Go, Ruby, Java, Bun, Deno, Elixir, Erlang, Dotnet, Swift, Zig, Rust\n\n**Configuration System:**\n- `mise.toml` files for project configuration\n- `.tool-versions` files for ASDF compatibility\n- Environment variable management and templating\n- Task definition and execution\n\n### Key Design Patterns\n1. **Backend Architecture**: Tools are implemented through a unified backend interface, allowing multiple sources (ASDF plugins, vfox plugins, cargo, npm, etc.)\n2. **Toolset Management**: The `Toolset` manages collections of tool versions and their installation state\n3. **Configuration Layering**: Config files are loaded hierarchically from system → global → local with environment-specific overrides\n4. **Task System**: Tasks can be defined in TOML files with dependencies, environment variables, and multiple execution modes\n\n### Configuration Files\n- `mise.toml` - Main configuration file format\n- `settings.toml` - Global settings definitions (generates code/docs)\n- `registry/` - Tool registry mappings\n- `tasks.toml` - Project task definitions\n\n### Test Structure\n- Unit tests within source files\n- E2E tests in `e2e/` directory organized by feature area (e.g., `e2e/cli/`, `e2e/backend/`)\n- E2E tests are bash scripts using assertion helpers from `e2e/assert.sh` (e.g., `assert`, `assert_contains`, `assert_fail`)\n- E2E tests do not need cleanup steps (rm, etc.) — the test harness handles that\n- Snapshot tests using `insta` crate for CLI output verification\n- Windows-specific tests in `e2e-win/`\n\n### Build System\n- Rust project using a Cargo workspace; member crates live in `crates/` (`vfox`, `aqua-registry`, `mise-shim`, `mise-sigstore`, `mise-cache-core`, `mise-tls`, `mise-brew-relocation`, `mise-brew-metadata`, `mise-agent-env`, `mise-interactive-config`, `mise-settings`, `mise-util`, `mise-ui`, `mise-system-packages`, `mise-config`, `mise-system`, `mise-oci`, `mise-daemons`, `mise-lsp`)\n- Custom build script in `build.rs` for generating metadata\n- Multiple build profiles including `release` and `serious` (with LTO)\n- Cross-compilation support via `Cross.toml`\n\n## Development Guidelines\n\n### Conventional Commits (REQUIRED)\nPR titles MUST follow conventional commit format. Intermediate commit subjects\nSHOULD use the same format:\n\n**Format:** `<type>[optional scope][optional !]: <description>`\n\n**Types:**\n- `feat:` - New features\n- `fix:` - Bug fixes that affect the CLI behavior (not CI, docs, or infrastructure)\n- `refactor:` - Code refactoring\n- `docs:` - Documentation changes\n- `style:` - Code style/formatting (no logic changes)\n- `perf:` - Performance improvements\n- `test:` - Testing changes\n- `chore:` - Maintenance tasks, releases, dependency updates, CI/infrastructure changes\n- `security:` - Security-related changes\n- `registry:` - Any changes to `registry/` (do not add a scope)\n- `ci:` - CI and automation changes\n- `revert:` - Reverting a previous change\n\n**Scopes:**\n- For command-specific changes, use the command name: `install`, `activate`, `use`, `exec`, etc.\n- For subsystem changes: `config`, `backend`, `env`, `task`, `vfox`, `python`, `github`, `release`, `completions`, `http`, `schema`, `doctor`, `shim`, `core`, `deps`, `ci`\n- Use `task` (not `run`) for task-related changes, even if the code lives in `src/cli/run.rs` or `src/cmd.rs`\n\n**Description Style:**\n- Start the description with a lowercase character, or with an acronym such as `PGO` or `CLI`\n- Use imperative mood (\"add feature\" not \"added feature\")\n- Keep it concise but descriptive\n\n**Examples:**\n- `fix(install): resolve version mismatch for previously installed tools`\n- `feat(activate): add fish shell support`\n- `feat(vfox): add semver Lua module for version sorting`\n- `feat(env): add environment caching with module cacheability support`\n- `docs(contributing): update hk usages`\n- `chore: release 2026.1.6`\n- `chore(ci): add FORGEJO_TOKEN for API authentication`\n- `registry: add miller`\n\nCI validates the pull request title and re-runs when it is edited. Intermediate\ncommit subjects are not checked because pull requests are squash-merged. CI\nmechanically checks the allowed type, syntax, and lowercase- or acronym-leading description;\nimperative mood and breaking-change details remain review rules.\n\n### PR titles and descriptions are release-note inputs\n\nCommunique generates release notes from PR titles and descriptions, so write them for a mise user who has not read the diff: lead with the user-visible problem and outcome, show a concrete example, and keep them in sync with the final diff. Follow the `pr-description` skill ([`.agents/skills/pr-description/SKILL.md`](.agents/skills/pr-description/SKILL.md)) when opening or revising a PR.\n\n### Pre-commit Process\n1. Run `mise run lint-fix` and `git add` any lint fixes before committing\n2. Use `mise run test:e2e [test_filename]...` for running specific e2e tests\n3. Never run e2e tests by executing them directly — always use the mise task\n\n`hk.pkl` defines `check` and `fix` steps and a git `pre-commit` hook that runs the same linters with auto-fix (`stash = \"git\"` preserves unstaged work). `hk install --mise` installs that hook. You can still run `mise run lint` / `mise run lint-fix` by hand; on Linux and macOS they run hk, but on Windows `lint-fix` runs only Clippy, oxfmt, and `cargo fmt`, so the other hk steps do not run there.\n\n### hk Agent Workflow\n\n- Prefer the hk MCP server for effect-aware plans, checks, fixes, logs, and captured diffs.\n- When invoking hk directly, use `hk run check --safe --format json` for a complete machine-readable result or `--format jsonl` for streaming lifecycle events.\n- Scope checks to changed files. For an exact file list, pass NUL-delimited paths with `--files0-from`; use `--cd` to target another project directory.\n- Never run a command classified as unknown or destructive without explicit user approval. Review the resulting diff after fixes.\n\n### Dependency Updates\n\n- Use the lowest-specificity dependency requirement that expresses compatibility in `Cargo.toml` (for example, prefer `\"1\"` over `\"1.2.3\"`, and `\"0.12\"` over `\"0.12.1\"` for a pre-1.0 crate).\n- Routine dependency updates should only change `Cargo.lock`. If the existing `Cargo.toml` requirement accepts the target version, do not change it merely to force or record the update; use `cargo update -p <crate> --precise <version>` instead.\n- Keep lockfile updates focused on the requested dependency and its required transitive changes. Remove unrelated resolver churn before committing.\n\nWhen updating the embedded `aube` crates, follow the `update-aube` skill ([`.agents/skills/update-aube/SKILL.md`](.agents/skills/update-aube/SKILL.md)).\n\n## Deprecation Policy\n\nWhen deprecating a feature, backend, or implicit behavior:\n\n1. **Immediately**: Mark it as deprecated in docs (add a warning banner) and display a CLI warning using the `deprecated_at!` macro from `src/output.rs` (`warn_at` is the current version).\n2. **12 months after warn** (`remove_at`): `debug_assert!` in `deprecated_at!` fires, signaling the deprecated code or behavior should be removed.\n\n12 months is the default window, not a hard rule. Some deprecations use a shorter window, such as 6 months, on purpose. Use 12 months for new deprecations unless jdx asks for something else, and do not lengthen an existing shorter window.\n\nDelay the CLI warning for up to 6 months only when migration requires a new setting, syntax, or replacement that older supported mise versions would reject or fail to parse. This compatibility window lets users adopt a configuration that works across old and new clients before warnings begin. Do not delay warnings for a behavior change that requires no new configuration, or when the replacement already works in older clients.\n\nUse mise version format for dates (e.g., `deprecated_at!(\"2026.10.0\", \"2027.10.0\", \"id\", \"message\")`).\n\nIf a compatibility window is required, removal remains 12 months after `warn_at`, not 12 months after the initial documentation notice.\n\nFor temporary code with no user-facing deprecation, such as a migration or a fallback that reads what an older mise wrote, use `remove_by!(\"2027.1.0\", \"id\")` from `src/output.rs`. It is a compile-time assertion, so the build fails once the version reaches `remove_at`; remove every `remove_by!` with that id and the code it guards.\n\n## Important Implementation Notes\n\n### Backend System\nWhen implementing new tool backends, follow the pattern in `src/backend/mod.rs`. Each backend must implement the `Backend` trait with methods for listing versions, installing tools, and managing tool metadata.\n\n### DO NOT ASSUME SEMVER\n**Do not assume tool versions follow semver or any other orderable scheme.** mise manages hundreds of tools with wildly different versioning conventions:\n\n- Date-based: `2024.01.15`, `20241015`\n- Pre-release / ref / tag versions: `tip`, `HEAD`, `nightly`, `edge`, `canary`, `ref:main`, `tag:v1`, `sub-X.Y:...`\n- Non-numeric tags: Python `3.12.0a1`, Ruby `3.2.0-preview1`, Go `1.22rc1`, Node `lts/hydrogen`, `lts-iron`\n- Tool-specific meanings of `latest` (e.g. some exclude pre-releases, some don't)\n\n**Rules:**\n1. Do not call `versions::Versioning::new(...)` (or any other semver comparator) at a new call site to pick the \"newest\" version, \"resolve latest\", or sort a version list. That crate silently returns `None` / arbitrary ordering for non-semver strings, which means wrong versions get chosen for many tools.\n2. To resolve a version request (`latest`, a prefix, a channel name), delegate to the backend via `Backend::latest_version`, `Backend::latest_installed_version`, `Backend::list_versions_matching`, or `ToolRequest::resolve` — the backend knows what \"latest\" means for its tool.\n3. To list installed versions in a meaningful order, use `Backend::list_installed_versions_matching` or the toolset's resolved versions. Do not reorder them yourself.\n4. Lockfile version strings must be treated as opaque — compare with `==`, never with a version ordering. Never write a non-concrete string (`latest`, `lts/*`, a prefix) into the lockfile; resolve first.\n\nA few existing call sites (e.g. runtime symlinks) do use `Versioning` ordering today, but that's legacy behavior and arguably also wrong — do not point at them to justify new semver assumptions.\n\nIf you think you need to pick \"the newest installed version\" at a new call site, stop and ask — that call almost always belongs on the backend, not inline.\n\n### Paranoid mode categories\n`paranoid` is a bool or a list of categories (`config`, `env_files`, `plugins`, `provenance`), defined by `Paranoid` in `crates/mise-settings/src/paranoid.rs`. Any new behavior gated on paranoid mode must belong to one of those categories, or introduce a new named category, so it is individually selectable. New code must never read paranoid as a plain bool: call `settings.paranoid.config()`, `.env_files()`, `.plugins()` or `.provenance()`, and add an e2e test that the category works alone.\n\n### Plugin Development\n- Core tools are implemented in `src/plugins/core/`\n- External plugins use ASDF or vfox compatibility layers\n- Plugin metadata is defined in `mise.plugin.toml` files\n\n### Configuration Parsing\nThe configuration system supports multiple file formats and environment-specific configs. Changes to settings require updating `settings.toml` and running `mise run render:schema`. The `Settings` types are generated from `settings.toml` in `crates/mise-settings`; loading them (config discovery, trust, CLI flags) stays in `src/config/settings.rs`, whose `SettingsExt` trait holds the methods that need the rest of mise.\n\n`schema/mise.json`, `schema/mise-task.json` and `schema/miserc.json` are generated from `crates/mise-config` and `settings.toml`: never edit the JSON. Change the Rust, then run `mise run render:schema`; a `mise-config` test fails while the committed files are stale. The top-level keys are the fields of `MiseTomlDecl` in `crates/mise-config/src/mise_toml.rs`, which `MiseToml` deserializes through: a new key goes in `MiseTomlDecl`, and `MiseToml::from_decl` moves it into `MiseToml`. Sections whose types derive `JsonSchema` (so far `[bootstrap]`, `[daemons_settings]`, `[daemon_groups]`, `[doctor]`, `[history]`, `[monorepo]`, `[oci]`, `[task_config]`, `[tasks]`, `[task_templates]`, `[tool_config]` and `[wrappers]`) are generated from those types and their doc comments. `[env]` and `[vars]` accept shapes a derive cannot parse, so `env.rs` reads them with visitors; their schema is derived from the `Env*` and `Vars*` declaration types in `crates/mise-config/src/env/decl.rs`, which describe the tables and nothing parses into them, and a test checks that the option keys they declare are the fields of `EnvDirectiveOptions`. `[[watch_files]]`, `[tool_alias]` and `min_version` have a hand-written `JsonSchema` impl in `watch_files.rs`, `alias.rs` and `min_version.rs`. Task fields with several accepted shapes (a string or a list, a name or a table, ...) take theirs from the declaration types in `crates/mise-config/src/task/shapes.rs`, which `TaskDecl` and `TaskConfig` attach with `schemars(with = ..)` so the runtime field types stay as they are; nothing parses into those types, so change them together with the parser. `task/schema.rs` composes the rest: the `task` definition, a task's `tools` (which follow the backend table of `[tools]`) and the template schema. `[tools]` picks per-backend options by key pattern: a backend's options are the declaration types in `crates/mise-config/src/tools/decl.rs` (a new option is a field with a doc comment, which is its description), and `crates/mise-config/src/tools/schema.rs` composes them, with one table row per backend and per platform table. mise reads these definitions by name to reject unknown options (`OptionSpec`), so change them together with `ToolVersionOptions::insert_option` and the backend's option reader. `[hooks]` is derived from the `Hook*` declaration types in `crates/mise-config/src/hooks/decl.rs`, which describe the shapes each event accepts, with a test that they name the keys the parser reads. The `[bootstrap]` values that stay raw TOML so newer shapes warn instead of failing (hooks, shell activation, macOS defaults, apt and dnf repositories) are derived from the declaration types in `crates/mise-config/src/bootstrap/decl.rs`; nothing parses into those, and tests in mise-system check the hook phases and the curated macOS keys against the code that reads them. `[daemons]` and `[daemon_providers]` stay raw tables that mise-daemons reads key by key, with their schema derived from the `Daemon*Decl` types in `crates/mise-config/src/daemons.rs`; those types describe a table, and nothing parses into them, so a key added in mise-daemons has to be added to them too. `[deps]` is derived from `DepsDecl` and `DepsProviderDecl`, which also hold the list of built-in providers mise shares; `[secrets]` stays raw TOML like the dotfiles, with its schema derived from `SecretsDecl` and a test in mise that its parser reads the same keys. `[dotfiles]` and `[dotfile_groups]` entries also stay raw TOML until mise-system expands them, but their schema is derived from the declaration types in `crates/mise-config/src/dotfiles.rs`, with the rules between keys written by hand in `dotfiles/schema.rs`; mise-system's `*_keys_match_the_declaration` tests fail until its parsers read the same keys. `[settings]` and `miserc.json` come from `settings.toml` through `crates/mise-config/src/schema/settings.rs`.\n\nThe `schema_matches_parser` unit test (`src/config/config_file/mise_toml/schema_conformance.rs`) validates every `toml` block in `docs/` and every mise config an e2e heredoc writes against both the schema and `MiseToml`'s parser, and fails when they disagree. Fix the schema rather than the corpus. Mark a config that mise refuses on purpose with `# schema: invalid` (e2e) or `<!-- schema: invalid -->` (docs) on the line above it, and an excerpt that is not a whole config with `schema: skip`. List deliberate differences in its `GAPS` with a reason.\n\n### Testing Strategy\n- E2E tests are organized by feature area (cli/, config/, backend/, etc.)\n- Use snapshot testing for CLI output verification\n- Backend-specific tests verify tool installation and version management\n- Slow tests (marked with `_slow` suffix) test actual tool compilation/installation\n\n### Cross-Platform Considerations\n- Windows modules follow one of two conventions:\n  - `*_windows.rs` is a platform-swapped sibling of a same-named module, selected with `#[cfg_attr(windows, path = \"..._windows.rs\")]` (e.g. `src/fake_asdf.rs` / `src/fake_asdf_windows.rs`)\n  - `windows_*.rs` is a single module about Windows with no non-Windows counterpart to swap in. Declare it on every platform and cfg-split it internally when other code calls it on all targets or its tests should run on Linux (e.g. `src/windows_posix.rs`, `src/windows_console.rs`); declare it under `#[cfg(windows)]` when only Windows code uses it (e.g. `src/windows_job.rs`)\n- Platform-specific tool installation logic in core plugins\n- Shim system varies by platform (especially Windows)\n- we don't chmod mise e2e tests to be executable\n\n### Windows PATH boundaries\n\n- Do not invoke subprocesses to translate paths in activation hooks, shims, or `mise x`/task execution.\n- Keep PATH in native Windows form inside mise and when launching child processes, including child MSYS2, Git Bash, or Cygwin processes. Never pre-convert the PATH inherited by a child emulator.\n- Convert PATH only when native Windows mise emits an assignment into an already-running, positively identified MSYS2/Cygwin shell. Only persisted mounts from the runtime defaults, `fstab`, and `fstab.d` are available; session-only `mount` changes cannot be reconstructed without entering the running process.\n- Never infer an emulator from the word `bash` alone. Require MSYS/Cygwin runtime evidence, and explicitly exclude WSL and BusyBox Bash.\n- Windows activation tests must execute a command through the emitted PATH and verify a native Windows grandchild receives a valid semicolon-delimited PATH. Output-shape assertions alone are insufficient.\n\n## GitHub Interactions\n\nNever open pull requests against the `release` branch. Default PRs to `main` unless the user explicitly names a different non-`release` base branch. If a change appears to belong on `release`, stop and ask for the intended branch strategy instead of opening a PR against `release`.\n\nSee [Discussions and Issues: Restricted AI Replies](#discussions-and-issues-restricted-ai-replies) at the top of this file.\n\nWhen AI contributes GitHub content—including a pull request description, review, pull request\ncomment, discussion post, or issue—append this disclosure:\n\n`*AI-assisted — Tool: <tool>; model: <provider>/<model>; version: <version-or-unavailable>.*`\n\nUse the exact model and version identifiers exposed by the runtime. Never infer or guess them; use\n`unavailable` when either value is not exposed.\n\n## Documentation\n\n### URL Structure\nWhen referencing mise documentation URLs, use the correct path structure based on the `docs/` directory layout:\n\n- **Dev tools & backends**: `mise.jdx.dev/dev-tools/backends/<backend>.html` (e.g., `mise.jdx.dev/dev-tools/backends/s3.html`)\n- **Configuration**: `mise.jdx.dev/configuration/...`\n- **Tasks**: `mise.jdx.dev/tasks/...`\n- **Environments**: `mise.jdx.dev/environments/...`\n- **CLI reference**: `mise.jdx.dev/cli/...`\n\nDo NOT use shortened paths like `mise.jdx.dev/backends/...` - always include the full path matching the `docs/` directory structure.\n\n## Cloud agent instructions (Cursor Cloud and Claude Code on the web)\n\nCursor Cloud Agents bootstrap from `.cursor/environment.json`, which runs `.cursor/install.sh`. Claude Code on the web runs the same script from the SessionStart hook in `.claude/settings.json` (`.claude/hooks/session-start.sh`), which runs on session `startup`/`resume`/`fork` (not `/clear` or compaction) with a 30-minute timeout, exits immediately unless `CLAUDE_CODE_REMOTE=true`, sends the bootstrap output to stderr, and adds the mise shims and `/usr/local/bin` to `PATH` through `CLAUDE_ENV_FILE`. The hook runs synchronously, so the session starts after the build finishes. Claude cloud containers do not provide a GitHub token by default; add `GITHUB_TOKEN` as an environment secret to avoid GitHub API rate limits during `mise install` and e2e tests. Use a fine-grained token with public-repository read-only access and no other permissions: any branch a session checks out (its hook, build scripts, tests, and tasks) can read the session environment. Draft environment builds often run as `ubuntu` rather than `root`; the script handles both (passwordless sudo, cargo/rustup permissions, world-writable `/tmp/fslock`).\n\nThe install script:\n\n- cds to the repository root derived from the script path before reading `Cargo.toml` or building\n- installs host packages needed to build mise and to run most e2e tests (openssl, pkg-config, zsh, fish, python3 + venv, jq, git, build-essential, and compile-time libs). It does **not** install a JDK or GUI libraries; those live in `packaging/e2e/Dockerfile`. `apt-get` is invoked as `sudo -n env DEBIAN_FRONTEND=noninteractive apt-get …` so the frontend reaches apt when elevation is required\n- installs and defaults to the latest stable Rust toolchain (not the `Cargo.toml` `rust-version` MSRV), including `rustfmt` and `clippy`, and updates it on reruns\n- gets a bootstrap `mise` and symlinks it to `/usr/local/bin/mise`: an existing `target/debug/mise` refreshes itself with `mise run build`; if it cannot run this checkout's config, a plain `cargo build` goes to `target/bootstrap` (the `mbx` wrapper leaves read-only outputs in `target/`); with no `target/` yet, a plain `cargo build` goes to `target/`\n- keeps `GITHUB_TOKEN`, `MISE_GITHUB_TOKEN`, and `GH_TOKEN` in sync via one `sync_github_tokens` helper (prefer any already-set token; fall back to `gh auth token` only when all three are empty)\n- runs `MISE_SAFE=1 /usr/local/bin/mise install` with the just-built binary so checkout-controlled hooks/templates/`[env]` and tool-level `postinstall` / `install_env` cannot run with those tokens, then `mise trust` for later agent commands\n- runs `mise run build` so `target/` is warm for the `mbx`-wrapped cargo (`[wrappers.cargo]` in `mise.toml`) that agents build with, then points `/usr/local/bin/mise` at `target/debug/mise`. Every build runs with `GITHUB_TOKEN`, `MISE_GITHUB_TOKEN`, `GH_TOKEN`, and `GITHUB_API_TOKEN` unset\n- runs `hk install --mise` (installs the git `pre-commit` hook defined in `hk.pkl`)\n- persists mise shims and token sync in one `/etc/profile.d/mise-dev-env.sh` (shims first, then `sync_github_tokens`) and rewrites the Cloud Agent block in `/etc/bash.bashrc` so non-login interactive bash picks it up after a snapshot. Fish/zsh only get this from login shells (`profile.d`), not from bashrc\n- exposes the mise-installed `node` / `npm` / `npx` / `hk` / `gh` binaries on `/usr/local/bin` (isolated e2e PATH includes that directory, not the agent's shims). Links freeze the version from install time — re-run `.cursor/install.sh` after upgrading those tools\n\nThere is no long-running service to start. Do not put `mise run build` or `mise run test:unit` in `terminals`; those are one-shot commands and would rerun a full build/test on every boot.\n\nThe debug `mise` binary is already on PATH. Prefer `mise run …` for project tasks.\n\n### E2E on Cloud Agents\n\n- Always `mise run test:e2e [test_filename]...` — never execute e2e scripts directly\n- Slow tests (`*_slow`) are skipped unless `TEST_ALL=1`. Do not run the full suite unless asked; pick tests under the feature area you changed\n- Isolated e2e uses `env -i` and a fake `HOME`, so the agent's mise shims are not on PATH. Tests install their own tools. Host packages (zsh, fish, python3, jq, git) still need to be on `/usr/bin`\n- If GitHub API calls 429, run `export GITHUB_TOKEN=\"$(gh auth token)\"; export MISE_GITHUB_TOKEN=\"$GITHUB_TOKEN\"`\n- A leftover `/tmp/mise.toml` will fail the harness; remove it if that error appears\n","isInternal":false,"tokens":8116,"sizeBytes":33328},{"name":"llms.txt","path":"llms.txt","rawUrl":"https://raw.githubusercontent.com/jdx/mise/HEAD/llms.txt","title":"LLM Index & Context Digest","category":"root-instruction","format":"text","content":"# mise (mise-en-place) - Development Environment Tool\n\n## What is mise?\n\nmise (pronounced \"meez\") is a development environment setup tool that manages:\n1. **Dev Tools**: Installing, pinning, and switching programming languages and tools\n2. **Environments**: Loading project-specific environment variables\n3. **Tasks**: Running project automation for build, test, lint, deploy, and everyday workflows\n\nmise supports hundreds of development tools and can automatically switch between different versions based on your project directory.\n\n## Installation\n\n### Quick Install (Linux/macOS)\n```bash\ncurl https://mise.run | sh\n```\n\n### Other Methods\n- **Homebrew**: `brew install mise`\n- **Windows**: `winget install jdx.mise` or `scoop install mise`\n- **Debian/Ubuntu**: Available via apt repository\n- **Fedora**: Available via dnf repository\n\n## Core Configuration\n\n### mise.toml\nThe main configuration file for mise. Can be named:\n- `mise.toml` (project-specific)\n- `mise.local.toml` (local, not committed to git)\n- `~/.config/mise/config.toml` (global)\n\nExample `mise.toml`:\n```toml\n[tools]\nnode = \"20\"\npython = \"3.11\"\nterraform = \"1.0.0\"\ngo = \"latest\"\n\n[env]\nNODE_ENV = \"development\"\nDATABASE_URL = \"postgresql://localhost/myapp\"\n\n[tasks.test]\nrun = \"npm test\"\ndescription = \"Run tests\"\n\n[tasks.build]\nrun = \"npm run build\"\ndeps = [\"test\"]\n```\n\n### .tool-versions (asdf compatibility)\nmise is compatible with asdf's `.tool-versions` format:\n```\nnode 20.0.0\npython 3.11.5\nterraform 1.0.0\n```\n\n## Essential Commands\n\n### Tool Management\n- `mise use node@20` - Install and set node version (updates config)\n- `mise use -g node@20` - Set global default\n- `mise install` - Install all tools from config\n- `mise install node@20` - Install specific version\n- `mise ls` - List installed tools\n- `mise ls-remote node` - List available versions\n\n### Execution\n- `mise exec node@20 -- node script.js` - Run command with specific tool version\n- `mise x node@20 -- node script.js` - Shorthand for exec\n- `mise run test` - Run defined task\n- `mise test` - Shorthand (if no command conflict)\n\n### Environment\n- `mise activate bash` - Activate mise in shell (add to .bashrc)\n- `mise activate zsh` - Activate mise in zsh (add to .zshrc)  \n- `mise activate fish` - Activate mise in fish\n- `mise env` - Show current environment\n- `mise set KEY=value` - Set environment variable\n\n### Information\n- `mise doctor` - Check mise setup\n- `mise config` - Show loaded config files\n- `mise current` - Show active tool versions\n- `mise which node` - Show path to tool\n\n## Key Concepts\n\n### Activation vs Shims vs Exec\n1. **Activation** (`mise activate`): Recommended for interactive shells. Updates PATH automatically when changing directories.\n2. **Shims**: Symlinks that intercept tool calls. Good for CI/CD and IDEs.\n3. **Exec** (`mise exec`): Run commands with mise environment without activation.\n\n### Tool Scopes\n- `node@20.1.0` - Exact version\n- `node@20` - Latest 20.x version\n- `node@latest` - Latest available version\n- `node@lts` - Latest LTS version\n- `ref:master` - Build from git ref\n- `prefix:1.19` - Latest matching prefix\n- `path:/custom/path` - Use custom installation\n\n### Configuration Hierarchy\nConfig files are loaded in order (later overrides earlier):\n1. Global: `~/.config/mise/config.toml`\n2. Parent directories: `mise.toml` files going up the tree\n3. Current directory: `mise.toml`\n4. Local: `mise.local.toml`\n\n## Tasks\n\n### TOML Tasks\n```toml\n[tasks.build]\nrun = \"cargo build\"\ndescription = \"Build the project\"\ndepends = [\"install\"]\n\n[tasks.test]\nrun = \"cargo test\"\ndepends = [\"build\"]\n```\n\n### File Tasks\nCreate executable scripts in `mise-tasks/` directory:\n```bash\n#!/usr/bin/env bash\n#MISE description=\"Run tests\"\ncargo test\n```\n\n### Task Features\n- Parallel execution by default\n- Dependency management\n- File watching (`mise watch`)\n- Environment variable passing\n\n## Environment Variables\n\n### Settings\n- `MISE_DATA_DIR` - Where tools are installed (`~/.local/share/mise`)\n- `MISE_CONFIG_DIR` - Config directory (`~/.config/mise`)\n- `MISE_CACHE_DIR` - Cache directory\n- `MISE_GITHUB_TOKEN` - GitHub token for API access\n\n### Tool-specific\n- `MISE_NODE_VERSION=20` - Override node version\n- `MISE_PYTHON_VERSION=3.11` - Override python version\n\n## Common Patterns\n\n### Project Setup\n```bash\n# Initialize project\ncd my-project\nmise use node@20 python@3.11\nmise install\n\n# Add environment variables\nmise set NODE_ENV=development\nmise set DATABASE_URL=postgresql://localhost/myapp\n```\n\n### Global Tools\n```bash\n# Set global defaults\nmise use -g node@lts python@3.11 go@latest\n```\n\n### CI/CD\n```bash\n# Install mise and tools\ncurl https://mise.run | sh\nexport PATH=\"$HOME/.local/bin:$PATH\"\nmise install\nmise run build\n```\n\n## Troubleshooting\n\n### Common Issues\n- **Rate limiting**: Set `MISE_GITHUB_TOKEN` for GitHub API access\n- **Tool not found**: Run `mise doctor` to check setup\n- **Slow performance**: Check `mise cache clear` if stale\n- **Permission errors**: Ensure proper file permissions\n\n### Debugging\n- `mise doctor` - Comprehensive health check\n- `mise config` - Show config file loading order\n- `mise env` - Show current environment\n- `mise which <tool>` - Show tool path resolution\n\n## Plugin System\n\nmise uses plugins to support different tools:\n- Compatible with asdf plugins\n- Automatic plugin installation\n- Custom plugin repositories supported\n- Plugin shortcuts in registry\n\n## Migration from asdf\n\nmise is largely compatible with asdf:\n- Reads `.tool-versions` files\n- Uses asdf plugins\n- Similar commands (with improvements)\n- Can run alongside asdf temporarily\n\n## Best Practices\n\n1. Use `mise.toml` for committed project configuration\n2. Use `mise.local.toml` for local overrides\n3. Activate mise in shell for interactive use\n4. Use shims for CI/CD and IDE integration\n5. Set `MISE_GITHUB_TOKEN` to avoid rate limits\n6. Use `mise doctor` regularly to check setup\n7. Pin versions in production environments\n8. Use tasks for project automation\n\n## Advanced Features\n\n### Tool Options\n```toml\n[tools]\nnode = { version = \"20\", postinstall = \"corepack enable\" }\npython = { version = \"3.11\", virtualenv = \"myproject\" }\n```\n\n### Hooks\n```toml\n[hooks]\nenter = \"mise install --quiet\"\nleave = \"deactivate\"\n```\n\n### Multiple Versions\n```toml\n[tools]\npython = [\"3.10\", \"3.11\", \"3.12\"]  # Install multiple versions\n```\n\n## Development & Contributing\n\n### Setting Up Development Environment\n\nmise is written in Rust and uses itself for development tasks. To contribute to mise:\n\n#### Prerequisites\n- Rust (latest stable)\n- Node.js\n- `pipx` or `uv` \n- Bash (newer than macOS default)\n\n#### Getting Started\n```bash\n# Clone the repository\ngit clone https://github.com/jdx/mise.git\ncd mise\n\n# Install dependencies and build\nmise run build\n\n# Run sanity check\nmise run build\n```\n\n#### Development Setup\nCreate a development shim to easily run mise during development:\n\n```bash\n# Create ~/.local/bin/@mise\n#!/bin/sh\nexec cargo run -q --all-features --manifest-path ~/src/mise/Cargo.toml -- \"$@\"\n```\n\nThen use `@mise` to run the development version:\n```bash\n@mise --help\neval \"$(@mise activate zsh)\"\n```\n\n### Testing\n\nmise has a comprehensive test suite with multiple types of tests to ensure reliability and functionality across different platforms and scenarios.\n\n#### Unit Tests\nUnit tests are fast, focused tests for individual components and functions:\n\n```bash\n# Run all unit tests\ncargo test --all-features\n\n# Run specific unit tests\ncargo test <test_name>\n\n# Run tests with verbose output\ncargo test --all-features -- --nocapture\n\n# Run tests in series (not parallel)\nRUST_TEST_THREADS=1 cargo test --all-features\n```\n\n**Unit test structure:**\n- Located in `src/` directory alongside source code\n- Use Rust's built-in test framework\n- Test individual functions and modules\n- Fast execution (used for quick feedback during development)\n\n#### E2E Tests\nEnd-to-end tests validate the complete functionality of mise in realistic scenarios:\n\n```bash\n# Run all E2E tests\nmise run test:e2e\n\n# Run specific E2E test\n./e2e/run_test test_name\n\n# Run E2E tests matching pattern\n./e2e/run_test task  # runs tests matching *task*\n\n# Run all tests including slow ones\nTEST_ALL=1 mise run test:e2e\n```\n\n**E2E test structure:**\n- Located in `e2e/` directory\n- Organized by functionality:\n  - `e2e/cli/` - Command-line interface tests\n  - `e2e/core/` - Core functionality tests\n  - `e2e/env/` - Environment variable tests\n  - `e2e/tasks/` - Task runner tests\n  - `e2e/config/` - Configuration tests\n  - `e2e/tools/` - Tool management tests\n  - `e2e/shell/` - Shell integration tests\n  - `e2e/backend/` - Backend tests\n  - `e2e/plugins/` - Plugin tests\n\n**E2E test categories:**\n- **Fast tests** (`test_*`): Run in normal test suites\n- **Slow tests** (`test_*_slow`): Only run when `TEST_ALL=1` is set\n- **Isolated environment**: Each test runs in a clean, isolated environment\n\n#### Coverage Tests\nCoverage tests measure how much of the codebase is covered by tests:\n\n```bash\n# Run coverage tests\nmise run test:coverage\n\n# Coverage tests run in parallel tranches for CI\nTEST_TRANCHE=0 TEST_TRANCHE_COUNT=8 mise run test:coverage\n```\n\n#### Windows E2E Tests\nWindows has its own test suite written in PowerShell:\n\n```powershell\n# Run all Windows E2E tests\npwsh e2e-win\\run.ps1\n\n# Run specific Windows tests\npwsh e2e-win\\run.ps1 task  # run tests matching *task*\n```\n\n#### Plugin Tests\nTest plugin functionality across different backends:\n\n```bash\n# Test specific plugin\nmise test-tool ripgrep\n\n# Test all plugins in registry\nmise test-tool --all\n\n# Test all plugins in config files\nmise test-tool --all-config\n\n# Test with parallel jobs\nmise test-tool --all --jobs 4\n```\n\n#### Test Environment Setup\nTests run in isolated environments to avoid conflicts:\n\n```bash\n# Disable mise during development testing\nexport MISE_DISABLE_TOOLS=1\n\n# Run tests with specific environment\nMISE_TRUSTED_CONFIG_PATHS=$PWD cargo test\n```\n\n#### Test Assertions\nThe E2E tests use a custom assertion framework (`e2e/assert.sh`):\n\n```bash\n# Basic assertions\nassert \"command\" \"expected_output\"\nassert_contains \"command\" \"substring\"\nassert_fail \"command\" \"expected_error\"\n\n# JSON assertions\nassert_json \"command\" '{\"key\": \"value\"}'\nassert_json_partial_array \"command\" \"fields\" '[{...}]'\n\n# File/directory assertions\nassert_directory_exists \"/path/to/dir\"\nassert_directory_not_exists \"/path/to/dir\"\nassert_empty \"command\"\n```\n\n#### Running Specific Test Categories\n\n```bash\n# Run all tests (unit + e2e)\nmise run test\n\n# Run only unit tests\nmise run test:unit\n\n# Run only e2e tests\nmise run test:e2e\n\n# Run tests with shuffle (for detecting order dependencies)\nmise run test:shuffle\n\n# Run nightly tests (with bleeding edge Rust)\nrustup default nightly && mise run test\n```\n\n#### Running Single Tests\n\n**Unit Tests:**\n```bash\n# Run a specific unit test by name\ncargo test test_name\n\n# Run tests matching a pattern\ncargo test pattern\n\n# Run tests in a specific module\ncargo test module_name\n\n# Run a single test with output\ncargo test test_name -- --nocapture\n\n# Run a single test file (if organized by file)\ncargo test --test test_file_name\n```\n\n**E2E Tests:**\n```bash\n# Run a specific E2E test by name\n./e2e/run_test test_name\n\n# Run E2E tests matching a pattern\nmise run test:e2e pattern\n\n# Examples:\n./e2e/run_test test_use                    # Run specific test\n./e2e/run_test test_config_set            # Run config-related test\nmise run test:e2e task                     # Run all tests matching \"task\"\n```\n\n**Plugin Tests:**\n```bash\n# Test a specific plugin\nmise test-tool ripgrep\n\n# Test a plugin with verbose output\nmise test-tool ripgrep --raw\n\n# Test multiple plugins\nmise test-tool ripgrep jq terraform\n```\n\n**Windows Tests:**\n```powershell\n# Run a specific Windows test\npwsh e2e-win\\run.ps1 -TestName \"test_name\"\n\n# Run tests matching a pattern\npwsh e2e-win\\run.ps1 task\n```\n\n#### Test Development Tips\n\n1. **Test naming**: Use descriptive names that explain what's being tested\n2. **Test isolation**: Each test should be independent and clean up after itself\n3. **Use slow tests sparingly**: Mark long-running tests as `_slow` to avoid CI timeouts\n4. **Mock external dependencies**: Use dummy plugins and mock data when possible\n5. **Test edge cases**: Include tests for error conditions and boundary cases\n\n#### Performance Testing\n```bash\n# Run performance benchmarks\nmise run test:perf\n\n# Build performance test workspace\nmise run test:build-perf-workspace\n```\n\n#### Snapshot Testing\nUsed for testing output consistency:\n\n```bash\n# Update test snapshots when output changes\nmise run snapshots\n\n# Use cargo-insta for snapshot testing\ncargo insta test --accept --unreferenced delete\n```\n\n### Available Development Tasks\n\nUse `mise tasks` to see all available development tasks:\n\n#### Common Tasks\n- `mise run build` - Build the project\n- `mise run test` - Run all tests (unit + E2E)\n- `mise run test:unit` - Run unit tests only\n- `mise run test:e2e` - Run E2E tests only\n- `mise run lint` - Run linting\n- `mise run lint:fix` - Run linting with fixes\n- `mise run format` - Format code\n- `mise run clean` - Clean build artifacts\n- `mise run snapshots` - Update test snapshots\n- `mise run render` - Generate documentation and completions\n\n#### Documentation Tasks\n- `mise run docs` - Start documentation development server\n- `mise run docs:build` - Build documentation\n- `mise run render:help` - Generate help documentation\n- `mise run render:completions` - Generate shell completions\n\n#### Release Tasks\n- `mise run ci` - Run CI tasks (format, build, test)\n\n### Project Structure\n\n```\nmise/\n├── src/           # Main Rust source code\n├── e2e/           # End-to-end tests\n├── docs/          # Documentation\n├── tasks.toml     # Development tasks\n├── mise.toml      # Project configuration\n├── Cargo.toml     # Rust project configuration\n└── xtasks/        # Additional build scripts\n```\n\n### Pre-commit Hooks & Code Quality\n\nmise uses multiple approaches for ensuring code quality and running pre-commit hooks:\n\n#### hk (Modern Hook Manager)\nmise uses [hk](https://hk.jdx.dev) (pronounced \"hook\") as its primary hook manager for linting and code quality checks. hk is a modern alternative to lefthook written by the same author as mise.\n\n**hk Configuration:**\nThe project uses `hk.pkl` (written in the Pkl configuration language) to define linting rules:\n\n```bash\n# Run all linting checks\nhk check --all\n\n# Run linting with fixes\nhk fix --all\n\n# Run specific linter\nhk check --step shellcheck\n```\n\n**Available Linters in hk:**\n- **prettier**: Code formatting for multiple languages\n- **clippy**: Rust linting with `cargo clippy`\n- **shellcheck**: Shell script linting\n- **shfmt**: Shell script formatting\n\n**Using hk in Development:**\n```bash\n# Install hk via mise\nmise use hk\n\n# Run linting (used in CI and pre-commit)\nmise run lint  # This runs hk check --all\n\n# Run linting with fixes\nhk fix --all\n\n# Check specific file types\nhk check --step prettier\nhk check --step shellcheck\n```\n\n#### Traditional Pre-commit Hooks (Alternative)\nmise also supports traditional pre-commit hooks through multiple methods:\n\n**Option 1: Using lefthook (Legacy)**\n```bash\n# Install lefthook\nmise use lefthook\n\n# Install the git hooks\nlefthook install\n\n# Run pre-commit manually\nlefthook run pre-commit\n```\n\n**Option 2: Using standard pre-commit framework**\n```bash\n# Install pre-commit\nmise use pre-commit\n\n# Install the git hooks\npre-commit install\n\n# Run pre-commit manually\npre-commit run --all-files\n```\n\n**Option 3: Using mise's built-in git hook generation**\n```bash\n# Generate a git pre-commit hook that runs mise tasks\nmise generate git-pre-commit --write --task=pre-commit\n\n# This creates .git/hooks/pre-commit that runs:\n# mise run pre-commit\n```\n\n#### Pre-commit Task Configuration\nmise defines a `pre-commit` task that runs the main linting checks:\n\n```toml\n[pre-commit]\nenv = { PRE_COMMIT = 1 }\nrun = [\"mise run lint\"]\n```\n\nThis task:\n1. Sets `PRE_COMMIT=1` environment variable\n2. Runs `mise run lint`, which executes `hk check --all`\n\n#### Setting Up Pre-commit Hooks\n**Recommended approach using hk:**\n```bash\n# Install hk\nmise use hk\n\n# Set up git hook to run mise's pre-commit task\nmise generate git-pre-commit --write --task=pre-commit\n\n# Or manually create .git/hooks/pre-commit:\ncat > .git/hooks/pre-commit << 'EOF'\n#!/bin/sh\nexec mise run pre-commit\nEOF\nchmod +x .git/hooks/pre-commit\n```\n\n**Alternative approach using standard pre-commit:**\n```bash\n# Install pre-commit\nmise use pre-commit\n\n# Install hooks defined in .pre-commit-config.yaml\npre-commit install\n```\n\n#### Running Pre-commit Checks Manually\n```bash\n# Run all pre-commit checks\nmise run pre-commit\n\n# Run specific linting checks\nmise run lint\n\n# Run linting with fixes\nhk fix --all\n\n# Run checks on specific files\nhk check --files=\"src/**/*.rs\"\n```\n\n#### Environment Variables for Hooks\nWhen hooks run, they have access to these environment variables:\n- `PRE_COMMIT=1`: Indicates the code is running in pre-commit context\n- `STAGED`: Git staged files (when using mise's git hook generation)\n- `MISE_PRE_COMMIT=1`: Set by mise's generated git hooks\n\n### Testing Configuration\n\n- **Unit tests**: Fast tests for individual components\n- **E2E tests**: Integration tests that test the full application\n- **Slow tests**: Only run with `TEST_ALL=1` environment variable\n- **Windows tests**: Separate PowerShell-based test suite\n\n### Development Tips\n\n1. **Disable mise during development**: If you use mise in your shell, disable it when running tests to avoid conflicts\n2. **Use dev container**: Docker setup available (currently needs fixing)\n3. **Test specific features**: Use `cargo test <test_name>` for targeted testing\n4. **Update snapshots**: Use `mise run snapshots` when changing test outputs\n5. **Rate limiting**: Set `MISE_GITHUB_TOKEN` to avoid GitHub API rate limits during development\n\n### Dependency Management\n\nmise uses several tools to validate dependencies and code quality:\n\n- **cargo-deny**: Validates licenses, security advisories, and dependency duplicates\n- **cargo-msrv**: Verifies minimum supported Rust version compatibility\n- **cargo-machete**: Detects unused dependencies in Cargo.toml\n\nThese checks run automatically in CI and can be run locally:\n```bash\n# Install tools\nmise use cargo-deny cargo-msrv cargo-machete\n\n# Run checks\ncargo deny check\ncargo msrv verify\ncargo machete --with-metadata\n```\n\n### Contributing Guidelines\n\n1. **Before starting**: File an issue or discuss in Discord for non-obvious changes\n2. **Look for issues**: Check \"help wanted\" and \"good first issue\" labels\n3. **Test thoroughly**: Ensure both unit and E2E tests pass\n4. **Follow conventions**: Use existing code style and patterns\n5. **Update documentation**: Add/update docs for new features\n\n#### Pull Request Workflow\n1. **PR titles**: Must follow conventional commit format (validated automatically)\n2. **Auto-formatting**: Code will be automatically formatted by autofix.ci\n3. **CI checks**: All tests must pass across Linux, macOS, and Windows\n4. **Coverage**: New code should maintain or improve test coverage\n5. **Dependencies**: New dependencies are validated with cargo-deny\n\n#### GitHub Actions Development\nIf modifying GitHub Actions workflows:\n- Run `mise run lint` for the repository's configured checks\n- Self-hosted runners are configured for performance testing\n- Run the zizmor workflow for security auditing\n\n### Conventional Commits\n\nmise uses [Conventional Commits](https://www.conventionalcommits.org/) for consistent commit messages and automated changelog generation. All commits should follow this format:\n\n```\n<type>[optional scope]: <description>\n\n[optional body]\n\n[optional footer(s)]\n```\n\n#### Commit Types\n\n- **feat**: New features (🚀 Features)\n- **fix**: Bug fixes (🐛 Bug Fixes)\n- **refactor**: Code refactoring (🚜 Refactor)\n- **doc**: Documentation changes (📚 Documentation)\n- **style**: Code style changes (🎨 Styling)\n- **perf**: Performance improvements (⚡ Performance)\n- **test**: Testing changes (🧪 Testing)\n- **chore**: Maintenance tasks, dependency updates\n- **revert**: Reverting previous changes (◀️ Revert)\n\n#### Examples\n\n```bash\nfeat(cli): add new command for listing plugins\nfix(parser): handle edge case in version parsing\nrefactor(config): simplify configuration loading logic\ndoc(readme): update installation instructions\ntest(e2e): add tests for new plugin functionality\nchore(deps): update dependencies to latest versions\n```\n\n#### Scopes\n\nCommon scopes used in mise:\n- `cli` - Command line interface changes\n- `config` - Configuration system changes\n- `parser` - Parsing logic changes\n- `deps` - Dependency updates\n- `security` - Security-related changes\n\n#### Breaking Changes\n\nFor breaking changes, add `!` after the type or include `BREAKING CHANGE:` in the footer:\n\n```bash\nfeat(api)!: remove deprecated configuration options\n# OR\nfeat(api): remove deprecated configuration options\n\nBREAKING CHANGE: The old configuration format is no longer supported\n```\n\n### Packaging Testing\n\nFor testing package installation:\n\n#### Ubuntu/Debian\n```bash\n# Test apt installation\ndocker run -ti --rm ubuntu\napt update -y && apt install -y curl\n# ... installation steps\n```\n\n#### Fedora\n```bash\n# Test dnf installation  \ndocker run -ti --rm fedora\ndnf install -y dnf-plugins-core\n# ... installation steps\n```\n\n### CI/CD & Pull Request Automation\n\nmise uses several automated workflows to maintain code quality and streamline development:\n\n#### Automated Code Formatting\n- **autofix.ci**: Automatically formats code and fixes linting issues in PRs\n- Runs `mise run render` and `mise run lint-fix` automatically\n- Commits fixes directly to the PR branch\n\n#### PR Title Validation\n- **semantic-pr-lint**: Validates PR titles follow conventional commit format\n- PR titles must match: `<type>[optional scope]: <description>`\n- Example: `feat(cli): add new command for listing plugins`\n\n#### Continuous Integration\n- **Cross-platform testing**: Ubuntu, macOS, and Windows\n- **Unit tests**: Fast component-level tests\n- **E2E tests**: Full integration testing with multiple test tranches\n- **Coverage testing**: Code coverage across 8 parallel test runs\n- **Dependency validation**: `cargo deny`, `cargo msrv`, `cargo machete`\n\n#### Release Automation\n- **release-plz**: Automated release management based on conventional commits\n- Automatically creates release PRs and publishes releases\n- Runs daily via scheduled workflow\n- Handles version bumping and changelog generation\n\n## mise Codebase Architecture\n\n### Overview\n\nmise is a Rust-based tool with a modular architecture designed around three main concepts:\n1. **Tool Version Management** - Managing different versions of development tools\n2. **Environment Management** - Setting up environment variables and project contexts\n3. **Task Running** - Executing project tasks with dependency management\n\n### Core Architecture Components\n\n#### 1. **Main Entry Point** (`src/main.rs`)\n- Asynchronous Tokio runtime with multi-threading\n- Global error handling and panic hooks\n- CLI argument parsing and routing\n- Multi-progress reporting system\n\n#### 2. **CLI Layer** (`src/cli/`)\n- **Command Structure**: Each command is a separate module (e.g., `install.rs`, `use.rs`, `run.rs`)\n- **Argument Parsing**: Uses `clap` for command-line argument handling\n- **Command Execution**: Async command execution with proper error handling\n- **Key Commands**:\n  - `install` - Install tool versions\n  - `use` - Add tools to configuration\n  - `run` - Execute tasks\n  - `env` - Environment management\n  - `shell` - Shell integration\n\n#### 3. **Backend System** (`src/backend/`)\nThe backend system is the core abstraction for tool management:\n\n**Backend Trait**: Common interface for all tool backends\n```rust\npub trait Backend: Debug + Send + Sync {\n    async fn list_remote_versions(&self) -> Result<Vec<String>>;\n    async fn install_version(&self, ctx: &InstallContext, tv: &ToolVersion) -> Result<()>;\n    async fn uninstall_version(&self, tv: &ToolVersion) -> Result<()>;\n    // ... other methods\n}\n```\n\n**Backend Types**:\n- **Core Backends**: Built-in support (Node.js, Python, etc.)\n- **ASDF Backends**: External plugin system compatibility\n- **Aqua Backends**: Package manager integration\n- **Language-specific**: npm, cargo, pipx, gem, go, etc.\n- **Universal**: ubi (GitHub releases)\n\n#### 4. **Configuration System** (`src/config/`)\n**Hierarchical Configuration**:\n- `Config` struct manages all configuration sources\n- `ConfigFile` trait for different config formats:\n  - `MiseToml` - Main configuration format\n  - `ToolVersions` - ASDF compatibility\n  - `IdiomaticVersion` - Language-specific files (`.nvmrc`, `.python-version`)\n\n**Configuration Hierarchy**:\n1. System config (`/etc/mise/config.toml`)\n2. Global config (`~/.config/mise/config.toml`)\n3. Project configs (searched up directory tree)\n4. Environment-specific configs (`mise.dev.toml`)\n\n#### 5. **Toolset Management** (`src/toolset/`)\n**Core Components**:\n- `Toolset` - Collection of tools for a specific context\n- `ToolVersion` - Represents a specific version of a tool\n- `ToolRequest` - User request for a tool (e.g., `node@18`)\n- `ToolsetBuilder` - Constructs toolsets from configuration\n\n**Tool Resolution Flow**:\n1. Parse configuration files\n2. Resolve version specifications\n3. Build toolset with dependencies\n4. Install missing tools\n5. Set up environment\n\n#### 6. **Task System** (`src/task/`)\n**Task Components**:\n- `Task` struct with metadata, dependencies, and execution info\n- `Deps` - Dependency graph management using petgraph\n- `TaskFileProvider` - Discovers tasks from files and configuration\n- Parallel execution with dependency resolution\n\n**Task Types**:\n- **TOML Tasks**: Defined in `mise.toml`\n- **File Tasks**: Executable scripts in task directories\n- **Command Tasks**: Simple command execution\n- **Script Tasks**: Inline script execution\n\n#### 7. **Plugin System** (`src/plugins/`)\n**Plugin Architecture**:\n- `Plugin` trait for extensibility\n- `AsdfPlugin` - ASDF plugin compatibility\n- `VfoxPlugin` - Vfox plugin system\n- `ScriptManager` - Manages plugin scripts\n\n**Plugin Types**:\n- **Core Plugins**: Built into mise\n- **External Plugins**: Downloaded from repositories\n- **Local Plugins**: Custom local implementations\n\n#### 8. **Shell Integration** (`src/shell/`)\n**Shell Support**:\n- Bash, Zsh, Fish, PowerShell support\n- `Shell` trait for shell-specific behavior\n- Activation scripts for environment setup\n- Hook system for directory changes\n\n#### 9. **Environment Management** (`src/env*.rs`)\n**Environment Components**:\n- `EnvDiff` - Tracks environment changes\n- `EnvDirective` - Configuration for environment variables\n- `PathEnv` - PATH management\n- Context-aware environment resolution\n\n#### 10. **Caching System** (`src/cache.rs`)\n**Cache Management**:\n- `CacheManager` - Generic caching with TTL\n- File-based caching for versions, metadata\n- Automatic cache invalidation\n- Per-backend cache isolation\n\n### Key Design Patterns\n\n#### 1. **Trait-Based Architecture**\n- `Backend` trait for tool management\n- `ConfigFile` trait for configuration formats\n- `Shell` trait for shell integration\n- `Plugin` trait for extensibility\n\n#### 2. **Async/Await Throughout**\n- Tokio runtime for async operations\n- Parallel tool installations\n- Concurrent task execution\n- Non-blocking I/O operations\n\n#### 3. **Error Handling**\n- `eyre` crate for error management\n- Structured error types\n- Context-aware error reporting\n- Graceful fallback behavior\n\n#### 4. **Configuration Hierarchy**\n- Multiple configuration sources\n- Inheritance and overrides\n- Environment-specific configurations\n- Validation and trust system\n\n#### 5. **Dependency Management**\n- Tool dependencies (e.g., Node.js for npm tools)\n- Task dependencies with DAG resolution\n- Parallel execution with proper ordering\n- Circular dependency detection\n\n### Data Flow\n\n1. **Initialization**: Load configuration hierarchy\n2. **Tool Discovery**: Find available backends and versions\n3. **Resolution**: Resolve tool requests to specific versions\n4. **Installation**: Install missing tools in dependency order\n5. **Environment Setup**: Configure PATH and environment variables\n6. **Execution**: Run tasks or provide shell integration\n\n### Testing Architecture\n\n**Test Structure**:\n- **Unit Tests**: Component-level testing with mocks\n- **Integration Tests**: End-to-end CLI testing\n- **E2E Tests**: Real-world scenario testing\n- **Snapshot Tests**: Output comparison testing\n\n**Test Organization**:\n- `src/` - Unit tests alongside source code\n- `e2e/` - End-to-end test scripts\n- `test/` - Test fixtures and utilities\n- `src/snapshots/` - Snapshot test data\n\nThis architecture provides a flexible, extensible foundation for managing development environments while maintaining compatibility with existing tools and workflows.\n\nThis covers the essential information about mise for LLMs to help users effectively use the tool for development environment management and contribute to its development.\n","isInternal":false,"tokens":7070,"sizeBytes":29029},{"name":"architecture.md","path":"docs/architecture.md","rawUrl":"https://raw.githubusercontent.com/jdx/mise/HEAD/docs/architecture.md","title":"docs - System Architecture & Module Boundaries","category":"project-spec","format":"markdown","content":"---\ndescription: \"Find where commands, configuration, backends, tasks, environments, and bootstrap live in the mise source tree.\"\noutline: [2, 3]\n---\n\n# Codebase architecture\n\nUse this map to find the code that owns a behavior before you change it. For\nsetup, checks, and how to submit a change, see [Contributing](/contributing.html).\n\n## Library, binary, and crates {#library-binary-and-crates}\n\nThe `mise` package builds two targets. The library, `src/lib.rs`, holds\neverything except the command line: configuration, toolsets, backends, tasks,\nenvironments, and bootstrap. The binary, `src/main.rs` plus `src/cli/`, sits on\ntop of it. `src/main.rs` imports the library's root with `use mise::*`, so code\nin `src/cli/` still writes `crate::config::…`. A change confined to `src/cli/`\nrecompiles only the binary.\n\nLibrary code must not refer to `crate::cli`. When core code needs command\nbehavior, it calls a hook in\n[`src/frontend.rs`](https://github.com/jdx/mise/blob/main/src/frontend.rs),\nwhich the binary fills in at startup with `cli::register_frontend`. The hooks\ncover running `mise lock` after an install adds versions and listing subcommand\nnames for \"did you mean\" suggestions. When `cli` needs a core item, make that\nitem `pub`. The library denies `unreachable_pub`, so everything else stays\n`pub(crate)`.\n\n`cfg(test)` is set for the binary's tests but not for the library they call, so\ncore code that behaves differently under tests checks\n`mise_util::testing::in_tests()` instead.\n\nThe workspace crates under `crates/` cannot depend on the `mise` package.\n`register_util_hooks` in `src/lib.rs` gives them what they need from mise, such\nas the settings loader and the build identity used in cache keys, before\nanything else runs.\n\n| Crate                     | Contents                                                                                                   |\n| ------------------------- | ---------------------------------------------------------------------------------------------------------- |\n| `mise-util`               | Environment, directory, file, HTTP, cache, template, and `EnvDiff`/`PathEnv` helpers                       |\n| `mise-daemons`            | Daemon declarations, ports, presets, and the supervisor runtime (the toolset glue stays in `src/daemons/`) |\n| `mise-oci`                | The OCI registry client, layers, and image layout (the image builder stays in `src/oci/`)                  |\n| `mise-system`             | The bootstrap, dotfiles, and history modules                                                               |\n| `mise-config`             | The `mise.toml` declaration types, so far for `[bootstrap]`, `[dotfiles]`, and `[history]`                 |\n| `mise-system-packages`    | System package manager drivers: apt, dnf, brew, brew-cask, and more                                        |\n| `mise-ui`                 | Progress reports, prompts, and themes for the terminal                                                     |\n| `mise-settings`           | The `Settings` types, generated from `settings.toml`, and the process-wide settings cache                  |\n| `vfox`                    | The embedded Lua runtime and the hook and module interfaces for vfox plugins                               |\n| `aqua-registry`           | Parsing, package lookup, and cache formats for aqua registries                                             |\n| `mise-bootstrap`          | Bootstrap resource planning and dependency ordering                                                        |\n| `mise-lsp`                | The language server behind `mise lsp`; mise passes it `schema/mise.json` and the `mise fmt` formatter      |\n| `mise-cache-core`         | The remote task cache protocol, content-addressed storage, authentication, and transport                   |\n| `mise-shim`               | `mise-shim.exe`, the native executable that Windows shims use in the default `exe` mode                    |\n| `mise-sigstore`           | Sigstore verification helpers                                                                              |\n| `mise-tls`                | Root certificate fallback for HTTPS clients when the system trust store is empty                           |\n| `mise-agent-env`          | Detection of AI coding agents from the process environment                                                 |\n| `mise-interactive-config` | The interactive TOML editor behind `mise edit`                                                             |\n| `mise-brew-metadata`      | Homebrew formula metadata models                                                                           |\n| `mise-brew-relocation`    | Homebrew bottle placeholder and binary relocation                                                          |\n| `mise-dotenv`             | A dotenv parser with explicit control over variable substitution                                           |\n\n## Where things live {#where-things-live}\n\n| Behavior                                 | Code                                                                                                               | User docs                                        |\n| ---------------------------------------- | ------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------ |\n| Commands, flags, and help text           | `src/cli/`; `mod.rs` dispatches, and each command has a file or directory such as `use.rs`, `exec.rs`, or `tasks/` | [CLI reference](/cli/)                           |\n| What each command changes                | `src/cli/command_effects.rs`                                                                                       |                                                  |\n| Config discovery, loading, and merging   | `src/config/`; `config_file/` holds `MiseToml`, `ToolVersions`, and `IdiomaticVersionFile`                         | [mise.toml](/configuration.html)                 |\n| Settings                                 | `settings.toml`, generated into `crates/mise-settings`; loading, trust, and CLI flags in `src/config/settings.rs`  | [Settings](/configuration/settings.html)         |\n| Config file schema                       | `schema/mise.json`                                                                                                 | [mise.toml](/configuration.html)                 |\n| Tool requests, resolution, install state | `src/toolset/`                                                                                                     | [Dev tools](/dev-tools/)                         |\n| Backends                                 | `src/backend/`; the `Backend` trait is in `mod.rs` and `BackendType` in `backend_type.rs`                          | [Backends](/dev-tools/backends/)                 |\n| Core tools                               | `src/plugins/core/`                                                                                                | [Core tools](/core-tools.html)                   |\n| Plugins                                  | `src/plugins/` (asdf and vfox adapters) and `crates/vfox`                                                          | [Plugins](/plugins.html)                         |\n| Tool shorthands                          | `registry/*.toml`, compiled in by `build.rs`; lookup in `src/registry.rs`                                          | [Registry](/registry.html)                       |\n| aqua registry                            | `crates/aqua-registry`; the bundled snapshot is `vendor/aqua-registry/`, baked in by `build.rs`                    | [aqua](/dev-tools/backends/aqua.html)            |\n| Lockfile                                 | `src/lockfile.rs` and `src/lockfile/`                                                                              | [Lockfile](/dev-tools/mise-lock.html)            |\n| Environment directives                   | `src/config/env_directive/`; `EnvDiff` and `PathEnv` come from `crates/mise-util`                                  | [Environment variables](/environments/)          |\n| Shell activation                         | `src/shell/` (one file per shell), `src/hook_env.rs`, `src/cli/activate.rs`                                        | [Shell setup](/shell-setup.html)                 |\n| Shims                                    | `src/shims.rs` and `crates/mise-shim`                                                                              | [Shims](/dev-tools/shims.html)                   |\n| Templates                                | `crates/mise-util/src/tera.rs`, re-exported as `src/tera.rs`                                                       | [Tera templates](/templates.html)                |\n| Tasks                                    | `src/task/`                                                                                                        | [Tasks](/tasks/)                                 |\n| Remote task cache                        | `crates/mise-cache-core`                                                                                           | [Remote task cache](/tasks/remote-cache.html)    |\n| Bootstrap and host packages              | `src/cli/bootstrap.rs`, `crates/mise-system` (packages in `crates/mise-system-packages`), `crates/mise-bootstrap`  | [Bootstrap](/bootstrap.html)                     |\n| Dotfiles                                 | `src/cli/dotfiles/`, `crates/mise-system/src/managed_files.rs`, `crates/mise-system/src/history/`                  | [Dotfiles](/dotfiles.html)                       |\n| Daemons                                  | `src/daemons/` (toolset glue), `crates/mise-daemons`                                                               | [Daemons](/daemons.html)                         |\n| Project dependencies                     | `src/deps/`                                                                                                        | [Project dependencies](/dev-tools/deps.html)     |\n| Secrets                                  | `src/secrets/`, `src/sops.rs`, `src/agecrypt.rs`                                                                   | [Secrets](/environments/secrets/)                |\n| Caches                                   | `crates/mise-util/src/cache.rs`: `CacheManager<T>`, MessagePack with zlib, written atomically                      | [Caches](/cache-behavior.html)                   |\n| packslip manifests                       | `src/packslip.rs`, `src/backend/packslip.rs`                                                                       | [packslip](/dev-tools/backends/packslip.html)    |\n| OCI images                               | `src/oci/` (builder), `crates/mise-oci`                                                                            | [OCI images](/dev-tools/mise-oci.html)           |\n| OpenTelemetry                            | `src/otel/`                                                                                                        | [OpenTelemetry](/tasks/opentelemetry.html)       |\n| Identity install layout                  | `src/install_layout/`                                                                                              | [Install layout](/dev-tools/install-layout.html) |\n| Sandboxing                               | `src/sandbox.rs`                                                                                                   | [Sandboxing](/sandboxing.html)                   |\n| Self-update                              | `src/cli/self_update.rs`                                                                                           | [Packaging mise](/packaging.html)                |\n\n## How a command runs {#system-overview}\n\nMost commands load the configuration, resolve the tools it requests, build an\nenvironment from them, and then run a child process or print shell code. Tasks\nand bootstrap start from the same configuration.\n\n```mermaid\nflowchart TD\n    CLI[CLI command] --> Config[Configuration and settings]\n    Config --> Tools[Tool requests and backend resolution]\n    Tools --> Env[Environment and PATH]\n    Env --> Exec[Child command or shell output]\n    Config --> Tasks[Task discovery and dependency graph]\n    Tasks --> Env\n    Config --> Bootstrap[Bootstrap plan and explicit apply]\n```\n\n### Configuration {#configuration-system}\n\n[`src/config`](https://github.com/jdx/mise/tree/main/src/config) finds config\nfiles, loads them through the `ConfigFile` trait, and merges them. Which files\nare found, whether they are trusted, and how each field merges are separate\ndecisions in the code. Settings, tools, environment directives, tasks, and\nbootstrap entries do not merge the same way, and write commands pick their\n[target file](/configuration.html#target-file-for-write-operations) separately.\n\n### Toolsets {#toolset-management}\n\n[`src/toolset`](https://github.com/jdx/mise/tree/main/src/toolset) connects\nversion requests to resolved versions and installation state:\n\n| Type             | Role                                                                                  |\n| ---------------- | ------------------------------------------------------------------------------------- |\n| `ToolRequest`    | A request such as `node@24`, a channel, or a ref, with its backend and options        |\n| `ToolVersion`    | A resolved version and its installation metadata                                      |\n| `Toolset`        | The requests and resolved versions for the current context                            |\n| `ToolsetBuilder` | Combines config, environment variable overrides, and command arguments, then resolves |\n\n### Backends {#backend-system}\n\nThe [`Backend` trait](https://github.com/jdx/mise/blob/main/src/backend/mod.rs)\nsplits shared policy from backend-specific work. Its public wrapper methods\nhandle caching and resolution. A backend implements hooks such as\n`_list_remote_versions`, which returns `VersionInfo` entries, and\n`install_version_`. Core tools in `src/plugins/core/` implement the same trait.\nFor how mise picks a backend for a short name, see\n[how backend selection works](/dev-tools/backends/#how-backend-selection-works);\nto add one, see [Adding a backend](/contributing.html#adding-backends).\n\n### Plugins {#plugins}\n\n[`src/plugins`](https://github.com/jdx/mise/tree/main/src/plugins) installs\nplugin sources and records their metadata.\n[`crates/vfox`](https://github.com/jdx/mise/tree/main/crates/vfox) runs vfox\nplugins in its embedded Lua runtime. Tool plugins install one tool, backend\nplugins handle `plugin:tool` requests, environment plugins return variables and\n`PATH` entries, and package plugins manage batches of host packages. asdf\nadapters run legacy shell scripts. Installing or updating a plugin's source is\nseparate from installing a tool version, and each keeps its own state. See\n[Plugins](/plugins.html).\n\n### Tasks {#task-system}\n\n[`src/task`](https://github.com/jdx/mise/tree/main/src/task) discovers, schedules,\nand runs tasks. `Task` holds a definition, the providers in\n`task_file_providers/` load local and remote task files, `Deps` is the\ndependency graph, and the executor and scheduler run ready tasks under the\nconfigured concurrency and output style. A node in the graph is a task with its\narguments, environment variables, and run phase, so the same task with\ndifferent arguments is a separate node. Read\n[Dependencies and execution order](/tasks/architecture.html) before you change\nhow the graph is built or how `depends`, `depends_post`, and `wait_for` behave.\n\n### Environment and shell activation {#shell-integration}\n\n`src/config/env_directive` evaluates `[env]` directives. Directives marked\n`tools = true` run after tools are resolved, and the rest run before.\n`mise activate` emits a shell hook from `src/shell/` that runs `mise hook-env`\nat each prompt. `hook-env` records an `EnvDiff` so the next run can undo the previous\ndirectory's changes before applying new ones. `mise exec` and `mise run` build\nthe child environment directly and do not need activation.\n\n### Bootstrap and host state {#bootstrap-and-host-state}\n\n`src/cli/bootstrap.rs` builds a plan and runs the selected phases. The code in\n`crates/mise-system` manages packages, files, edits, repositories, services, and\nplatform-specific resources, which live outside any tool's install directory.\nStatus, preview, apply, and prune are separate operations: a status check reads\nthe host and changes nothing. A package batch can be a subset named on the\ncommand line, so never treat a package's absence from a batch as a request to\nremove it.\n\n## Rules to preserve {#rules-to-preserve}\n\n- Treat versions as opaque strings. Resolve a request through the backend\n  (`Backend::latest_version`, `Backend::list_versions_matching`,\n  `ToolRequest::resolve`), never with a semver sort at a new call site.\n- Compare lockfile versions with `==`, keep the backend and checksum of an\n  entry, and never write `latest`, `lts/*`, or a prefix into the lockfile.\n- Do not add installs or network requests to a code path that only reports\n  local state.\n- Build a subprocess's environment from the one mise computed, not the\n  inherited process environment, which can miss earlier directives or select\n  the wrong tool.\n- Include every input that changes a cached result in its cache key, such as\n  options, environment variables, and source metadata. The environment cache\n  (`src/toolset/env_cache.rs`) and the task caches (`src/task/task_cache.rs`)\n  do not use `CacheManager` and have their own formats and invalidation rules.\n- Keep Windows `PATH` in native form inside mise and in child processes.\n  Convert it only when emitting assignments into a running, positively\n  identified MSYS2 or Cygwin shell; the\n  [agent guide](https://github.com/jdx/mise/blob/main/AGENTS.md) has the full\n  rules.\n- Classify every new command in `src/cli/command_effects.rs`; see\n  [Changing a CLI command](/contributing.html#changing-a-cli-command).\n\n## Generated files {#generated-files}\n\nEdit the source, then regenerate. Commit the output with the change that\nproduced it.\n\n| Output                                                                 | Source                                                                                                                                                   | Regenerate with                               |\n| ---------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------- |\n| `mise.usage.kdl`, `docs/cli/`                                          | Command definitions in `src/cli/`, `src/assets/mise-extra.usage.kdl`, and `docs/.vitepress/cli-reference.ts`                                             | `mise run render:usage`                       |\n| `tasks.md`                                                             | The project's tasks in `tasks.toml`, `xtasks/`, and `mise.toml`, through `mise generate task-docs`                                                       | `mise run render:usage`                       |\n| `man/man1/mise.1`                                                      | `mise.usage.kdl`                                                                                                                                         | `mise run render:mangen`                      |\n| `completions/`                                                         | The usage spec, through `mise completion <shell>`                                                                                                        | `mise run render:completions`                 |\n| `docs/.vitepress/cli_commands.ts` and the idiomatic version file table | `src/cli/` and the `idiomatic_files` keys in `registry/*.toml`                                                                                           | `mise run render:help`                        |\n| `schema/mise.json`, `schema/mise-task.json`, `schema/miserc.json`      | The types and doc comments in `crates/mise-config` (`MiseTomlDecl` for the top level) and `settings.toml`, through mise-config's `render-schema` example | `mise run render:schema`                      |\n| `docs/public/llms.txt`                                                 | Page titles and leads, and `docs/.vitepress/sidebar.ts`                                                                                                  | `mise run render:llms`                        |\n| `Settings` types                                                       | `settings.toml`                                                                                                                                          | Every build (`crates/mise-settings/build.rs`) |\n| The registry compiled into mise                                        | `registry/*.toml`                                                                                                                                        | Every build (`build.rs`)                      |\n| The [settings reference](/configuration/settings.html)                 | `settings.toml`                                                                                                                                          | Every docs build                              |\n\n`mise run render` runs every `render:*` task. For the schemas, change the types\nand doc comments in `crates/mise-config`, not the JSON; a `mise-config` test\nfails while the committed files are stale.\n\n## Tests {#tests}\n\nUnit tests sit beside the code they test, E2E tests are Bash scripts under\n`e2e/` run with `mise run test:e2e`, and the Windows E2E tests under `e2e-win/`\nuse Pester. See [Testing](/contributing.html#testing) for the commands and\nprerequisites.\n","frontmatter":{"description":"Find where commands, configuration, backends, tasks, environments, and bootstrap live in the mise source tree.","outline":[2,3]},"isInternal":false,"tokens":4045,"sizeBytes":22028},{"name":".luarc.json","path":"crates/vfox/plugins/.luarc.json","rawUrl":"https://raw.githubusercontent.com/jdx/mise/HEAD/crates/vfox/plugins/.luarc.json","title":"Plugins Skill","category":"anthropic-skill","format":"json","content":"{\n  \"$schema\": \"https://raw.githubusercontent.com/LuaLS/vscode-lua/master/setting/schema.json\",\n  \"runtime\": {\n    \"version\": \"Lua 5.1\"\n  },\n  \"diagnostics\": {\n    \"disable\": [\"duplicate-set-field\"]\n  },\n  \"workspace\": {\n    \"checkThirdParty\": false,\n    \"library\": [\"../types\"]\n  }\n}\n","frontmatter":{"$schema":"https://raw.githubusercontent.com/LuaLS/vscode-lua/master/setting/schema.json","runtime":{"version":"Lua 5.1"},"diagnostics":{"disable":["duplicate-set-field"]},"workspace":{"checkThirdParty":false,"library":["../types"]}},"isInternal":false,"tokens":84,"sizeBytes":285},{"name":"apk.md","path":"docs/bootstrap/packages/apk.md","rawUrl":"https://raw.githubusercontent.com/jdx/mise/HEAD/docs/bootstrap/packages/apk.md","title":"Packages Skill","category":"anthropic-skill","format":"markdown","content":"# Packages Skill\n\nPath: `docs/bootstrap/packages/apk.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/bootstrap/packages/apk.md)","tokens":300,"sizeBytes":166},{"name":"apt.md","path":"docs/bootstrap/packages/apt.md","rawUrl":"https://raw.githubusercontent.com/jdx/mise/HEAD/docs/bootstrap/packages/apt.md","title":"Packages Skill","category":"anthropic-skill","format":"markdown","content":"# Packages Skill\n\nPath: `docs/bootstrap/packages/apt.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/bootstrap/packages/apt.md)","tokens":300,"sizeBytes":166},{"name":"brew.md","path":"docs/bootstrap/packages/brew.md","rawUrl":"https://raw.githubusercontent.com/jdx/mise/HEAD/docs/bootstrap/packages/brew.md","title":"Packages Skill","category":"anthropic-skill","format":"markdown","content":"# Packages Skill\n\nPath: `docs/bootstrap/packages/brew.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/bootstrap/packages/brew.md)","tokens":300,"sizeBytes":168},{"name":"dnf.md","path":"docs/bootstrap/packages/dnf.md","rawUrl":"https://raw.githubusercontent.com/jdx/mise/HEAD/docs/bootstrap/packages/dnf.md","title":"Packages Skill","category":"anthropic-skill","format":"markdown","content":"# Packages Skill\n\nPath: `docs/bootstrap/packages/dnf.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/bootstrap/packages/dnf.md)","tokens":300,"sizeBytes":166},{"name":"flatpak.md","path":"docs/bootstrap/packages/flatpak.md","rawUrl":"https://raw.githubusercontent.com/jdx/mise/HEAD/docs/bootstrap/packages/flatpak.md","title":"Packages Skill","category":"anthropic-skill","format":"markdown","content":"# Packages Skill\n\nPath: `docs/bootstrap/packages/flatpak.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/bootstrap/packages/flatpak.md)","tokens":300,"sizeBytes":174},{"name":"index.md","path":"docs/bootstrap/packages/index.md","rawUrl":"https://raw.githubusercontent.com/jdx/mise/HEAD/docs/bootstrap/packages/index.md","title":"Packages Skill","category":"anthropic-skill","format":"markdown","content":"# Packages Skill\n\nPath: `docs/bootstrap/packages/index.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/bootstrap/packages/index.md)","tokens":300,"sizeBytes":170},{"name":"mas.md","path":"docs/bootstrap/packages/mas.md","rawUrl":"https://raw.githubusercontent.com/jdx/mise/HEAD/docs/bootstrap/packages/mas.md","title":"Packages Skill","category":"anthropic-skill","format":"markdown","content":"# Packages Skill\n\nPath: `docs/bootstrap/packages/mas.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/bootstrap/packages/mas.md)","tokens":300,"sizeBytes":166},{"name":"pacman.md","path":"docs/bootstrap/packages/pacman.md","rawUrl":"https://raw.githubusercontent.com/jdx/mise/HEAD/docs/bootstrap/packages/pacman.md","title":"Packages Skill","category":"anthropic-skill","format":"markdown","content":"# Packages Skill\n\nPath: `docs/bootstrap/packages/pacman.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/bootstrap/packages/pacman.md)","tokens":300,"sizeBytes":172},{"name":"plugins.md","path":"docs/bootstrap/packages/plugins.md","rawUrl":"https://raw.githubusercontent.com/jdx/mise/HEAD/docs/bootstrap/packages/plugins.md","title":"Packages Skill","category":"anthropic-skill","format":"markdown","content":"# Packages Skill\n\nPath: `docs/bootstrap/packages/plugins.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/bootstrap/packages/plugins.md)","tokens":300,"sizeBytes":174},{"name":"apply.md","path":"docs/cli/bootstrap/packages/apply.md","rawUrl":"https://raw.githubusercontent.com/jdx/mise/HEAD/docs/cli/bootstrap/packages/apply.md","title":"Packages Skill","category":"anthropic-skill","format":"markdown","content":"# Packages Skill\n\nPath: `docs/cli/bootstrap/packages/apply.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/cli/bootstrap/packages/apply.md)","tokens":300,"sizeBytes":178},{"name":"brew.md","path":"docs/cli/bootstrap/packages/brew.md","rawUrl":"https://raw.githubusercontent.com/jdx/mise/HEAD/docs/cli/bootstrap/packages/brew.md","title":"Packages Skill","category":"anthropic-skill","format":"markdown","content":"# Packages Skill\n\nPath: `docs/cli/bootstrap/packages/brew.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/cli/bootstrap/packages/brew.md)","tokens":300,"sizeBytes":176},{"name":"tap.md","path":"docs/cli/bootstrap/packages/brew/tap.md","rawUrl":"https://raw.githubusercontent.com/jdx/mise/HEAD/docs/cli/bootstrap/packages/brew/tap.md","title":"Brew Skill","category":"anthropic-skill","format":"markdown","content":"# Brew Skill\n\nPath: `docs/cli/bootstrap/packages/brew/tap.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/cli/bootstrap/packages/brew/tap.md)","tokens":300,"sizeBytes":180},{"name":"untap.md","path":"docs/cli/bootstrap/packages/brew/untap.md","rawUrl":"https://raw.githubusercontent.com/jdx/mise/HEAD/docs/cli/bootstrap/packages/brew/untap.md","title":"Brew Skill","category":"anthropic-skill","format":"markdown","content":"# Brew Skill\n\nPath: `docs/cli/bootstrap/packages/brew/untap.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/cli/bootstrap/packages/brew/untap.md)","tokens":300,"sizeBytes":184},{"name":"import.md","path":"docs/cli/bootstrap/packages/import.md","rawUrl":"https://raw.githubusercontent.com/jdx/mise/HEAD/docs/cli/bootstrap/packages/import.md","title":"Packages Skill","category":"anthropic-skill","format":"markdown","content":"# Packages Skill\n\nPath: `docs/cli/bootstrap/packages/import.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/cli/bootstrap/packages/import.md)","tokens":300,"sizeBytes":180},{"name":"prune.md","path":"docs/cli/bootstrap/packages/prune.md","rawUrl":"https://raw.githubusercontent.com/jdx/mise/HEAD/docs/cli/bootstrap/packages/prune.md","title":"Packages Skill","category":"anthropic-skill","format":"markdown","content":"# Packages Skill\n\nPath: `docs/cli/bootstrap/packages/prune.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/cli/bootstrap/packages/prune.md)","tokens":300,"sizeBytes":178},{"name":"status.md","path":"docs/cli/bootstrap/packages/status.md","rawUrl":"https://raw.githubusercontent.com/jdx/mise/HEAD/docs/cli/bootstrap/packages/status.md","title":"Packages Skill","category":"anthropic-skill","format":"markdown","content":"# Packages Skill\n\nPath: `docs/cli/bootstrap/packages/status.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/cli/bootstrap/packages/status.md)","tokens":300,"sizeBytes":180},{"name":"upgrade.md","path":"docs/cli/bootstrap/packages/upgrade.md","rawUrl":"https://raw.githubusercontent.com/jdx/mise/HEAD/docs/cli/bootstrap/packages/upgrade.md","title":"Packages Skill","category":"anthropic-skill","format":"markdown","content":"# Packages Skill\n\nPath: `docs/cli/bootstrap/packages/upgrade.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/cli/bootstrap/packages/upgrade.md)","tokens":300,"sizeBytes":182},{"name":"use.md","path":"docs/cli/bootstrap/packages/use.md","rawUrl":"https://raw.githubusercontent.com/jdx/mise/HEAD/docs/cli/bootstrap/packages/use.md","title":"Packages Skill","category":"anthropic-skill","format":"markdown","content":"# Packages Skill\n\nPath: `docs/cli/bootstrap/packages/use.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/cli/bootstrap/packages/use.md)","tokens":300,"sizeBytes":174},{"name":"apply.md","path":"docs/cli/bootstrap/plugins/apply.md","rawUrl":"https://raw.githubusercontent.com/jdx/mise/HEAD/docs/cli/bootstrap/plugins/apply.md","title":"Plugins Skill","category":"anthropic-skill","format":"markdown","content":"# Plugins Skill\n\nPath: `docs/cli/bootstrap/plugins/apply.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/cli/bootstrap/plugins/apply.md)","tokens":300,"sizeBytes":175},{"name":"status.md","path":"docs/cli/bootstrap/plugins/status.md","rawUrl":"https://raw.githubusercontent.com/jdx/mise/HEAD/docs/cli/bootstrap/plugins/status.md","title":"Plugins Skill","category":"anthropic-skill","format":"markdown","content":"# Plugins Skill\n\nPath: `docs/cli/bootstrap/plugins/status.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/cli/bootstrap/plugins/status.md)","tokens":300,"sizeBytes":177},{"name":"install.md","path":"docs/cli/plugins/install.md","rawUrl":"https://raw.githubusercontent.com/jdx/mise/HEAD/docs/cli/plugins/install.md","title":"Plugins Skill","category":"anthropic-skill","format":"markdown","content":"# Plugins Skill\n\nPath: `docs/cli/plugins/install.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/cli/plugins/install.md)","tokens":300,"sizeBytes":159},{"name":"link.md","path":"docs/cli/plugins/link.md","rawUrl":"https://raw.githubusercontent.com/jdx/mise/HEAD/docs/cli/plugins/link.md","title":"Plugins Skill","category":"anthropic-skill","format":"markdown","content":"# Plugins Skill\n\nPath: `docs/cli/plugins/link.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/cli/plugins/link.md)","tokens":300,"sizeBytes":153},{"name":"ls-remote.md","path":"docs/cli/plugins/ls-remote.md","rawUrl":"https://raw.githubusercontent.com/jdx/mise/HEAD/docs/cli/plugins/ls-remote.md","title":"Plugins Skill","category":"anthropic-skill","format":"markdown","content":"# Plugins Skill\n\nPath: `docs/cli/plugins/ls-remote.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/cli/plugins/ls-remote.md)","tokens":300,"sizeBytes":163},{"name":"ls.md","path":"docs/cli/plugins/ls.md","rawUrl":"https://raw.githubusercontent.com/jdx/mise/HEAD/docs/cli/plugins/ls.md","title":"Plugins Skill","category":"anthropic-skill","format":"markdown","content":"# Plugins Skill\n\nPath: `docs/cli/plugins/ls.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/cli/plugins/ls.md)","tokens":300,"sizeBytes":149},{"name":"uninstall.md","path":"docs/cli/plugins/uninstall.md","rawUrl":"https://raw.githubusercontent.com/jdx/mise/HEAD/docs/cli/plugins/uninstall.md","title":"Plugins Skill","category":"anthropic-skill","format":"markdown","content":"# Plugins Skill\n\nPath: `docs/cli/plugins/uninstall.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/cli/plugins/uninstall.md)","tokens":300,"sizeBytes":163},{"name":"update.md","path":"docs/cli/plugins/update.md","rawUrl":"https://raw.githubusercontent.com/jdx/mise/HEAD/docs/cli/plugins/update.md","title":"Plugins Skill","category":"anthropic-skill","format":"markdown","content":"# Plugins Skill\n\nPath: `docs/cli/plugins/update.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/cli/plugins/update.md)","tokens":300,"sizeBytes":157},{"name":"conventional_commits.mdc","path":".cursor/rules/conventional_commits.mdc","rawUrl":"https://raw.githubusercontent.com/jdx/mise/HEAD/.cursor/rules/conventional_commits.mdc","title":"Cursor Rule: conventional_commits","category":"cursor-rule","format":"mdc","content":"---\nalwaysApply: false\ndescription: how to write commit and PR titles\n---\n\n## Conventional Commits (REQUIRED)\n\nPR titles MUST follow conventional commit format. Intermediate commit subjects\nSHOULD use the same format:\n\n### Format\n```\n<type>[optional scope][optional !]: <description>\n```\n\n### Types\n- `feat:` - New features\n- `fix:` - Bug fixes that affect CLI behavior (not CI, docs, or infrastructure)\n- `refactor:` - Code refactoring\n- `docs:` - Documentation changes\n- `style:` - Code style/formatting (no logic changes)\n- `perf:` - Performance improvements\n- `test:` - Testing changes\n- `chore:` - Maintenance tasks, releases, dependency updates, CI/infrastructure\n- `ci:` - CI and automation changes\n- `revert:` - Revert a previous change\n- `security:` - Security-related changes\n- `registry:` - Any changes to `registry/` (no extra scope)\n\n### Examples\n```\nfeat(cli): add new command for tool management\nfix(config): resolve parsing issue with nested tables\nrefactor(backend): simplify plugin loading logic\ndocs(contributing): update installation instructions\ntest(e2e): add tests for tool installation\nchore(ci): improve cursor cloud agent environment\nregistry: add miller\n```\n\n### Common Scopes\nCommand names (`install`, `activate`, `use`, `exec`, …) or subsystems:\n`config`, `backend`, `env`, `task`, `vfox`, `python`, `github`, `release`,\n`completions`, `http`, `schema`, `doctor`, `shim`, `core`, `deps`, `ci`.\n\nUse `task` (not `run`) for task-related changes, even if the code lives in\n`src/cli/run.rs` or `src/cmd.rs`.\n\nDescription: start with a lowercase character, use imperative mood, and keep it concise.\n","frontmatter":{"alwaysApply":false,"description":"how to write commit and PR titles"},"isInternal":false,"tokens":409,"sizeBytes":1625},{"name":"development.mdc","path":".cursor/rules/development.mdc","rawUrl":"https://raw.githubusercontent.com/jdx/mise/HEAD/.cursor/rules/development.mdc","title":"Cursor Rule: development","category":"cursor-rule","format":"mdc","content":"---\nalwaysApply: true\n---\n\n- `cargo build --all-features` - build the project\n- `target/debug/mise` - run the built binary\n- `mise run test:e2e [test_filename]...` - run e2e tests\n- `mise run test:unit` - run unit tests\n- `mise run lint` - run linting\n- `mise run lint-fix` - run linting and fix issues\n\nDon't run e2e tests by trying to execute them directly, always use `mise run test:e2e [test_filename]...`\n\nRun `mise run lint-fix` and `git add` any lint fixes before trying to commit.\n","frontmatter":{"alwaysApply":true},"isInternal":false,"tokens":143,"sizeBytes":489},{"name":"testing.mdc","path":".cursor/rules/testing.mdc","rawUrl":"https://raw.githubusercontent.com/jdx/mise/HEAD/.cursor/rules/testing.mdc","title":"Cursor Rule: testing","category":"cursor-rule","format":"mdc","content":"---\ndescription: how to test the mise codebase\nalwaysApply: false\n---\n\nTesting and linting commands should be run via `mise run`.\n\n- `mise run test:e2e [test_filename]...` executes an e2e test\n- `mise run test:unit` executes the unit tests\n- `mise run lint` runs the linting commands\n- `mise run lint-fix` runs the linting commands and fixes the issues\n- `mise --cd crates/vfox run test` executes the tests for the vfox crate\n- `mise --cd crates/vfox run lint` runs the linting commands for the vfox crate\n- `mise --cd crates/vfox run lint-fix` runs the linting commands and fixes the issues for the vfox crate\n\nNever execute e2e scripts directly. Slow tests (`*_slow`) are skipped unless `TEST_ALL=1`.\n\nFor GitHub API rate limits during e2e, set `MISE_GITHUB_TOKEN` (or `GITHUB_TOKEN`). Cloud Agents can use `export MISE_GITHUB_TOKEN=\"$(gh auth token)\"` when those are unset.\n\nOther tasks can be found by running `mise task ls`\n","frontmatter":{"description":"how to test the mise codebase","alwaysApply":false},"isInternal":false,"tokens":244,"sizeBytes":929},{"name":"README.md","path":"crates/vfox/plugins/dummy/README.md","rawUrl":"https://raw.githubusercontent.com/jdx/mise/HEAD/crates/vfox/plugins/dummy/README.md","title":"dummy Documentation","category":"plugin-manifest","format":"markdown","content":"# dummy Documentation\n\nPath: `crates/vfox/plugins/dummy/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/crates/vfox/plugins/dummy/README.md)","tokens":300,"sizeBytes":181},{"name":"mise.plugin.json","path":"schema/mise.plugin.json","rawUrl":"https://raw.githubusercontent.com/jdx/mise/HEAD/schema/mise.plugin.json","title":"schema Plugin Manifest","category":"plugin-manifest","format":"json","content":"{\n  \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n  \"$id\": \"https://mise.jdx.dev/schema/mise.plugin.json\",\n  \"title\": \"mise-plugin\",\n  \"description\": \"config file for a mise plugin\",\n  \"type\": \"object\",\n  \"unevaluatedProperties\": false,\n  \"$defs\": {\n    \"plugin-script-config\": {\n      \"type\": \"object\",\n      \"unevaluatedProperties\": false,\n      \"properties\": {\n        \"cache-key\": {\n          \"description\": \"cache the script results separately based on these values; only consumed for list-bin-paths and exec-env, accepted elsewhere\",\n          \"type\": \"array\",\n          \"items\": {\n            \"type\": \"string\"\n          }\n        },\n        \"data\": {\n          \"description\": \"static data to use instead of executing the script; only consumed for list-aliases, list-idiomatic-filenames, and list-legacy-filenames, accepted elsewhere\",\n          \"type\": \"string\"\n        }\n      }\n    }\n  },\n  \"properties\": {\n    \"list-aliases\": {\n      \"description\": \"configuration for bin/list-aliases script\",\n      \"$ref\": \"#/$defs/plugin-script-config\"\n    },\n    \"list-legacy-filenames\": {\n      \"description\": \"configuration for bin/list-legacy-filenames script\",\n      \"$ref\": \"#/$defs/plugin-script-config\"\n    },\n    \"list-idiomatic-filenames\": {\n      \"description\": \"configuration for idiomatic filename discovery\",\n      \"$ref\": \"#/$defs/plugin-script-config\"\n    },\n    \"list-bin-paths\": {\n      \"description\": \"configuration for bin/list-bin-paths script\",\n      \"$ref\": \"#/$defs/plugin-script-config\"\n    },\n    \"exec-env\": {\n      \"description\": \"configuration for bin/exec-env script\",\n      \"$ref\": \"#/$defs/plugin-script-config\"\n    },\n    \"idiomatic-filenames\": {\n      \"description\": \"legacy key from old plugins that is ignored; when present, mise stops parsing the file entirely\",\n      \"deprecated\": true\n    },\n    \"legacy-filenames\": {\n      \"description\": \"legacy key from old plugins that is ignored; when present, mise stops parsing the file entirely\",\n      \"deprecated\": true\n    },\n    \"package-manager\": {\n      \"description\": \"configuration for a package-manager plugin\",\n      \"type\": \"object\",\n      \"unevaluatedProperties\": false,\n      \"properties\": {\n        \"requires\": {\n          \"description\": \"host binaries required by the package-manager plugin\",\n          \"type\": \"array\",\n          \"items\": {\n            \"type\": \"string\"\n          }\n        },\n        \"supports_version_pins\": {\n          \"description\": \"whether the package manager supports version-pinned requests\",\n          \"type\": \"boolean\"\n        },\n        \"supports-version-pins\": {\n          \"description\": \"whether the package manager supports version-pinned requests\",\n          \"type\": \"boolean\"\n        },\n        \"os\": {\n          \"description\": \"operating systems supported by the package-manager plugin\",\n          \"type\": \"array\",\n          \"items\": {\n            \"type\": \"string\"\n          }\n        }\n      }\n    }\n  }\n}\n","frontmatter":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"https://mise.jdx.dev/schema/mise.plugin.json","title":"mise-plugin","description":"config file for a mise plugin","type":"object","unevaluatedProperties":false,"$defs":{"plugin-script-config":{"type":"object","unevaluatedProperties":false,"properties":{"cache-key":{"description":"cache the script results separately based on these values; only consumed for list-bin-paths and exec-env, accepted elsewhere","type":"array","items":{"type":"string"}},"data":{"description":"static data to use instead of executing the script; only consumed for list-aliases, list-idiomatic-filenames, and list-legacy-filenames, accepted elsewhere","type":"string"}}}},"properties":{"list-aliases":{"description":"configuration for bin/list-aliases script","$ref":"#/$defs/plugin-script-config"},"list-legacy-filenames":{"description":"configuration for bin/list-legacy-filenames script","$ref":"#/$defs/plugin-script-config"},"list-idiomatic-filenames":{"description":"configuration for idiomatic filename discovery","$ref":"#/$defs/plugin-script-config"},"list-bin-paths":{"description":"configuration for bin/list-bin-paths script","$ref":"#/$defs/plugin-script-config"},"exec-env":{"description":"configuration for bin/exec-env script","$ref":"#/$defs/plugin-script-config"},"idiomatic-filenames":{"description":"legacy key from old plugins that is ignored; when present, mise stops parsing the file entirely","deprecated":true},"legacy-filenames":{"description":"legacy key from old plugins that is ignored; when present, mise stops parsing the file entirely","deprecated":true},"package-manager":{"description":"configuration for a package-manager plugin","type":"object","unevaluatedProperties":false,"properties":{"requires":{"description":"host binaries required by the package-manager plugin","type":"array","items":{"type":"string"}},"supports_version_pins":{"description":"whether the package manager supports version-pinned requests","type":"boolean"},"supports-version-pins":{"description":"whether the package manager supports version-pinned requests","type":"boolean"},"os":{"description":"operating systems supported by the package-manager plugin","type":"array","items":{"type":"string"}}}}}},"isInternal":false,"tokens":672,"sizeBytes":2945},{"name":"README.md","path":"test/plugins/vfox-npm/README.md","rawUrl":"https://raw.githubusercontent.com/jdx/mise/HEAD/test/plugins/vfox-npm/README.md","title":"vfox-npm Documentation","category":"plugin-manifest","format":"markdown","content":"# vfox-npm Documentation\n\nPath: `test/plugins/vfox-npm/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/test/plugins/vfox-npm/README.md)","tokens":300,"sizeBytes":176},{"name":"test-runner.md","path":".claude/agents/test-runner.md","rawUrl":"https://raw.githubusercontent.com/jdx/mise/HEAD/.claude/agents/test-runner.md","title":"test-runner","category":"subagent-persona","format":"markdown","content":"---\nname: test-runner\ndescription: Use proactively to run tests and analyze failures for the current task. Returns detailed failure analysis without making fixes.\ntools: Bash, Read, Grep, Glob\ncolor: yellow\n---\n\nYou are a specialized test execution agent. Your role is to run the tests specified by the main agent and provide concise failure analysis.\n\n## Core Responsibilities\n\n1. **Run Specified Tests**: Execute exactly what the main agent requests (specific tests, test files, or full suite)\n2. **Analyze Failures**: Provide actionable failure information\n3. **Return Control**: Never attempt fixes - only analyze and report\n\n## Workflow\n\n1. Run the test command provided by the main agent\n2. Parse and analyze test results\n3. For failures, provide:\n   - Test name and location\n   - Expected vs actual result\n   - Most likely fix location\n   - One-line suggestion for fix approach\n4. Return control to main agent\n\n## Output Format\n\n```\n✅ Passing: X tests\n❌ Failing: Y tests\n\nFailed Test 1: test_name (file:line)\nExpected: [brief description]\nActual: [brief description]\nFix location: path/to/file.rb:line\nSuggested approach: [one line]\n\n[Additional failures...]\n\nReturning control for fixes.\n```\n\n## Important Constraints\n\n- Run exactly what the main agent specifies\n- Keep analysis concise (avoid verbose stack traces)\n- Focus on actionable information\n- Never modify files\n- Return control promptly after analysis\n\n## Example Usage\n\nMain agent might request:\n\n- \"Run the password reset test file\"\n- \"Run only the failing tests from the previous run\"\n- \"Run the full test suite\"\n- \"Run tests matching pattern 'user_auth'\"\n\nYou execute the requested tests and provide focused analysis.\n","frontmatter":{"name":"test-runner","description":"Use proactively to run tests and analyze failures for the current task. Returns detailed failure analysis without making fixes.","tools":"Bash, Read, Grep, Glob","color":"yellow"},"isInternal":false,"tokens":372,"sizeBytes":1694},{"name":"config.toml","path":".codex/config.toml","rawUrl":"https://raw.githubusercontent.com/jdx/mise/HEAD/.codex/config.toml","title":"Codex Directive: config.toml","category":"codex-rule","format":"markdown","content":"\n[features]\nhooks = true\n\n[mcp_servers.hk]\ncommand = \"hk\"\nargs = [\"mcp\", \"--root\", \".\"]\n","isInternal":false,"tokens":30,"sizeBytes":88},{"name":"hooks.json","path":".codex/hooks.json","rawUrl":"https://raw.githubusercontent.com/jdx/mise/HEAD/.codex/hooks.json","title":"Codex Directive: hooks.json","category":"codex-rule","format":"markdown","content":"{\n  \"hooks\": {\n    \"PostToolUse\": [\n      {\n        \"matcher\": null,\n        \"hooks\": [\n          {\n            \"type\": \"command\",\n            \"command\": \"sh -c 'if ! command -v entire >/dev/null 2>&1; then exit 0; fi; exec entire hooks codex post-tool-use'\",\n            \"timeout\": 30\n          }\n        ]\n      }\n    ],\n    \"SessionEnd\": [\n      {\n        \"matcher\": null,\n        \"hooks\": [\n          {\n            \"type\": \"command\",\n            \"command\": \"sh -c 'if ! command -v entire >/dev/null 2>&1; then exit 0; fi; exec entire hooks codex session-end'\",\n            \"timeout\": 3\n          }\n        ]\n      }\n    ],\n    \"SessionStart\": [\n      {\n        \"matcher\": null,\n        \"hooks\": [\n          {\n            \"type\": \"command\",\n            \"command\": \"sh -c 'if ! command -v entire >/dev/null 2>&1; then printf \\\"%s\\\\n\\\" \\\"{\\\\\\\"systemMessage\\\\\\\":\\\\\\\"Entire CLI is enabled but not installed or not on PATH. Installation guide: https://docs.entire.io/cli/installation#installation-methods\\\\\\\"}\\\"; exit 0; fi; exec entire hooks codex session-start'\",\n            \"timeout\": 30\n          }\n        ]\n      }\n    ],\n    \"Stop\": [\n      {\n        \"matcher\": null,\n        \"hooks\": [\n          {\n            \"type\": \"command\",\n            \"command\": \"sh -c 'if ! command -v entire >/dev/null 2>&1; then exit 0; fi; exec entire hooks codex stop'\",\n            \"timeout\": 30\n          }\n        ]\n      }\n    ],\n    \"SubagentStart\": [\n      {\n        \"matcher\": null,\n        \"hooks\": [\n          {\n            \"type\": \"command\",\n            \"command\": \"sh -c 'if ! command -v entire >/dev/null 2>&1; then exit 0; fi; exec entire hooks codex subagent-start'\",\n            \"timeout\": 30\n          }\n        ]\n      }\n    ],\n    \"SubagentStop\": [\n      {\n        \"matcher\": null,\n        \"hooks\": [\n          {\n            \"type\": \"command\",\n            \"command\": \"sh -c 'if ! command -v entire >/dev/null 2>&1; then exit 0; fi; exec entire hooks codex subagent-stop'\",\n            \"timeout\": 30\n          }\n        ]\n      }\n    ],\n    \"UserPromptSubmit\": [\n      {\n        \"matcher\": null,\n        \"hooks\": [\n          {\n            \"type\": \"command\",\n            \"command\": \"sh -c 'if ! command -v entire >/dev/null 2>&1; then exit 0; fi; exec entire hooks codex user-prompt-submit'\",\n            \"timeout\": 30\n          }\n        ]\n      }\n    ]\n  }\n}\n","frontmatter":{"hooks":{"PostToolUse":[{"matcher":null,"hooks":[{"type":"command","command":"sh -c 'if ! command -v entire >/dev/null 2>&1; then exit 0; fi; exec entire hooks codex post-tool-use'","timeout":30}]}],"SessionEnd":[{"matcher":null,"hooks":[{"type":"command","command":"sh -c 'if ! command -v entire >/dev/null 2>&1; then exit 0; fi; exec entire hooks codex session-end'","timeout":3}]}],"SessionStart":[{"matcher":null,"hooks":[{"type":"command","command":"sh -c 'if ! command -v entire >/dev/null 2>&1; then printf \"%s\\n\" \"{\\\"systemMessage\\\":\\\"Entire CLI is enabled but not installed or not on PATH. Installation guide: https://docs.entire.io/cli/installation#installation-methods\\\"}\"; exit 0; fi; exec entire hooks codex session-start'","timeout":30}]}],"Stop":[{"matcher":null,"hooks":[{"type":"command","command":"sh -c 'if ! command -v entire >/dev/null 2>&1; then exit 0; fi; exec entire hooks codex stop'","timeout":30}]}],"SubagentStart":[{"matcher":null,"hooks":[{"type":"command","command":"sh -c 'if ! command -v entire >/dev/null 2>&1; then exit 0; fi; exec entire hooks codex subagent-start'","timeout":30}]}],"SubagentStop":[{"matcher":null,"hooks":[{"type":"command","command":"sh -c 'if ! command -v entire >/dev/null 2>&1; then exit 0; fi; exec entire hooks codex subagent-stop'","timeout":30}]}],"UserPromptSubmit":[{"matcher":null,"hooks":[{"type":"command","command":"sh -c 'if ! command -v entire >/dev/null 2>&1; then exit 0; fi; exec entire hooks codex user-prompt-submit'","timeout":30}]}]}},"isInternal":false,"tokens":631,"sizeBytes":2362}],"systemPromptSnippet":"<yakaai_skills repo=\"jdx/mise\">\n<!-- File: AGENTS.md (Tokens: ~8116 | Category: root-instruction) -->\n# Repository Agent Guide\n\nThis file is the canonical agent guide. `CLAUDE.md` is a symlink to `AGENTS.md` for compatibility with existing tooling.\n\nTask-specific procedures live as skills in `.agents/skills/` (`.claude/skills` is a symlink to it). Load the named skill when this guide points to one; agents without skill support can read its `SKILL.md` directly.\n\n## Discussions and Issues: Restricted AI Replies\n\n**Do not use AI to reply to a mise Discussion or Issue unless the user (a) created that Discussion or Issue, (b) opened a PR that fixes it, or (c) has already had a contribution merged into the default branch of mise.** Otherwise they are not allowed to use AI to respond to it. Drive-by AI replies are spam, the problem is getting worse, and **doing it is an instant ban across all of jdx's projects** (mise, hk, pitchfork, usage, fnox, and the rest).\n\n- If the user asks you to answer, comment on, or \"help with\" a Discussion or Issue, confirm one of the three conditions first. If you cannot confirm one, **do not post**.\n  - (a) Compare the thread author to the authenticated user (`gh api user --jq .login`). For an Issue, use `gh api repos/jdx/mise/issues/<number> --jq .user.login`. Discussions have no REST endpoint, so use GraphQL: `gh api graphql -f query='query{repository(owner:\"jdx\",name:\"mise\"){discussion(number:<number>){author{login}}}}' --jq .data.repository.discussion.author.login`.\n  - (b) Check that the user's PR actually fixes the problem described in the thread. A closing keyword such as `Fixes #<number>` is good evidence, but a link is not required, and a PR that merely mentions an unrelated thread does not count.\n  - (c) Look for any contribution merged into the default branch that is tied to the user's GitHub account, not just a matching name or email: a PR authored by the user that was merged into the default branch (`gh pr list --repo jdx/mise --author @me --state merged --base main --limit 1`), commits on the default branch that GitHub attributes to their login (`gh api 'repos/jdx/mise/commits?author=<login>&per_page=1'` lists the default branch), never commits on a local or unmerged branch, or a PR from someone else, merged into the default branch, that credits them with a `Co-authored-by` trailer whose email is their GitHub noreply address or one verified on their account. Do not accept `git log --author` output, which includes local unmerged commits, or a trailer matched only by display name. Both queries filter by author on the server, so one matching result is enough to qualify and no pagination is needed.\n- If none of the three apply, **do not post a reply, even a short one.** Tell them this project does not allow AI replies from people who have not contributed, and offer to explain the answer to them in chat instead.\n- Never batch-post, loop over, or sweep Discussions or Issues to answer several of them, even for a merged contributor.\n- Lightly edited, human-reviewed, or disclosed model output does not create an exception. The disclosure footer does not make an AI reply acceptable on its own.\n- Permitted replies may be AI-assisted. The user must review and verify the reply before it is posted.\n- Creating a new Discussion or Issue with AI assistance is fine and is not restricted. The user must review it before it is posted, and it needs the AI disclosure below.\n\nWhen you post AI-contributed GitHub content, including a new Discussion or Issue, a reply, or a PR description or comment, append this disclosure: `*AI-assisted — Tool: <tool>; model: <provider>/<model>; version: <version-or-unavailable>.*` Use the exact model and version identifiers exposed by the runtime, never guessed values, and `unavailable` when one is not exposed.\n\n## Registry Submissions: READ THIS FIRST\n\n**Most new registry additions from agents get rejected.** mise's `registry/` is curated for tools that are already widely used — generally thousands of GitHub stars, not hundreds. jdx closes PRs that miss the bar without giving a reason.\n\nBefore adding a **new** tool or shorthand to `registry/`, follow the `registry-submission` skill ([`.agents/skills/registry-submission/SKILL.md`](.agents/skills/registry-submission/SKILL.md)). In short:\n\n- Warn the user about the bar, look up real popularity numbers, and stop if the tool is personal, internal, a fork, or niche.\n- Put a `## Popularity` section with those numbers in the PR description.\n- Confirm `mise ls-remote <backend>` lists installable versions.\n- Prefer `packslip:`, then `aqua:`, `github:`, or `gitlab:`. `conda:` has a high bar; `npm:`, `pipx:`, `gem:`, `cargo:`, `go:`, and `dotnet:` are almost never accepted. New `asdf:`, `vfox:`, and `ubi:` entries are not accepted.\n- Users can install any tool without a registry entry (`mise use github:owner/repo`, `mise use cargo:name`, …); the registry only adds a shorthand.\n\nNone of this applies to editing an existing registry entry; do not ask the user about popularity for maintenance or fixes.\n\n## Development Commands\n\n### Building and Testing\n- `mise run build` or `mise run b` - Build the project with cargo\n- `target/debug/mise` - Run the built binary directly\n- `mise run test` or `mise run t` - Run all tests (unit + e2e)\n- `mise run test:unit` - Run unit tests only\n- `mise run test:e2e` - Run end-to-end tests only\n- `mise run snapshots` - Update test snapshots with `cargo insta`\n\n### Debugging\n- Use `MISE_DEBUG=1` or `MISE_TRACE=1` environment variables to enable debug output (not `RUST_LOG`)\n\n### Code Quality and Testing\n- `mise run lint` - Run all linting tasks (hk; does not run clippy — see below)\n- `mise run lint-fix` - Run linting and automatically fix issues\n- `mise run format` - Format code (part of CI task)\n- `mise run ci` - Run format, build, and test\n- `mise run test:e2e [test_filename]...` - Run specific e2e tests (use this instead of executing test files directly)\n- `mise --cd crates/vfox run test` - Run tests for the vfox crate\n- `mise --cd crates/vfox run lint` - Run linting for the vfox crate\n- `mise --cd crates/vfox run lint-fix` - Run linting and fix issues for the vfox crate\n- `mise task ls` - List all available tasks\n\n### Clippy Exclusions\n\n- Do not add `#[allow(clippy::...)]`, `#[expect(clippy::...)]`, Cargo lint levels set to `allow`, or `-A clippy::...` command-line flags.\n- Refactor the code so `cargo clippy --workspace --all-features --all-targets -- -D warnings` passes without exclusions.\n- `mise run lint` does not cover this: the clippy step in `hk.pkl` is disabled, and `cargo check` does not enforce `-D warnings`. CI runs clippy separately, so run the command above yourself before pushing Rust changes.\n- If a feature or fix needs a preparatory refactor to satisfy Clippy cleanly, put that refactor in a prerequisite PR and stack the behavior change on top of it.\n\n### Documentation and Generation\n- `mise run render` - Generate all documentation and completions\n- `mise run render:usage` - Generate CLI usage documentation\n- `mise run render:completions` - Generate shell completions\n- `mise run docs` - Start documentation dev server\n- `mise run docs:build` - Build documentation\n\n### Development\n- `mise run install-dev` - Install development version locally\n- `mise run clean` - Clean cargo build artifacts\n\n## Code Architecture\n\n### High-Level Structure\nMise is a Rust CLI tool that manages development environments, tools, tasks, and environment variables. The codebase follows a modular architecture:\n\nThe `mise` package has two targets. The library (`src/lib.rs`) is everything except the command line; the binary (`src/main.rs` plus `src/cli/`) sits on top of it and glob-imports its root, so `cli` code still writes `crate::config::…`. An edit under `src/cli/` recompiles only the binary. Core code must not refer to `crate::cli`: it reaches command behavior through the hooks in `src/frontend.rs`. When `cli` needs a core item, make that item `pub`; `unreachable_pub` keeps everything else `pub(crate)`. `cfg(test)` does not reach the library from the binary's tests, so core code that behaves differently under tests checks `mise_util::testing::in_tests()` instead.\n\n**Core Components:**\n- `src/main.rs` - Binary entry point\n- `src/lib.rs` - Library root: module list and the hooks lower crates need\n- `src/cli/` - Command-line interface implementation with subcommands (binary only)\n- `src/config/` - Configuration file parsing and management\n- `src/backend/` - Tool backend implementations (aqua, github, cargo, npm, asdf, vfox, …)\n- `src/toolset/` - Tool version management and installation logic\n- `src/task/` - Task execution system\n- `src/plugins/` - Plugin system for extending tool support\n\n**Key Backend Systems** (`src/backend/`):\n- `packslip.rs` — Signed release manifests (preferred for new registry entries)\n- `aqua.rs` — Aqua registry\n- `github.rs` — GitHub / GitLab / Forgejo releases\n- `http.rs`, `s3.rs` — HTTP and S3 backends\n- `cargo.rs`, `npm.rs` (plus embedded aube), `pipx.rs`, `gem.rs`, `go.rs`, `dotnet.rs`, `conda.rs`, `spm.rs`\n- `asdf.rs`, `vfox.rs` — plugin compatibility layers\n- `ubi.rs` — deprecated; do not add new registry entries\n\n**Core Tools (Built-in):**\n- `src/plugins/core/` — Node, Python, Go, Ruby, Java, Bun, Deno, Elixir, Erlang, Dotnet, Swift, Zig, Rust\n\n**Configuration System:**\n- `mise.toml` files for project configuration\n- `.tool-versions` files for ASDF compatibility\n- Environment variable management and templating\n- Task definition and execution\n\n### Key Design Patterns\n1. **Backend Architecture**: Tools are implemented through a unified backend interface, allowing multiple sources (ASDF plugins, vfox plugins, cargo, npm, etc.)\n2. **Toolset Management**: The `Toolset` manages collections of tool versions and their installation state\n3. **Configuration Layering**: Config files are loaded hierarchically from system → global → local with environment-specific overrides\n4. **Task System**: Tasks can be defined in TOML files with dependencies, environment variables, and multiple execution modes\n\n### Configuration Files\n- `mise.toml` - Main configuration file format\n- `settings.toml` - Global settings definitions (generates code/docs)\n- `registry/` - Tool registry mappings\n- `tasks.toml` - Project task definitions\n\n### Test Structure\n- Unit tests within source files\n- E2E tests in `e2e/` directory organized by feature area (e.g., `e2e/cli/`, `e2e/backend/`)\n- E2E tests are bash scripts using assertion helpers from `e2e/assert.sh` (e.g., `assert`, `assert_contains`, `assert_fail`)\n- E2E tests do not need cleanup steps (rm, etc.) — the test harness handles that\n- Snapshot tests using `insta` crate for CLI output verification\n- Windows-specific tests in `e2e-win/`\n\n### Build System\n- Rust project using a Cargo workspace; member crates live in `crates/` (`vfox`, `aqua-registry`, `mise-shim`, `mise-sigstore`, `mise-cache-core`, `mise-tls`, `mise-brew-relocation`, `mise-brew-metadata`, `mise-agent-env`, `mise-interactive-config`, `mise-settings`, `mise-util`, `mise-ui`, `mise-system-packages`, `mise-config`, `mise-system`, `mise-oci`, `mise-daemons`, `mise-lsp`)\n- Custom build script in `build.rs` for generating metadata\n- Multiple build profiles including `release` and `serious` (with LTO)\n- Cross-compilation support via `Cross.toml`\n\n## Development Guidelines\n\n### Conventional Commits (REQUIRED)\nPR titles MUST follow conventional commit format. Intermediate commit subjects\nSHOULD use the same format:\n\n**Format:** `<type>[optional scope][optional !]: <description>`\n\n**Types:**\n- `feat:` - New features\n- `fix:` - Bug fixes that affect the CLI behavior (not CI, docs, or infrastructure)\n- `refactor:` - Code refactoring\n- `docs:` - Documentation changes\n- `style:` - Code style/formatting (no logic changes)\n- `perf:` - Performance improvements\n- `test:` - Testing changes\n- `chore:` - Maintenance tasks, releases, dependency updates, CI/infrastructure changes\n- `security:` - Security-related changes\n- `registry:` - Any changes to `registry/` (do not add a scope)\n- `ci:` - CI and automation changes\n- `revert:` - Reverting a previous change\n\n**Scopes:**\n- For command-specific changes, use the command name: `install`, `activate`, `use`, `exec`, etc.\n- For subsystem changes: `config`, `backend`, `env`, `task`, `vfox`, `python`, `github`, `release`, `completions`, `http`, `schema`, `doctor`, `shim`, `core`, `deps`, `ci`\n- Use `task` (not `run`) for task-related changes, even if the code lives in `src/cli/run.rs` or `src/cmd.rs`\n\n**Description Style:**\n- Start the description with a lowercase character, or with an acronym such as `PGO` or `CLI`\n- Use imperative mood (\"add feature\" not \"added feature\")\n- Keep it concise but descriptive\n\n**Examples:**\n- `fix(install): resolve version mismatch for previously installed tools`\n- `feat(activate): add fish shell support`\n- `feat(vfox): add semver Lua module for version sorting`\n- `feat(env): add environment caching with module cacheability support`\n- `docs(contributing): update hk usages`\n- `chore: release 2026.1.6`\n- `chore(ci): add FORGEJO_TOKEN for API authentication`\n- `registry: add miller`\n\nCI validates the pull request title and re-runs when it is edited. Intermediate\ncommit subjects are not checked because pull requests are squash-merged. CI\nmechanically checks the allowed type, syntax, and lowercase- or acronym-leading description;\nimperative mood and breaking-change details remain review rules.\n\n### PR titles and descriptions are release-note inputs\n\nCommunique generates release notes from PR titles and descriptions, so write them for a mise user who has not read the diff: lead with the user-visible problem and outcome, show a concrete example, and keep them in sync with the final diff. Follow the `pr-description` skill ([`.agents/skills/pr-description/SKILL.md`](.agents/skills/pr-description/SKILL.md)) when opening or revising a PR.\n\n### Pre-commit Process\n1. Run `mise run lint-fix` and `git add` any lint fixes before committing\n2. Use `mise run test:e2e [test_filename]...` for running specific e2e tests\n3. Never run e2e tests by executing them directly — always use the mise task\n\n`hk.pkl` defines `check` and `fix` steps and a git `pre-commit` hook that runs the same linters with auto-fix (`stash = \"git\"` preserves unstaged work). `hk install --mise` installs that hook. You can still run `mise run lint` / `mise run lint-fix` by hand; on Linux and macOS they run hk, but on Windows `lint-fix` runs only Clippy, oxfmt, and `cargo fmt`, so the other hk steps do not run there.\n\n### hk Agent Workflow\n\n- Prefer the hk MCP server for effect-aware plans, checks, fixes, logs, and captured diffs.\n- When invoking hk directly, use `hk run check --safe --format json` for a complete machine-readable result or `--format jsonl` for streaming lifecycle events.\n- Scope checks to changed files. For an exact file list, pass NUL-delimited paths with `--files0-from`; use `--cd` to target another project directory.\n- Never run a command classified as unknown or destructive without explicit user approval. Review the resulting diff after fixes.\n\n### Dependency Updates\n\n- Use the lowest-specificity dependency requirement that expresses compatibility in `Cargo.toml` (for example, prefer `\"1\"` over `\"1.2.3\"`, and `\"0.12\"` over `\"0.12.1\"` for a pre-1.0 crate).\n- Routine dependency updates should only change `Cargo.lock`. If the existing `Cargo.toml` requirement accepts the target version, do not change it merely to force or record the update; use `cargo update -p <crate> --precise <version>` instead.\n- Keep lockfile updates focused on the requested dependency and its required transitive changes. Remove unrelated resolver churn before committing.\n\nWhen updating the embedded `aube` crates, follow the `update-aube` skill ([`.agents/skills/update-aube/SKILL.md`](.agents/skills/update-aube/SKILL.md)).\n\n## Deprecation Policy\n\nWhen deprecating a feature, backend, or implicit behavior:\n\n1. **Immediately**: Mark it as deprecated in docs (add a warning banner) and display a CLI warning using the `deprecated_at!` macro from `src/output.rs` (`warn_at` is the current version).\n2. **12 months after warn** (`remove_at`): `debug_assert!` in `deprecated_at!` fires, signaling the deprecated code or behavior should be removed.\n\n12 months is the default window, not a hard rule. Some deprecations use a shorter window, such as 6 months, on purpose. Use 12 months for new deprecations unless jdx asks for something else, and do not lengthen an existing shorter window.\n\nDelay the CLI warning for up to 6 months only when migration requires a new setting, syntax, or replacement that older supported mise versions would reject or fail to parse. This compatibility window lets users adopt a configuration that works across old and new clients before warnings begin. Do not delay warnings for a behavior change that requires no new configuration, or when the replacement already works in older clients.\n\nUse mise version format for dates (e.g., `deprecated_at!(\"2026.10.0\", \"2027.10.0\", \"id\", \"message\")`).\n\nIf a compatibility window is required, removal remains 12 months after `warn_at`, not 12 months after the initial documentation notice.\n\nFor temporary code with no user-facing deprecation, such as a migration or a fallback that reads what an older mise wrote, use `remove_by!(\"2027.1.0\", \"id\")` from `src/output.rs`. It is a compile-time assertion, so the build fails once the version reaches `remove_at`; remove every `remove_by!` with that id and the code it guards.\n\n## Important Implementation Notes\n\n### Backend System\nWhen implementing new tool backends, follow the pattern in `src/backend/mod.rs`. Each backend must implement the `Backend` trait with methods for listing versions, installing tools, and managing tool metadata.\n\n### DO NOT ASSUME SEMVER\n**Do not assume tool versions follow semver or any other orderable scheme.** mise manages hundreds of tools with wildly different versioning conventions:\n\n- Date-based: `2024.01.15`, `20241015`\n- Pre-release / ref / tag versions: `tip`, `HEAD`, `nightly`, `edge`, `canary`, `ref:main`, `tag:v1`, `sub-X.Y:...`\n- Non-numeric tags: Python `3.12.0a1`, Ruby `3.2.0-preview1`, Go `1.22rc1`, Node `lts/hydrogen`, `lts-iron`\n- Tool-specific meanings of `latest` (e.g. some exclude pre-releases, some don't)\n\n**Rules:**\n1. Do not call `versions::Versioning::new(...)` (or any other semver comparator) at a new call site to pick the \"newest\" version, \"resolve latest\", or sort a version list. That crate silently returns `None` / arbitrary ordering for non-semver strings, which means wrong versions get chosen for many tools.\n2. To resolve a version request (`latest`, a prefix, a channel name), delegate to the backend via `Backend::latest_version`, `Backend::latest_installed_version`, `Backend::list_versions_matching`, or `ToolRequest::resolve` — the backend knows what \"latest\" means for its tool.\n3. To list installed versions in a meaningful order, use `Backend::list_installed_versions_matching` or the toolset's resolved versions. Do not reorder them yourself.\n4. Lockfile version strings must be treated as opaque — compare with `==`, never with a version ordering. Never write a non-concrete string (`latest`, `lts/*`, a prefix) into the lockfile; resolve first.\n\nA few existing call sites (e.g. runtime symlinks) do use `Versioning` ordering today, but that's legacy behavior and arguably also wrong — do not point at them to justify new semver assumptions.\n\nIf you think you need to pick \"the newest installed version\" at a new call site, stop and ask — that call almost always belongs on the backend, not inline.\n\n### Paranoid mode categories\n`paranoid` is a bool or a list of categories (`config`, `env_files`, `plugins`, `provenance`), defined by `Paranoid` in `crates/mise-settings/src/paranoid.rs`. Any new behavior gated on paranoid mode must belong to one of those categories, or introduce a new named category, so it is individually selectable. New code must never read paranoid as a plain bool: call `settings.paranoid.config()`, `.env_files()`, `.plugins()` or `.provenance()`, and add an e2e test that the category works alone.\n\n### Plugin Development\n- Core tools are implemented in `src/plugins/core/`\n- External plugins use ASDF or vfox compatibility layers\n- Plugin metadata is defined in `mise.plugin.toml` files\n\n### Configuration Parsing\nThe configuration system supports multiple file formats and environment-specific configs. Changes to settings require updating `settings.toml` and running `mise run render:schema`. The `Settings` types are generated from `settings.toml` in `crates/mise-settings`; loading them (config discovery, trust, CLI flags) stays in `src/config/settings.rs`, whose `SettingsExt` trait holds the methods that need the rest of mise.\n\n`schema/mise.json`, `schema/mise-task.json` and `schema/miserc.json` are generated from `crates/mise-config` and `settings.toml`: never edit the JSON. Change the Rust, then run `mise run render:schema`; a `mise-config` test fails while the committed files are stale. The top-level keys are the fields of `MiseTomlDecl` in `crates/mise-config/src/mise_toml.rs`, which `MiseToml` deserializes through: a new key goes in `MiseTomlDecl`, and `MiseToml::from_decl` moves it into `MiseToml`. Sections whose types derive `JsonSchema` (so far `[bootstrap]`, `[daemons_settings]`, `[daemon_groups]`, `[doctor]`, `[history]`, `[monorepo]`, `[oci]`, `[task_config]`, `[tasks]`, `[task_templates]`, `[tool_config]` and `[wrappers]`) are generated from those types and their doc comments. `[env]` and `[vars]` accept shapes a derive cannot parse, so `env.rs` reads them with visitors; their schema is derived from the `Env*` and `Vars*` declaration types in `crates/mise-config/src/env/decl.rs`, which describe the tables and nothing parses into them, and a test checks that the option keys they declare are the fields of `EnvDirectiveOptions`. `[[watch_files]]`, `[tool_alias]` and `min_version` have a hand-written `JsonSchema` impl in `watch_files.rs`, `alias.rs` and `min_version.rs`. Task fields with several accepted shapes (a string or a list, a name or a table, ...) take theirs from the declaration types in `crates/mise-config/src/task/shapes.rs`, which `TaskDecl` and `TaskConfig` attach with `schemars(with = ..)` so the runtime field types stay as they are; nothing parses into those types, so change them together with the parser. `task/schema.rs` composes the rest: the `task` definition, a task's `tools` (which follow the backend table of `[tools]`) and the template schema. `[tools]` picks per-backend options by key pattern: a backend's options are the declaration types in `crates/mise-config/src/tools/decl.rs` (a new option is a field with a doc comment, which is its description), and `crates/mise-config/src/tools/schema.rs` composes them, with one table row per backend and per platform table. mise reads these definitions by name to reject unknown options (`OptionSpec`), so change them together with `ToolVersionOptions::insert_option` and the backend's option reader. `[hooks]` is derived from the `Hook*` declaration types in `crates/mise-config/src/hooks/decl.rs`, which describe the shapes each event accepts, with a test that they name the keys the parser reads. The `[bootstrap]` values that stay raw TOML so newer shapes warn instead of failing (hooks, shell activation, macOS defaults, apt and dnf repositories) are derived from the declaration types in `crates/mise-config/src/bootstrap/decl.rs`; nothing parses into those, and tests in mise-system check the hook phases and the curated macOS keys against the code that reads them. `[daemons]` and `[daemon_providers]` stay raw tables that mise-daemons reads key by key, with their schema derived from the `Daemon*Decl` types in `crates/mise-config/src/daemons.rs`; those types describe a table, and nothing parses into them, so a key added in mise-daemons has to be added to them too. `[deps]` is derived from `DepsDecl` and `DepsProviderDecl`, which also hold the list of built-in providers mise shares; `[secrets]` stays raw TOML like the dotfiles, with its schema derived from `SecretsDecl` and a test in mise that its parser reads the same keys. `[dotfiles]` and `[dotfile_groups]` entries also stay raw TOML until mise-system expands them, but their schema is derived from the declaration types in `crates/mise-config/src/dotfiles.rs`, with the rules between keys written by hand in `dotfiles/schema.rs`; mise-system's `*_keys_match_the_declaration` tests fail until its parsers read the same keys. `[settings]` and `miserc.json` come from `settings.toml` through `crates/mise-config/src/schema/settings.rs`.\n\nThe `schema_matches_parser` unit test (`src/config/config_file/mise_toml/schema_conformance.rs`) validates every `toml` block in `docs/` and every mise config an e2e heredoc writes against both the schema and `MiseToml`'s parser, and fails when they disagree. Fix the schema rather than the corpus. Mark a config that mise refuses on purpose with `# schema: invalid` (e2e) or `<!-- schema: invalid -->` (docs) on the line above it, and an excerpt that is not a whole config with `schema: skip`. List deliberate differences in its `GAPS` with a reason.\n\n### Testing Strategy\n- E2E tests are organized by feature area (cli/, config/, backend/, etc.)\n- Use snapshot testing for CLI output verification\n- Backend-specific tests verify tool installation and version management\n- Slow tests (marked with `_slow` suffix) test actual tool compilation/installation\n\n### Cross-Platform Considerations\n- Windows modules follow one of two conventions:\n  - `*_windows.rs` is a platform-swapped sibling of a same-named module, selected with `#[cfg_attr(windows, path = \"..._windows.rs\")]` (e.g. `src/fake_asdf.rs` / `src/fake_asdf_windows.rs`)\n  - `windows_*.rs` is a single module about Windows with no non-Windows counterpart to swap in. Declare it on every platform and cfg-split it internally when other code calls it on all targets or its tests should run on Linux (e.g. `src/windows_posix.rs`, `src/windows_console.rs`); declare it under `#[cfg(windows)]` when only Windows code uses it (e.g. `src/windows_job.rs`)\n- Platform-specific tool installation logic in core plugins\n- Shim system varies by platform (especially Windows)\n- we don't chmod mise e2e tests to be executable\n\n### Windows PATH boundaries\n\n- Do not invoke subprocesses to translate paths in activation hooks, shims, or `mise x`/task execution.\n- Keep PATH in native Windows form inside mise and when launching child processes, including child MSYS2, Git Bash, or Cygwin processes. Never pre-convert the PATH inherited by a child emulator.\n- Convert PATH only when native Windows mise emits an assignment into an already-running, positively identified MSYS2/Cygwin shell. Only persisted mounts from the runtime defaults, `fstab`, and `fstab.d` are available; session-only `mount` changes cannot be reconstructed without entering the running process.\n- Never infer an emulator from the word `bash` alone. Require MSYS/Cygwin runtime evidence, and explicitly exclude WSL and BusyBox Bash.\n- Windows activation tests must execute a command through the emitted PATH and verify a native Windows grandchild receives a valid semicolon-delimited PATH. Output-shape assertions alone are insufficient.\n\n## GitHub Interactions\n\nNever open pull requests against the `release` branch. Default PRs to `main` unless the user explicitly names a different non-`release` base branch. If a change appears to belong on `release`, stop and ask for the intended branch strategy instead of opening a PR against `release`.\n\nSee [Discussions and Issues: Restricted AI Replies](#discussions-and-issues-restricted-ai-replies) at the top of this file.\n\nWhen AI contributes GitHub content—including a pull request description, review, pull request\ncomment, discussion post, or issue—append this disclosure:\n\n`*AI-assisted — Tool: <tool>; model: <provider>/<model>; version: <version-or-unavailable>.*`\n\nUse the exact model and version identifiers exposed by the runtime. Never infer or guess them; use\n`unavailable` when either value is not exposed.\n\n## Documentation\n\n### URL Structure\nWhen referencing mise documentation URLs, use the correct path structure based on the `docs/` directory layout:\n\n- **Dev tools & backends**: `mise.jdx.dev/dev-tools/backends/<backend>.html` (e.g., `mise.jdx.dev/dev-tools/backends/s3.html`)\n- **Configuration**: `mise.jdx.dev/configuration/...`\n- **Tasks**: `mise.jdx.dev/tasks/...`\n- **Environments**: `mise.jdx.dev/environments/...`\n- **CLI reference**: `mise.jdx.dev/cli/...`\n\nDo NOT use shortened paths like `mise.jdx.dev/backends/...` - always include the full path matching the `docs/` directory structure.\n\n## Cloud agent instructions (Cursor Cloud and Claude Code on the web)\n\nCursor Cloud Agents bootstrap from `.cursor/environment.json`, which runs `.cursor/install.sh`. Claude Code on the web runs the same script from the SessionStart hook in `.claude/settings.json` (`.claude/hooks/session-start.sh`), which runs on session `startup`/`resume`/`fork` (not `/clear` or compaction) with a 30-minute timeout, exits immediately unless `CLAUDE_CODE_REMOTE=true`, sends the bootstrap output to stderr, and adds the mise shims and `/usr/local/bin` to `PATH` through `CLAUDE_ENV_FILE`. The hook runs synchronously, so the session starts after the build finishes. Claude cloud containers do not provide a GitHub token by default; add `GITHUB_TOKEN` as an environment secret to avoid GitHub API rate limits during `mise install` and e2e tests. Use a fine-grained token with public-repository read-only access and no other permissions: any branch a session checks out (its hook, build scripts, tests, and tasks) can read the session environment. Draft environment builds often run as `ubuntu` rather than `root`; the script handles both (passwordless sudo, cargo/rustup permissions, world-writable `/tmp/fslock`).\n\nThe install script:\n\n- cds to the repository root derived from the script path before reading `Cargo.toml` or building\n- installs host packages needed to build mise and to run most e2e tests (openssl, pkg-config, zsh, fish, python3 + venv, jq, git, build-essential, and compile-time libs). It does **not** install a JDK or GUI libraries; those live in `packaging/e2e/Dockerfile`. `apt-get` is invoked as `sudo -n env DEBIAN_FRONTEND=noninteractive apt-get …` so the frontend reaches apt when elevation is required\n- installs and defaults to the latest stable Rust toolchain (not the `Cargo.toml` `rust-version` MSRV), including `rustfmt` and `clippy`, and updates it on reruns\n- gets a bootstrap `mise` and symlinks it to `/usr/local/bin/mise`: an existing `target/debug/mise` refreshes itself with `mise run build`; if it cannot run this checkout's config, a plain `cargo build` goes to `target/bootstrap` (the `mbx` wrapper leaves read-only outputs in `target/`); with no `target/` yet, a plain `cargo build` goes to `target/`\n- keeps `GITHUB_TOKEN`, `MISE_GITHUB_TOKEN`, and `GH_TOKEN` in sync via one `sync_github_tokens` helper (prefer any already-set token; fall back to `gh auth token` only when all three are empty)\n- runs `MISE_SAFE=1 /usr/local/bin/mise install` with the just-built binary so checkout-controlled hooks/templates/`[env]` and tool-level `postinstall` / `install_env` cannot run with those tokens, then `mise trust` for later agent commands\n- runs `mise run build` so `target/` is warm for the `mbx`-wrapped cargo (`[wrappers.cargo]` in `mise.toml`) that agents build with, then points `/usr/local/bin/mise` at `target/debug/mise`. Every build runs with `GITHUB_TOKEN`, `MISE_GITHUB_TOKEN`, `GH_TOKEN`, and `GITHUB_API_TOKEN` unset\n- runs `hk install --mise` (installs the git `pre-commit` hook defined in `hk.pkl`)\n- persists mise shims and token sync in one `/etc/profile.d/mise-dev-env.sh` (shims first, then `sync_github_tokens`) and rewrites the Cloud Agent block in `/etc/bash.bashrc` so non-login interactive bash picks it up after a snapshot. Fish/zsh only get this from login shells (`profile.d`), not from bashrc\n- exposes the mise-installed `node` / `npm` / `npx` / `hk` / `gh` binaries on `/usr/local/bin` (isolated e2e PATH includes that directory, not the agent's shims). Links freeze the version from install time — re-run `.cursor/install.sh` after upgrading those tools\n\nThere is no long-running service to start. Do not put `mise run build` or `mise run test:unit` in `terminals`; those are one-shot commands and would rerun a full build/test on every boot.\n\nThe debug `mise` binary is already on PATH. Prefer `mise run …` for project tasks.\n\n### E2E on Cloud Agents\n\n- Always `mise run test:e2e [test_filename]...` — never execute e2e scripts directly\n- Slow tests (`*_slow`) are skipped unless `TEST_ALL=1`. Do not run the full suite unless asked; pick tests under the feature area you changed\n- Isolated e2e uses `env -i` and a fake `HOME`, so the agent's mise shims are not on PATH. Tests install their own tools. Host packages (zsh, fish, python3, jq, git) still need to be on `/usr/bin`\n- If GitHub API calls 429, run `export GITHUB_TOKEN=\"$(gh auth token)\"; export MISE_GITHUB_TOKEN=\"$GITHUB_TOKEN\"`\n- A leftover `/tmp/mise.toml` will fail the harness; remove it if that error appears\n\n<!-- File: llms.txt (Tokens: ~7070 | Category: root-instruction) -->\n# mise (mise-en-place) - Development Environment Tool\n\n## What is mise?\n\nmise (pronounced \"meez\") is a development environment setup tool that manages:\n1. **Dev Tools**: Installing, pinning, and switching programming languages and tools\n2. **Environments**: Loading project-specific environment variables\n3. **Tasks**: Running project automation for build, test, lint, deploy, and everyday workflows\n\nmise supports hundreds of development tools and can automatically switch between different versions based on your project directory.\n\n## Installation\n\n### Quick Install (Linux/macOS)\n```bash\ncurl https://mise.run | sh\n```\n\n### Other Methods\n- **Homebrew**: `brew install mise`\n- **Windows**: `winget install jdx.mise` or `scoop install mise`\n- **Debian/Ubuntu**: Available via apt repository\n- **Fedora**: Available via dnf repository\n\n## Core Configuration\n\n### mise.toml\nThe main configuration file for mise. Can be named:\n- `mise.toml` (project-specific)\n- `mise.local.toml` (local, not committed to git)\n- `~/.config/mise/config.toml` (global)\n\nExample `mise.toml`:\n```toml\n[tools]\nnode = \"20\"\npython = \"3.11\"\nterraform = \"1.0.0\"\ngo = \"latest\"\n\n[env]\nNODE_ENV = \"development\"\nDATABASE_URL = \"postgresql://localhost/myapp\"\n\n[tasks.test]\nrun = \"npm test\"\ndescription = \"Run tests\"\n\n[tasks.build]\nrun = \"npm run build\"\ndeps = [\"test\"]\n```\n\n### .tool-versions (asdf compatibility)\nmise is compatible with asdf's `.tool-versions` format:\n```\nnode 20.0.0\npython 3.11.5\nterraform 1.0.0\n```\n\n## Essential Commands\n\n### Tool Management\n- `mise use node@20` - Install and set node version (updates config)\n- `mise use -g node@20` - Set global default\n- `mise install` - Install all tools from config\n- `mise install node@20` - Install specific version\n- `mise ls` - List installed tools\n- `mise ls-remote node` - List available versions\n\n### Execution\n- `mise exec node@20 -- node script.js` - Run command with specific tool version\n- `mise x node@20 -- node script.js` - Shorthand for exec\n- `mise run test` - Run defined task\n- `mise test` - Shorthand (if no command conflict)\n\n### Environment\n- `mise activate bash` - Activate mise in shell (add to .bashrc)\n- `mise activate zsh` - Activate mise in zsh (add to .zshrc)  \n- `mise activate fish` - Activate mise in fish\n- `mise env` - Show current environment\n- `mise set KEY=value` - Set environment variable\n\n### Information\n- `mise doctor` - Check mise setup\n- `mise config` - Show loaded config files\n- `mise current` - Show active tool versions\n- `mise which node` - Show path to tool\n\n## Key Concepts\n\n### Activation vs Shims vs Exec\n1. **Activation** (`mise activate`): Recommended for interactive shells. Updates PATH automatically when changing directories.\n2. **Shims**: Symlinks that intercept tool calls. Good for CI/CD and IDEs.\n3. **Exec** (`mise exec`): Run commands with mise environment without activation.\n\n### Tool Scopes\n- `node@20.1.0` - Exact version\n- `node@20` - Latest 20.x version\n- `node@latest` - Latest available version\n- `node@lts` - Latest LTS version\n- `ref:master` - Build from git ref\n- `prefix:1.19` - Latest matching prefix\n- `path:/custom/path` - Use custom installation\n\n### Configuration Hierarchy\nConfig files are loaded in order (later overrides earlier):\n1. Global: `~/.config/mise/config.toml`\n2. Parent directories: `mise.toml` files going up the tree\n3. Current directory: `mise.toml`\n4. Local: `mise.local.toml`\n\n## Tasks\n\n### TOML Tasks\n```toml\n[tasks.build]\nrun = \"cargo build\"\ndescription = \"Build the project\"\ndepends = [\"install\"]\n\n[tasks.test]\nrun = \"cargo test\"\ndepends = [\"build\"]\n```\n\n### File Tasks\nCreate executable scripts in `mise-tasks/` directory:\n```bash\n#!/usr/bin/env bash\n#MISE description=\"Run tests\"\ncargo test\n```\n\n### Task Features\n- Parallel execution by default\n- Dependency management\n- File watching (`mise watch`)\n- Environment variable passing\n\n## Environment Variables\n\n### Settings\n- `MISE_DATA_DIR` - Where tools are installed (`~/.local/share/mise`)\n- `MISE_CONFIG_DIR` - Config directory (`~/.config/mise`)\n- `MISE_CACHE_DIR` - Cache directory\n- `MISE_GITHUB_TOKEN` - GitHub token for API access\n\n### Tool-specific\n- `MISE_NODE_VERSION=20` - Override node version\n- `MISE_PYTHON_VERSION=3.11` - Override python version\n\n## Common Patterns\n\n### Project Setup\n```bash\n# Initialize project\ncd my-project\nmise use node@20 python@3.11\nmise install\n\n# Add environment variables\nmise set NODE_ENV=development\nmise set DATABASE_URL=postgresql://localhost/myapp\n```\n\n### Global Tools\n```bash\n# Set global defaults\nmise use -g node@lts python@3.11 go@latest\n```\n\n### CI/CD\n```bash\n# Install mise and tools\ncurl https://mise.run | sh\nexport PATH=\"$HOME/.local/bin:$PATH\"\nmise install\nmise run build\n```\n\n## Troubleshooting\n\n### Common Issues\n- **Rate limiting**: Set `MISE_GITHUB_TOKEN` for GitHub API access\n- **Tool not found**: Run `mise doctor` to check setup\n- **Slow performance**: Check `mise cache clear` if stale\n- **Permission errors**: Ensure proper file permissions\n\n### Debugging\n- `mise doctor` - Comprehensive health check\n- `mise config` - Show config file loading order\n- `mise env` - Show current environment\n- `mise which <tool>` - Show tool path resolution\n\n## Plugin System\n\nmise uses plugins to support different tools:\n- Compatible with asdf plugins\n- Automatic plugin installation\n- Custom plugin repositories supported\n- Plugin shortcuts in registry\n\n## Migration from asdf\n\nmise is largely compatible with asdf:\n- Reads `.tool-versions` files\n- Uses asdf plugins\n- Similar commands (with improvements)\n- Can run alongside asdf temporarily\n\n## Best Practices\n\n1. Use `mise.toml` for committed project configuration\n2. Use `mise.local.toml` for local overrides\n3. Activate mise in shell for interactive use\n4. Use shims for CI/CD and IDE integration\n5. Set `MISE_GITHUB_TOKEN` to avoid rate limits\n6. Use `mise doctor` regularly to check setup\n7. Pin versions in production environments\n8. Use tasks for project automation\n\n## Advanced Features\n\n### Tool Options\n```toml\n[tools]\nnode = { version = \"20\", postinstall = \"corepack enable\" }\npython = { version = \"3.11\", virtualenv = \"myproject\" }\n```\n\n### Hooks\n```toml\n[hooks]\nenter = \"mise install --quiet\"\nleave = \"deactivate\"\n```\n\n### Multiple Versions\n```toml\n[tools]\npython = [\"3.10\", \"3.11\", \"3.12\"]  # Install multiple versions\n```\n\n## Development & Contributing\n\n### Setting Up Development Environment\n\nmise is written in Rust and uses itself for development tasks. To contribute to mise:\n\n#### Prerequisites\n- Rust (latest stable)\n- Node.js\n- `pipx` or `uv` \n- Bash (newer than macOS default)\n\n#### Getting Started\n```bash\n# Clone the repository\ngit clone https://github.com/jdx/mise.git\ncd mise\n\n# Install dependencies and build\nmise run build\n\n# Run sanity check\nmise run build\n```\n\n#### Development Setup\nCreate a development shim to easily run mise during development:\n\n```bash\n# Create ~/.local/bin/@mise\n#!/bin/sh\nexec cargo run -q --all-features --manifest-path ~/src/mise/Cargo.toml -- \"$@\"\n```\n\nThen use `@mise` to run the development version:\n```bash\n@mise --help\neval \"$(@mise activate zsh)\"\n```\n\n### Testing\n\nmise has a comprehensive test suite with multiple types of tests to ensure reliability and functionality across different platforms and scenarios.\n\n#### Unit Tests\nUnit tests are fast, focused tests for individual components and functions:\n\n```bash\n# Run all unit tests\ncargo test --all-features\n\n# Run specific unit tests\ncargo test <test_name>\n\n# Run tests with verbose output\ncargo test --all-features -- --nocapture\n\n# Run tests in series (not parallel)\nRUST_TEST_THREADS=1 cargo test --all-features\n```\n\n**Unit test structure:**\n- Located in `src/` directory alongside source code\n- Use Rust's built-in test framework\n- Test individual functions and modules\n- Fast execution (used for quick feedback during development)\n\n#### E2E Tests\nEnd-to-end tests validate the complete functionality of mise in realistic scenarios:\n\n```bash\n# Run all E2E tests\nmise run test:e2e\n\n# Run specific E2E test\n./e2e/run_test test_name\n\n# Run E2E tests matching pattern\n./e2e/run_test task  # runs tests matching *task*\n\n# Run all tests including slow ones\nTEST_ALL=1 mise run test:e2e\n```\n\n**E2E test structure:**\n- Located in `e2e/` directory\n- Organized by functionality:\n  - `e2e/cli/` - Command-line interface tests\n  - `e2e/core/` - Core functionality tests\n  - `e2e/env/` - Environment variable tests\n  - `e2e/tasks/` - Task runner tests\n  - `e2e/config/` - Configuration tests\n  - `e2e/tools/` - Tool management tests\n  - `e2e/shell/` - Shell integration tests\n  - `e2e/backend/` - Backend tests\n  - `e2e/plugins/` - Plugin tests\n\n**E2E test categories:**\n- **Fast tests** (`test_*`): Run in normal test suites\n- **Slow tests** (`test_*_slow`): Only run when `TEST_ALL=1` is set\n- **Isolated environment**: Each test runs in a clean, isolated environment\n\n#### Coverage Tests\nCoverage tests measure how much of the codebase is covered by tests:\n\n```bash\n# Run coverage tests\nmise run test:coverage\n\n# Coverage tests run in parallel tranches for CI\nTEST_TRANCHE=0 TEST_TRANCHE_COUNT=8 mise run test:coverage\n```\n\n#### Windows E2E Tests\nWindows has its own test suite written in PowerShell:\n\n```powershell\n# Run all Windows E2E tests\npwsh e2e-win\\run.ps1\n\n# Run specific Windows tests\npwsh e2e-win\\run.ps1 task  # run tests matching *task*\n```\n\n#### Plugin Tests\nTest plugin functionality across different backends:\n\n```bash\n# Test specific plugin\nmise test-tool ripgrep\n\n# Test all plugins in registry\nmise test-tool --all\n\n# Test all plugins in config files\nmise test-tool --all-config\n\n# Test with parallel jobs\nmise test-tool --all --jobs 4\n```\n\n#### Test Environment Setup\nTests run in isolated environments to avoid conflicts:\n\n```bash\n# Disable mise during development testing\nexport MISE_DISABLE_TOOLS=1\n\n# Run tests with specific environment\nMISE_TRUSTED_CONFIG_PATHS=$PWD cargo test\n```\n\n#### Test Assertions\nThe E2E tests use a custom assertion framework (`e2e/assert.sh`):\n\n```bash\n# Basic assertions\nassert \"command\" \"expected_output\"\nassert_contains \"command\" \"substring\"\nassert_fail \"command\" \"expected_error\"\n\n# JSON assertions\nassert_json \"command\" '{\"key\": \"value\"}'\nassert_json_partial_array \"command\" \"fields\" '[{...}]'\n\n# File/directory assertions\nassert_directory_exists \"/path/to/dir\"\nassert_directory_not_exists \"/path/to/dir\"\nassert_empty \"command\"\n```\n\n#### Running Specific Test Categories\n\n```bash\n# Run all tests (unit + e2e)\nmise run test\n\n# Run only unit tests\nmise run test:unit\n\n# Run only e2e tests\nmise run test:e2e\n\n# Run tests with shuffle (for detecting order dependencies)\nmise run test:shuffle\n\n# Run nightly tests (with bleeding edge Rust)\nrustup default nightly && mise run test\n```\n\n#### Running Single Tests\n\n**Unit Tests:**\n```bash\n# Run a specific unit test by name\ncargo test test_name\n\n# Run tests matching a pattern\ncargo test pattern\n\n# Run tests in a specific module\ncargo test module_name\n\n# Run a single test with output\ncargo test test_name -- --nocapture\n\n# Run a single test file (if organized by file)\ncargo test --test test_file_name\n```\n\n**E2E Tests:**\n```bash\n# Run a specific E2E test by name\n./e2e/run_test test_name\n\n# Run E2E tests matching a pattern\nmise run test:e2e pattern\n\n# Examples:\n./e2e/run_test test_use                    # Run specific test\n./e2e/run_test test_config_set            # Run config-related test\nmise run test:e2e task                     # Run all tests matching \"task\"\n```\n\n**Plugin Tests:**\n```bash\n# Test a specific plugin\nmise test-tool ripgrep\n\n# Test a plugin with verbose output\nmise test-tool ripgrep --raw\n\n# Test multiple plugins\nmise test-tool ripgrep jq terraform\n```\n\n**Windows Tests:**\n```powershell\n# Run a specific Windows test\npwsh e2e-win\\run.ps1 -TestName \"test_name\"\n\n# Run tests matching a pattern\npwsh e2e-win\\run.ps1 task\n```\n\n#### Test Development Tips\n\n1. **Test naming**: Use descriptive names that explain what's being tested\n2. **Test isolation**: Each test should be independent and clean up after itself\n3. **Use slow tests sparingly**: Mark long-running tests as `_slow` to avoid CI timeouts\n4. **Mock external dependencies**: Use dummy plugins and mock data when possible\n5. **Test edge cases**: Include tests for error conditions and boundary cases\n\n#### Performance Testing\n```bash\n# Run performance benchmarks\nmise run test:perf\n\n# Build performance test workspace\nmise run test:build-perf-workspace\n```\n\n#### Snapshot Testing\nUsed for testing output consistency:\n\n```bash\n# Update test snapshots when output changes\nmise run snapshots\n\n# Use cargo-insta for snapshot testing\ncargo insta test --accept --unreferenced delete\n```\n\n### Available Development Tasks\n\nUse `mise tasks` to see all available development tasks:\n\n#### Common Tasks\n- `mise run build` - Build the project\n- `mise run test` - Run all tests (unit + E2E)\n- `mise run test:unit` - Run unit tests only\n- `mise run test:e2e` - Run E2E tests only\n- `mise run lint` - Run linting\n- `mise run lint:fix` - Run linting with fixes\n- `mise run format` - Format code\n- `mise run clean` - Clean build artifacts\n- `mise run snapshots` - Update test snapshots\n- `mise run render` - Generate documentation and completions\n\n#### Documentation Tasks\n- `mise run docs` - Start documentation development server\n- `mise run docs:build` - Build documentation\n- `mise run render:help` - Generate help documentation\n- `mise run render:completions` - Generate shell completions\n\n#### Release Tasks\n- `mise run ci` - Run CI tasks (format, build, test)\n\n### Project Structure\n\n```\nmise/\n├── src/           # Main Rust source code\n├── e2e/           # End-to-end tests\n├── docs/          # Documentation\n├── tasks.toml     # Development tasks\n├── mise.toml      # Project configuration\n├── Cargo.toml     # Rust project configuration\n└── xtasks/        # Additional build scripts\n```\n\n### Pre-commit Hooks & Code Quality\n\nmise uses multiple approaches for ensuring code quality and running pre-commit hooks:\n\n#### hk (Modern Hook Manager)\nmise uses [hk](https://hk.jdx.dev) (pronounced \"hook\") as its primary hook manager for linting and code quality checks. hk is a modern alternative to lefthook written by the same author as mise.\n\n**hk Configuration:**\nThe project uses `hk.pkl` (written in the Pkl configuration language) to define linting rules:\n\n```bash\n# Run all linting checks\nhk check --all\n\n# Run linting with fixes\nhk fix --all\n\n# Run specific linter\nhk check --step shellcheck\n```\n\n**Available Linters in hk:**\n- **prettier**: Code formatting for multiple languages\n- **clippy**: Rust linting with `cargo clippy`\n- **shellcheck**: Shell script linting\n- **shfmt**: Shell script formatting\n\n**Using hk in Development:**\n```bash\n# Install hk via mise\nmise use hk\n\n# Run linting (used in CI and pre-commit)\nmise run lint  # This runs hk check --all\n\n# Run linting with fixes\nhk fix --all\n\n# Check specific file types\nhk check --step prettier\nhk check --step shellcheck\n```\n\n#### Traditional Pre-commit Hooks (Alternative)\nmise also supports traditional pre-commit hooks through multiple methods:\n\n**Option 1: Using lefthook (Legacy)**\n```bash\n# Install lefthook\nmise use lefthook\n\n# Install the git hooks\nlefthook install\n\n# Run pre-commit manually\nlefthook run pre-commit\n```\n\n**Option 2: Using standard pre-commit framework**\n```bash\n# Install pre-commit\nmise use pre-commit\n\n# Install the git hooks\npre-commit install\n\n# Run pre-commit manually\npre-commit run --all-files\n```\n\n**Option 3: Using mise's built-in git hook generation**\n```bash\n# Generate a git pre-commit hook that runs mise tasks\nmise generate git-pre-commit --write --task=pre-commit\n\n# This creates .git/hooks/pre-commit that runs:\n# mise run pre-commit\n```\n\n#### Pre-commit Task Configuration\nmise defines a `pre-commit` task that runs the main linting checks:\n\n```toml\n[pre-commit]\nenv = { PRE_COMMIT = 1 }\nrun = [\"mise run lint\"]\n```\n\nThis task:\n1. Sets `PRE_COMMIT=1` environment variable\n2. Runs `mise run lint`, which executes `hk check --all`\n\n#### Setting Up Pre-commit Hooks\n**Recommended approach using hk:**\n```bash\n# Install hk\nmise use hk\n\n# Set up git hook to run mise's pre-commit task\nmise generate git-pre-commit --write --task=pre-commit\n\n# Or manually create .git/hooks/pre-commit:\ncat > .git/hooks/pre-commit << 'EOF'\n#!/bin/sh\nexec mise run pre-commit\nEOF\nchmod +x .git/hooks/pre-commit\n```\n\n**Alternative approach using standard pre-commit:**\n```bash\n# Install pre-commit\nmise use pre-commit\n\n# Install hooks defined in .pre-commit-config.yaml\npre-commit install\n```\n\n#### Running Pre-commit Checks Manually\n```bash\n# Run all pre-commit checks\nmise run pre-commit\n\n# Run specific linting checks\nmise run lint\n\n# Run linting with fixes\nhk fix --all\n\n# Run checks on specific files\nhk check --files=\"src/**/*.rs\"\n```\n\n#### Environment Variables for Hooks\nWhen hooks run, they have access to these environment variables:\n- `PRE_COMMIT=1`: Indicates the code is running in pre-commit context\n- `STAGED`: Git staged files (when using mise's git hook generation)\n- `MISE_PRE_COMMIT=1`: Set by mise's generated git hooks\n\n### Testing Configuration\n\n- **Unit tests**: Fast tests for individual components\n- **E2E tests**: Integration tests that test the full application\n- **Slow tests**: Only run with `TEST_ALL=1` environment variable\n- **Windows tests**: Separate PowerShell-based test suite\n\n### Development Tips\n\n1. **Disable mise during development**: If you use mise in your shell, disable it when running tests to avoid conflicts\n2. **Use dev container**: Docker setup available (currently needs fixing)\n3. **Test specific features**: Use `cargo test <test_name>` for targeted testing\n4. **Update snapshots**: Use `mise run snapshots` when changing test outputs\n5. **Rate limiting**: Set `MISE_GITHUB_TOKEN` to avoid GitHub API rate limits during development\n\n### Dependency Management\n\nmise uses several tools to validate dependencies and code quality:\n\n- **cargo-deny**: Validates licenses, security advisories, and dependency duplicates\n- **cargo-msrv**: Verifies minimum supported Rust version compatibility\n- **cargo-machete**: Detects unused dependencies in Cargo.toml\n\nThese checks run automatically in CI and can be run locally:\n```bash\n# Install tools\nmise use cargo-deny cargo-msrv cargo-machete\n\n# Run checks\ncargo deny check\ncargo msrv verify\ncargo machete --with-metadata\n```\n\n### Contributing Guidelines\n\n1. **Before starting**: File an issue or discuss in Discord for non-obvious changes\n2. **Look for issues**: Check \"help wanted\" and \"good first issue\" labels\n3. **Test thoroughly**: Ensure both unit and E2E tests pass\n4. **Follow conventions**: Use existing code style and patterns\n5. **Update documentation**: Add/update docs for new features\n\n#### Pull Request Workflow\n1. **PR titles**: Must follow conventional commit format (validated automatically)\n2. **Auto-formatting**: Code will be automatically formatted by autofix.ci\n3. **CI checks**: All tests must pass across Linux, macOS, and Windows\n4. **Coverage**: New code should maintain or improve test coverage\n5. **Dependencies**: New dependencies are validated with cargo-deny\n\n#### GitHub Actions Development\nIf modifying GitHub Actions workflows:\n- Run `mise run lint` for the repository's configured checks\n- Self-hosted runners are configured for performance testing\n- Run the zizmor workflow for security auditing\n\n### Conventional Commits\n\nmise uses [Conventional Commits](https://www.conventionalcommits.org/) for consistent commit messages and automated changelog generation. All commits should follow this format:\n\n```\n<type>[optional scope]: <description>\n\n[optional body]\n\n[optional footer(s)]\n```\n\n#### Commit Types\n\n- **feat**: New features (🚀 Features)\n- **fix**: Bug fixes (🐛 Bug Fixes)\n- **refactor**: Code refactoring (🚜 Refactor)\n- **doc**: Documentation changes (📚 Documentation)\n- **style**: Code style changes (🎨 Styling)\n- **perf**: Performance improvements (⚡ Performance)\n- **test**: Testing changes (🧪 Testing)\n- **chore**: Maintenance tasks, dependency updates\n- **revert**: Reverting previous changes (◀️ Revert)\n\n#### Examples\n\n```bash\nfeat(cli): add new command for listing plugins\nfix(parser): handle edge case in version parsing\nrefactor(config): simplify configuration loading logic\ndoc(readme): update installation instructions\ntest(e2e): add tests for new plugin functionality\nchore(deps): update dependencies to latest versions\n```\n\n#### Scopes\n\nCommon scopes used in mise:\n- `cli` - Command line interface changes\n- `config` - Configuration system changes\n- `parser` - Parsing logic changes\n- `deps` - Dependency updates\n- `security` - Security-related changes\n\n#### Breaking Changes\n\nFor breaking changes, add `!` after the type or include `BREAKING CHANGE:` in the footer:\n\n```bash\nfeat(api)!: remove deprecated configuration options\n# OR\nfeat(api): remove deprecated configuration options\n\nBREAKING CHANGE: The old configuration format is no longer supported\n```\n\n### Packaging Testing\n\nFor testing package installation:\n\n#### Ubuntu/Debian\n```bash\n# Test apt installation\ndocker run -ti --rm ubuntu\napt update -y && apt install -y curl\n# ... installation steps\n```\n\n#### Fedora\n```bash\n# Test dnf installation  \ndocker run -ti --rm fedora\ndnf install -y dnf-plugins-core\n# ... installation steps\n```\n\n### CI/CD & Pull Request Automation\n\nmise uses several automated workflows to maintain code quality and streamline development:\n\n#### Automated Code Formatting\n- **autofix.ci**: Automatically formats code and fixes linting issues in PRs\n- Runs `mise run render` and `mise run lint-fix` automatically\n- Commits fixes directly to the PR branch\n\n#### PR Title Validation\n- **semantic-pr-lint**: Validates PR titles follow conventional commit format\n- PR titles must match: `<type>[optional scope]: <description>`\n- Example: `feat(cli): add new command for listing plugins`\n\n#### Continuous Integration\n- **Cross-platform testing**: Ubuntu, macOS, and Windows\n- **Unit tests**: Fast component-level tests\n- **E2E tests**: Full integration testing with multiple test tranches\n- **Coverage testing**: Code coverage across 8 parallel test runs\n- **Dependency validation**: `cargo deny`, `cargo msrv`, `cargo machete`\n\n#### Release Automation\n- **release-plz**: Automated release management based on conventional commits\n- Automatically creates release PRs and publishes releases\n- Runs daily via scheduled workflow\n- Handles version bumping and changelog generation\n\n## mise Codebase Architecture\n\n### Overview\n\nmise is a Rust-based tool with a modular architecture designed around three main concepts:\n1. **Tool Version Management** - Managing different versions of development tools\n2. **Environment Management** - Setting up environment variables and project contexts\n3. **Task Running** - Executing project tasks with dependency management\n\n### Core Architecture Components\n\n#### 1. **Main Entry Point** (`src/main.rs`)\n- Asynchronous Tokio runtime with multi-threading\n- Global error handling and panic hooks\n- CLI argument parsing and routing\n- Multi-progress reporting system\n\n#### 2. **CLI Layer** (`src/cli/`)\n- **Command Structure**: Each command is a separate module (e.g., `install.rs`, `use.rs`, `run.rs`)\n- **Argument Parsing**: Uses `clap` for command-line argument handling\n- **Command Execution**: Async command execution with proper error handling\n- **Key Commands**:\n  - `install` - Install tool versions\n  - `use` - Add tools to configuration\n  - `run` - Execute tasks\n  - `env` - Environment management\n  - `shell` - Shell integration\n\n#### 3. **Backend System** (`src/backend/`)\nThe backend system is the core abstraction for tool management:\n\n**Backend Trait**: Common interface for all tool backends\n```rust\npub trait Backend: Debug + Send + Sync {\n    async fn list_remote_versions(&self) -> Result<Vec<String>>;\n    async fn install_version(&self, ctx: &InstallContext, tv: &ToolVersion) -> Result<()>;\n    async fn uninstall_version(&self, tv: &ToolVersion) -> Result<()>;\n    // ... other methods\n}\n```\n\n**Backend Types**:\n- **Core Backends**: Built-in support (Node.js, Python, etc.)\n- **ASDF Backends**: External plugin system compatibility\n- **Aqua Backends**: Package manager integration\n- **Language-specific**: npm, cargo, pipx, gem, go, etc.\n- **Universal**: ubi (GitHub releases)\n\n#### 4. **Configuration System** (`src/config/`)\n**Hierarchical Configuration**:\n- `Config` struct manages all configuration sources\n- `ConfigFile` trait for different config formats:\n  - `MiseToml` - Main configuration format\n  - `ToolVersions` - ASDF compatibility\n  - `IdiomaticVersion` - Language-specific files (`.nvmrc`, `.python-version`)\n\n**Configuration Hierarchy**:\n1. System config (`/etc/mise/config.toml`)\n2. Global config (`~/.config/mise/config.toml`)\n3. Project configs (searched up directory tree)\n4. Environment-specific configs (`mise.dev.toml`)\n\n#### 5. **Toolset Management** (`src/toolset/`)\n**Core Components**:\n- `Toolset` - Collection of tools for a specific context\n- `ToolVersion` - Represents a specific version of a tool\n- `ToolRequest` - User request for a tool (e.g., `node@18`)\n- `ToolsetBuilder` - Constructs toolsets from configuration\n\n**Tool Resolution Flow**:\n1. Parse configuration files\n2. Resolve version specifications\n3. Build toolset with dependencies\n4. Install missing tools\n5. Set up environment\n\n#### 6. **Task System** (`src/task/`)\n**Task Components**:\n- `Task` struct with metadata, dependencies, and execution info\n- `Deps` - Dependency graph management using petgraph\n- `TaskFileProvider` - Discovers tasks from files and configuration\n- Parallel execution with dependency resolution\n\n**Task Types**:\n- **TOML Tasks**: Defined in `mise.toml`\n- **File Tasks**: Executable scripts in task directories\n- **Command Tasks**: Simple command execution\n- **Script Tasks**: Inline script execution\n\n#### 7. **Plugin System** (`src/plugins/`)\n**Plugin Architecture**:\n- `Plugin` trait for extensibility\n- `AsdfPlugin` - ASDF plugin compatibility\n- `VfoxPlugin` - Vfox plugin system\n- `ScriptManager` - Manages plugin scripts\n\n**Plugin Types**:\n- **Core Plugins**: Built into mise\n- **External Plugins**: Downloaded from repositories\n- **Local Plugins**: Custom local implementations\n\n#### 8. **Shell Integration** (`src/shell/`)\n**Shell Support**:\n- Bash, Zsh, Fish, PowerShell support\n- `Shell` trait for shell-specific behavior\n- Activation scripts for environment setup\n- Hook system for directory changes\n\n#### 9. **Environment Management** (`src/env*.rs`)\n**Environment Components**:\n- `EnvDiff` - Tracks environment changes\n- `EnvDirective` - Configuration for environment variables\n- `PathEnv` - PATH management\n- Context-aware environment resolution\n\n#### 10. **Caching System** (`src/cache.rs`)\n**Cache Management**:\n- `CacheManager` - Generic caching with TTL\n- File-based caching for versions, metadata\n- Automatic cache invalidation\n- Per-backend cache isolation\n\n### Key Design Patterns\n\n#### 1. **Trait-Based Architecture**\n- `Backend` trait for tool management\n- `ConfigFile` trait for configuration formats\n- `Shell` trait for shell integration\n- `Plugin` trait for extensibility\n\n#### 2. **Async/Await Throughout**\n- Tokio runtime for async operations\n- Parallel tool installations\n- Concurrent task execution\n- Non-blocking I/O operations\n\n#### 3. **Error Handling**\n- `eyre` crate for error management\n- Structured error types\n- Context-aware error reporting\n- Graceful fallback behavior\n\n#### 4. **Configuration Hierarchy**\n- Multiple configuration sources\n- Inheritance and overrides\n- Environment-specific configurations\n- Validation and trust system\n\n#### 5. **Dependency Management**\n- Tool dependencies (e.g., Node.js for npm tools)\n- Task dependencies with DAG resolution\n- Parallel execution with proper ordering\n- Circular dependency detection\n\n### Data Flow\n\n1. **Initialization**: Load configuration hierarchy\n2. **Tool Discovery**: Find available backends and versions\n3. **Resolution**: Resolve tool requests to specific versions\n4. **Installation**: Install missing tools in dependency order\n5. **Environment Setup**: Configure PATH and environment variables\n6. **Execution**: Run tasks or provide shell integration\n\n### Testing Architecture\n\n**Test Structure**:\n- **Unit Tests**: Component-level testing with mocks\n- **Integration Tests**: End-to-end CLI testing\n- **E2E Tests**: Real-world scenario testing\n- **Snapshot Tests**: Output comparison testing\n\n**Test Organization**:\n- `src/` - Unit tests alongside source code\n- `e2e/` - End-to-end test scripts\n- `test/` - Test fixtures and utilities\n- `src/snapshots/` - Snapshot test data\n\nThis architecture provides a flexible, extensible foundation for managing development environments while maintaining compatibility with existing tools and workflows.\n\nThis covers the essential information about mise for LLMs to help users effectively use the tool for development environment management and contribute to its development.\n\n<!-- File: docs/architecture.md (Tokens: ~4045 | Category: project-spec) -->\n---\ndescription: \"Find where commands, configuration, backends, tasks, environments, and bootstrap live in the mise source tree.\"\noutline: [2, 3]\n---\n\n# Codebase architecture\n\nUse this map to find the code that owns a behavior before you change it. For\nsetup, checks, and how to submit a change, see [Contributing](/contributing.html).\n\n## Library, binary, and crates {#library-binary-and-crates}\n\nThe `mise` package builds two targets. The library, `src/lib.rs`, holds\neverything except the command line: configuration, toolsets, backends, tasks,\nenvironments, and bootstrap. The binary, `src/main.rs` plus `src/cli/`, sits on\ntop of it. `src/main.rs` imports the library's root with `use mise::*`, so code\nin `src/cli/` still writes `crate::config::…`. A change confined to `src/cli/`\nrecompiles only the binary.\n\nLibrary code must not refer to `crate::cli`. When core code needs command\nbehavior, it calls a hook in\n[`src/frontend.rs`](https://github.com/jdx/mise/blob/main/src/frontend.rs),\nwhich the binary fills in at startup with `cli::register_frontend`. The hooks\ncover running `mise lock` after an install adds versions and listing subcommand\nnames for \"did you mean\" suggestions. When `cli` needs a core item, make that\nitem `pub`. The library denies `unreachable_pub`, so everything else stays\n`pub(crate)`.\n\n`cfg(test)` is set for the binary's tests but not for the library they call, so\ncore code that behaves differently under tests checks\n`mise_util::testing::in_tests()` instead.\n\nThe workspace crates under `crates/` cannot depend on the `mise` package.\n`register_util_hooks` in `src/lib.rs` gives them what they need from mise, such\nas the settings loader and the build identity used in cache keys, before\nanything else runs.\n\n| Crate                     | Contents                                                                                                   |\n| ------------------------- | ---------------------------------------------------------------------------------------------------------- |\n| `mise-util`               | Environment, directory, file, HTTP, cache, template, and `EnvDiff`/`PathEnv` helpers                       |\n| `mise-daemons`            | Daemon declarations, ports, presets, and the supervisor runtime (the toolset glue stays in `src/daemons/`) |\n| `mise-oci`                | The OCI registry client, layers, and image layout (the image builder stays in `src/oci/`)                  |\n| `mise-system`             | The bootstrap, dotfiles, and history modules                                                               |\n| `mise-config`             | The `mise.toml` declaration types, so far for `[bootstrap]`, `[dotfiles]`, and `[history]`                 |\n| `mise-system-packages`    | System package manager drivers: apt, dnf, brew, brew-cask, and more                                        |\n| `mise-ui`                 | Progress reports, prompts, and themes for the terminal                                                     |\n| `mise-settings`           | The `Settings` types, generated from `settings.toml`, and the process-wide settings cache                  |\n| `vfox`                    | The embedded Lua runtime and the hook and module interfaces for vfox plugins                               |\n| `aqua-registry`           | Parsing, package lookup, and cache formats for aqua registries                                             |\n| `mise-bootstrap`          | Bootstrap resource planning and dependency ordering                                                        |\n| `mise-lsp`                | The language server behind `mise lsp`; mise passes it `schema/mise.json` and the `mise fmt` formatter      |\n| `mise-cache-core`         | The remote task cache protocol, content-addressed storage, authentication, and transport                   |\n| `mise-shim`               | `mise-shim.exe`, the native executable that Windows shims use in the default `exe` mode                    |\n| `mise-sigstore`           | Sigstore verification helpers                                                                              |\n| `mise-tls`                | Root certificate fallback for HTTPS clients when the system trust store is empty                           |\n| `mise-agent-env`          | Detection of AI coding agents from the process environment                                                 |\n| `mise-interactive-config` | The interactive TOML editor behind `mise edit`                                                             |\n| `mise-brew-metadata`      | Homebrew formula metadata models                                                                           |\n| `mise-brew-relocation`    | Homebrew bottle placeholder and binary relocation                                                          |\n| `mise-dotenv`             | A dotenv parser with explicit control over variable substitution                                           |\n\n## Where things live {#where-things-live}\n\n| Behavior                                 | Code                                                                                                               | User docs                                        |\n| ---------------------------------------- | ------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------ |\n| Commands, flags, and help text           | `src/cli/`; `mod.rs` dispatches, and each command has a file or directory such as `use.rs`, `exec.rs`, or `tasks/` | [CLI reference](/cli/)                           |\n| What each command changes                | `src/cli/command_effects.rs`                                                                                       |                                                  |\n| Config discovery, loading, and merging   | `src/config/`; `config_file/` holds `MiseToml`, `ToolVersions`, and `IdiomaticVersionFile`                         | [mise.toml](/configuration.html)                 |\n| Settings                                 | `settings.toml`, generated into `crates/mise-settings`; loading, trust, and CLI flags in `src/config/settings.rs`  | [Settings](/configuration/settings.html)         |\n| Config file schema                       | `schema/mise.json`                                                                                                 | [mise.toml](/configuration.html)                 |\n| Tool requests, resolution, install state | `src/toolset/`                                                                                                     | [Dev tools](/dev-tools/)                         |\n| Backends                                 | `src/backend/`; the `Backend` trait is in `mod.rs` and `BackendType` in `backend_type.rs`                          | [Backends](/dev-tools/backends/)                 |\n| Core tools                               | `src/plugins/core/`                                                                                                | [Core tools](/core-tools.html)                   |\n| Plugins                                  | `src/plugins/` (asdf and vfox adapters) and `crates/vfox`                                                          | [Plugins](/plugins.html)                         |\n| Tool shorthands                          | `registry/*.toml`, compiled in by `build.rs`; lookup in `src/registry.rs`                                          | [Registry](/registry.html)                       |\n| aqua registry                            | `crates/aqua-registry`; the bundled snapshot is `vendor/aqua-registry/`, baked in by `build.rs`                    | [aqua](/dev-tools/backends/aqua.html)            |\n| Lockfile                                 | `src/lockfile.rs` and `src/lockfile/`                                                                              | [Lockfile](/dev-tools/mise-lock.html)            |\n| Environment directives                   | `src/config/env_directive/`; `EnvDiff` and `PathEnv` come from `crates/mise-util`                                  | [Environment variables](/environments/)          |\n| Shell activation                         | `src/shell/` (one file per shell), `src/hook_env.rs`, `src/cli/activate.rs`                                        | [Shell setup](/shell-setup.html)                 |\n| Shims                                    | `src/shims.rs` and `crates/mise-shim`                                                                              | [Shims](/dev-tools/shims.html)                   |\n| Templates                                | `crates/mise-util/src/tera.rs`, re-exported as `src/tera.rs`                                                       | [Tera templates](/templates.html)                |\n| Tasks                                    | `src/task/`                                                                                                        | [Tasks](/tasks/)                                 |\n| Remote task cache                        | `crates/mise-cache-core`                                                                                           | [Remote task cache](/tasks/remote-cache.html)    |\n| Bootstrap and host packages              | `src/cli/bootstrap.rs`, `crates/mise-system` (packages in `crates/mise-system-packages`), `crates/mise-bootstrap`  | [Bootstrap](/bootstrap.html)                     |\n| Dotfiles                                 | `src/cli/dotfiles/`, `crates/mise-system/src/managed_files.rs`, `crates/mise-system/src/history/`                  | [Dotfiles](/dotfiles.html)                       |\n| Daemons                                  | `src/daemons/` (toolset glue), `crates/mise-daemons`                                                               | [Daemons](/daemons.html)                         |\n| Project dependencies                     | `src/deps/`                                                                                                        | [Project dependencies](/dev-tools/deps.html)     |\n| Secrets                                  | `src/secrets/`, `src/sops.rs`, `src/agecrypt.rs`                                                                   | [Secrets](/environments/secrets/)                |\n| Caches                                   | `crates/mise-util/src/cache.rs`: `CacheManager<T>`, MessagePack with zlib, written atomically                      | [Caches](/cache-behavior.html)                   |\n| packslip manifests                       | `src/packslip.rs`, `src/backend/packslip.rs`                                                                       | [packslip](/dev-tools/backends/packslip.html)    |\n| OCI images                               | `src/oci/` (builder), `crates/mise-oci`                                                                            | [OCI images](/dev-tools/mise-oci.html)           |\n| OpenTelemetry                            | `src/otel/`                                                                                                        | [OpenTelemetry](/tasks/opentelemetry.html)       |\n| Identity install layout                  | `src/install_layout/`                                                                                              | [Install layout](/dev-tools/install-layout.html) |\n| Sandboxing                               | `src/sandbox.rs`                                                                                                   | [Sandboxing](/sandboxing.html)                   |\n| Self-update                              | `src/cli/self_update.rs`                                                                                           | [Packaging mise](/packaging.html)                |\n\n## How a command runs {#system-overview}\n\nMost commands load the configuration, resolve the tools it requests, build an\nenvironment from them, and then run a child process or print shell code. Tasks\nand bootstrap start from the same configuration.\n\n```mermaid\nflowchart TD\n    CLI[CLI command] --> Config[Configuration and settings]\n    Config --> Tools[Tool requests and backend resolution]\n    Tools --> Env[Environment and PATH]\n    Env --> Exec[Child command or shell output]\n    Config --> Tasks[Task discovery and dependency graph]\n    Tasks --> Env\n    Config --> Bootstrap[Bootstrap plan and explicit apply]\n```\n\n### Configuration {#configuration-system}\n\n[`src/config`](https://github.com/jdx/mise/tree/main/src/config) finds config\nfiles, loads them through the `ConfigFile` trait, and merges them. Which files\nare found, whether they are trusted, and how each field merges are separate\ndecisions in the code. Settings, tools, environment directives, tasks, and\nbootstrap entries do not merge the same way, and write commands pick their\n[target file](/configuration.html#target-file-for-write-operations) separately.\n\n### Toolsets {#toolset-management}\n\n[`src/toolset`](https://github.com/jdx/mise/tree/main/src/toolset) connects\nversion requests to resolved versions and installation state:\n\n| Type             | Role                                                                                  |\n| ---------------- | ------------------------------------------------------------------------------------- |\n| `ToolRequest`    | A request such as `node@24`, a channel, or a ref, with its backend and options        |\n| `ToolVersion`    | A resolved version and its installation metadata                                      |\n| `Toolset`        | The requests and resolved versions for the current context                            |\n| `ToolsetBuilder` | Combines config, environment variable overrides, and command arguments, then resolves |\n\n### Backends {#backend-system}\n\nThe [`Backend` trait](https://github.com/jdx/mise/blob/main/src/backend/mod.rs)\nsplits shared policy from backend-specific work. Its public wrapper methods\nhandle caching and resolution. A backend implements hooks such as\n`_list_remote_versions`, which returns `VersionInfo` entries, and\n`install_version_`. Core tools in `src/plugins/core/` implement the same trait.\nFor how mise picks a backend for a short name, see\n[how backend selection works](/dev-tools/backends/#how-backend-selection-works);\nto add one, see [Adding a backend](/contributing.html#adding-backends).\n\n### Plugins {#plugins}\n\n[`src/plugins`](https://github.com/jdx/mise/tree/main/src/plugins) installs\nplugin sources and records their metadata.\n[`crates/vfox`](https://github.com/jdx/mise/tree/main/crates/vfox) runs vfox\nplugins in its embedded Lua runtime. Tool plugins install one tool, backend\nplugins handle `plugin:tool` requests, environment plugins return variables and\n`PATH` entries, and package plugins manage batches of host packages. asdf\nadapters run legacy shell scripts. Installing or updating a plugin's source is\nseparate from installing a tool version, and each keeps its own state. See\n[Plugins](/plugins.html).\n\n### Tasks {#task-system}\n\n[`src/task`](https://github.com/jdx/mise/tree/main/src/task) discovers, schedules,\nand runs tasks. `Task` holds a definition, the providers in\n`task_file_providers/` load local and remote task files, `Deps` is the\ndependency graph, and the executor and scheduler run ready tasks under the\nconfigured concurrency and output style. A node in the graph is a task with its\narguments, environment variables, and run phase, so the same task with\ndifferent arguments is a separate node. Read\n[Dependencies and execution order](/tasks/architecture.html) before you change\nhow the graph is built or how `depends`, `depends_post`, and `wait_for` behave.\n\n### Environment and shell activation {#shell-integration}\n\n`src/config/env_directive` evaluates `[env]` directives. Directives marked\n`tools = true` run after tools are resolved, and the rest run before.\n`mise activate` emits a shell hook from `src/shell/` that runs `mise hook-env`\nat each prompt. `hook-env` records an `EnvDiff` so the next run can undo the previous\ndirectory's changes before applying new ones. `mise exec` and `mise run` build\nthe child environment directly and do not need activation.\n\n### Bootstrap and host state {#bootstrap-and-host-state}\n\n`src/cli/bootstrap.rs` builds a plan and runs the selected phases. The code in\n`crates/mise-system` manages packages, files, edits, repositories, services, and\nplatform-specific resources, which live outside any tool's install directory.\nStatus, preview, apply, and prune are separate operations: a status check reads\nthe host and changes nothing. A package batch can be a subset named on the\ncommand line, so never treat a package's absence from a batch as a request to\nremove it.\n\n## Rules to preserve {#rules-to-preserve}\n\n- Treat versions as opaque strings. Resolve a request through the backend\n  (`Backend::latest_version`, `Backend::list_versions_matching`,\n  `ToolRequest::resolve`), never with a semver sort at a new call site.\n- Compare lockfile versions with `==`, keep the backend and checksum of an\n  entry, and never write `latest`, `lts/*`, or a prefix into the lockfile.\n- Do not add installs or network requests to a code path that only reports\n  local state.\n- Build a subprocess's environment from the one mise computed, not the\n  inherited process environment, which can miss earlier directives or select\n  the wrong tool.\n- Include every input that changes a cached result in its cache key, such as\n  options, environment variables, and source metadata. The environment cache\n  (`src/toolset/env_cache.rs`) and the task caches (`src/task/task_cache.rs`)\n  do not use `CacheManager` and have their own formats and invalidation rules.\n- Keep Windows `PATH` in native form inside mise and in child processes.\n  Convert it only when emitting assignments into a running, positively\n  identified MSYS2 or Cygwin shell; the\n  [agent guide](https://github.com/jdx/mise/blob/main/AGENTS.md) has the full\n  rules.\n- Classify every new command in `src/cli/command_effects.rs`; see\n  [Changing a CLI command](/contributing.html#changing-a-cli-command).\n\n## Generated files {#generated-files}\n\nEdit the source, then regenerate. Commit the output with the change that\nproduced it.\n\n| Output                                                                 | Source                                                                                                                                                   | Regenerate with                               |\n| ---------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------- |\n| `mise.usage.kdl`, `docs/cli/`                                          | Command definitions in `src/cli/`, `src/assets/mise-extra.usage.kdl`, and `docs/.vitepress/cli-reference.ts`                                             | `mise run render:usage`                       |\n| `tasks.md`                                                             | The project's tasks in `tasks.toml`, `xtasks/`, and `mise.toml`, through `mise generate task-docs`                                                       | `mise run render:usage`                       |\n| `man/man1/mise.1`                                                      | `mise.usage.kdl`                                                                                                                                         | `mise run render:mangen`                      |\n| `completions/`                                                         | The usage spec, through `mise completion <shell>`                                                                                                        | `mise run render:completions`                 |\n| `docs/.vitepress/cli_commands.ts` and the idiomatic version file table | `src/cli/` and the `idiomatic_files` keys in `registry/*.toml`                                                                                           | `mise run render:help`                        |\n| `schema/mise.json`, `schema/mise-task.json`, `schema/miserc.json`      | The types and doc comments in `crates/mise-config` (`MiseTomlDecl` for the top level) and `settings.toml`, through mise-config's `render-schema` example | `mise run render:schema`                      |\n| `docs/public/llms.txt`                                                 | Page titles and leads, and `docs/.vitepress/sidebar.ts`                                                                                                  | `mise run render:llms`                        |\n| `Settings` types                                                       | `settings.toml`                                                                                                                                          | Every build (`crates/mise-settings/build.rs`) |\n| The registry compiled into mise                                        | `registry/*.toml`                                                                                                                                        | Every build (`build.rs`)                      |\n| The [settings reference](/configuration/settings.html)                 | `settings.toml`                                                                                                                                          | Every docs build                              |\n\n`mise run render` runs every `render:*` task. For the schemas, change the types\nand doc comments in `crates/mise-config`, not the JSON; a `mise-config` test\nfails while the committed files are stale.\n\n## Tests {#tests}\n\nUnit tests sit beside the code they test, E2E tests are Bash scripts under\n`e2e/` run with `mise run test:e2e`, and the Windows E2E tests under `e2e-win/`\nuse Pester. See [Testing](/contributing.html#testing) for the commands and\nprerequisites.\n\n<!-- File: crates/vfox/plugins/.luarc.json (Tokens: ~84 | Category: anthropic-skill) -->\n{\n  \"$schema\": \"https://raw.githubusercontent.com/LuaLS/vscode-lua/master/setting/schema.json\",\n  \"runtime\": {\n    \"version\": \"Lua 5.1\"\n  },\n  \"diagnostics\": {\n    \"disable\": [\"duplicate-set-field\"]\n  },\n  \"workspace\": {\n    \"checkThirdParty\": false,\n    \"library\": [\"../types\"]\n  }\n}\n\n<!-- File: docs/bootstrap/packages/apk.md (Tokens: ~300 | Category: anthropic-skill) -->\n# Packages Skill\n\nPath: `docs/bootstrap/packages/apk.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/bootstrap/packages/apk.md)\n\n<!-- File: docs/bootstrap/packages/apt.md (Tokens: ~300 | Category: anthropic-skill) -->\n# Packages Skill\n\nPath: `docs/bootstrap/packages/apt.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/bootstrap/packages/apt.md)\n\n<!-- File: docs/bootstrap/packages/brew.md (Tokens: ~300 | Category: anthropic-skill) -->\n# Packages Skill\n\nPath: `docs/bootstrap/packages/brew.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/bootstrap/packages/brew.md)\n\n<!-- File: docs/bootstrap/packages/dnf.md (Tokens: ~300 | Category: anthropic-skill) -->\n# Packages Skill\n\nPath: `docs/bootstrap/packages/dnf.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/bootstrap/packages/dnf.md)\n\n<!-- File: docs/bootstrap/packages/flatpak.md (Tokens: ~300 | Category: anthropic-skill) -->\n# Packages Skill\n\nPath: `docs/bootstrap/packages/flatpak.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/bootstrap/packages/flatpak.md)\n\n<!-- File: docs/bootstrap/packages/index.md (Tokens: ~300 | Category: anthropic-skill) -->\n# Packages Skill\n\nPath: `docs/bootstrap/packages/index.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/bootstrap/packages/index.md)\n\n<!-- File: docs/bootstrap/packages/mas.md (Tokens: ~300 | Category: anthropic-skill) -->\n# Packages Skill\n\nPath: `docs/bootstrap/packages/mas.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/bootstrap/packages/mas.md)\n\n<!-- File: docs/bootstrap/packages/pacman.md (Tokens: ~300 | Category: anthropic-skill) -->\n# Packages Skill\n\nPath: `docs/bootstrap/packages/pacman.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/bootstrap/packages/pacman.md)\n\n<!-- File: docs/bootstrap/packages/plugins.md (Tokens: ~300 | Category: anthropic-skill) -->\n# Packages Skill\n\nPath: `docs/bootstrap/packages/plugins.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/bootstrap/packages/plugins.md)\n\n<!-- File: docs/cli/bootstrap/packages/apply.md (Tokens: ~300 | Category: anthropic-skill) -->\n# Packages Skill\n\nPath: `docs/cli/bootstrap/packages/apply.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/cli/bootstrap/packages/apply.md)\n\n<!-- File: docs/cli/bootstrap/packages/brew.md (Tokens: ~300 | Category: anthropic-skill) -->\n# Packages Skill\n\nPath: `docs/cli/bootstrap/packages/brew.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/cli/bootstrap/packages/brew.md)\n\n<!-- File: docs/cli/bootstrap/packages/brew/tap.md (Tokens: ~300 | Category: anthropic-skill) -->\n# Brew Skill\n\nPath: `docs/cli/bootstrap/packages/brew/tap.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/cli/bootstrap/packages/brew/tap.md)\n\n<!-- File: docs/cli/bootstrap/packages/brew/untap.md (Tokens: ~300 | Category: anthropic-skill) -->\n# Brew Skill\n\nPath: `docs/cli/bootstrap/packages/brew/untap.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/cli/bootstrap/packages/brew/untap.md)\n\n<!-- File: docs/cli/bootstrap/packages/import.md (Tokens: ~300 | Category: anthropic-skill) -->\n# Packages Skill\n\nPath: `docs/cli/bootstrap/packages/import.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/cli/bootstrap/packages/import.md)\n\n<!-- File: docs/cli/bootstrap/packages/prune.md (Tokens: ~300 | Category: anthropic-skill) -->\n# Packages Skill\n\nPath: `docs/cli/bootstrap/packages/prune.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/cli/bootstrap/packages/prune.md)\n\n<!-- File: docs/cli/bootstrap/packages/status.md (Tokens: ~300 | Category: anthropic-skill) -->\n# Packages Skill\n\nPath: `docs/cli/bootstrap/packages/status.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/cli/bootstrap/packages/status.md)\n\n<!-- File: docs/cli/bootstrap/packages/upgrade.md (Tokens: ~300 | Category: anthropic-skill) -->\n# Packages Skill\n\nPath: `docs/cli/bootstrap/packages/upgrade.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/cli/bootstrap/packages/upgrade.md)\n\n<!-- File: docs/cli/bootstrap/packages/use.md (Tokens: ~300 | Category: anthropic-skill) -->\n# Packages Skill\n\nPath: `docs/cli/bootstrap/packages/use.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/cli/bootstrap/packages/use.md)\n\n<!-- File: docs/cli/bootstrap/plugins/apply.md (Tokens: ~300 | Category: anthropic-skill) -->\n# Plugins Skill\n\nPath: `docs/cli/bootstrap/plugins/apply.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/cli/bootstrap/plugins/apply.md)\n\n<!-- File: docs/cli/bootstrap/plugins/status.md (Tokens: ~300 | Category: anthropic-skill) -->\n# Plugins Skill\n\nPath: `docs/cli/bootstrap/plugins/status.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/cli/bootstrap/plugins/status.md)\n\n<!-- File: docs/cli/plugins/install.md (Tokens: ~300 | Category: anthropic-skill) -->\n# Plugins Skill\n\nPath: `docs/cli/plugins/install.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/cli/plugins/install.md)\n\n<!-- File: docs/cli/plugins/link.md (Tokens: ~300 | Category: anthropic-skill) -->\n# Plugins Skill\n\nPath: `docs/cli/plugins/link.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/cli/plugins/link.md)\n\n<!-- File: docs/cli/plugins/ls-remote.md (Tokens: ~300 | Category: anthropic-skill) -->\n# Plugins Skill\n\nPath: `docs/cli/plugins/ls-remote.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/cli/plugins/ls-remote.md)\n\n<!-- File: docs/cli/plugins/ls.md (Tokens: ~300 | Category: anthropic-skill) -->\n# Plugins Skill\n\nPath: `docs/cli/plugins/ls.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/cli/plugins/ls.md)\n\n<!-- File: docs/cli/plugins/uninstall.md (Tokens: ~300 | Category: anthropic-skill) -->\n# Plugins Skill\n\nPath: `docs/cli/plugins/uninstall.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/cli/plugins/uninstall.md)\n\n<!-- File: docs/cli/plugins/update.md (Tokens: ~300 | Category: anthropic-skill) -->\n# Plugins Skill\n\nPath: `docs/cli/plugins/update.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/jdx/mise/HEAD/docs/cli/plugins/update.md)\n\n<!-- ... +9 more modular skills available via /api/skills/jdx/mise?path={path} -->\n</yakaai_skills>"}