How to Set a Project-Specific Tool Version with mise: A Complete Guide

You set a project-specific tool version in mise by using the mise local command, which writes to a .tool-versions file in your project directory, and mise automatically discovers this file when executing commands within that project tree.

The mise tool (formerly rtx) manages runtime versions through project-specific configuration files. Setting a project-specific tool version ensures that every developer and CI pipeline uses the exact same runtime, eliminating "works on my machine" issues. This workflow centers on the .tool-versions file and the local subcommand implemented in the jdx/mise repository.

How Project-Specific Configuration Works in mise

mise determines which tool version to use by traversing the directory hierarchy for a .tool-versions file. According to the source code in src/env.rs, the environment variable MISE_DEFAULT_TOOL_VERSIONS_FILENAME defaults to .tool-versions, establishing the standard filename that mise searches for.

In src/config/mod.rs, the helper function is_tool_versions_file identifies these configuration files and treats them as low-priority, read-only sources for writes. When you execute a command, mise walks up the directory tree from your current working directory, parsing the nearest .tool-versions file it finds.

The parsing logic resides in src/config/config_file/tool_versions.rs, which handles the file format and syntax quirks, converting the contents into ToolVersions objects that the rest of the application consumes. The origin of each tool version is tracked via src/toolset/tool_source.rs, allowing mise to report where a particular version was defined.

Using mise local to Set Tool Versions

The mise local command, implemented in src/cli/local.rs, provides the primary interface for setting project-specific versions. This command searches the current directory and its ancestors for an existing .tool-versions file, or creates one in the current working directory if none exists.

The command supports several modes for version specification:

  • Fuzzy versioning (--fuzzy): Allows version prefixes like node@20
  • Exact pinning (--pin): Writes the precise version such as node@20.0.0
  • Removal (--unset): Deletes a tool entry from the configuration

When you specify a version, the request passes through the ToolRequest machinery, which delegates to the appropriate backend in src/backend/mod.rs. This backend knows how to resolve "latest", version prefixes, or channel names, ensuring correct handling of non-SemVer version schemes.

Practical Examples for mise local

Here are the concrete commands for managing project-specific tool versions:


# Set a fuzzy version (e.g., "node 20") for the current project

mise local --fuzzy node@20

# Pin an exact version (e.g., "node 20.0.0") for the current project

mise local --pin node@20.0.0

# Remove a tool from the project's .tool-versions

mise local --unset node

# Show the version that will be used for the current directory

mise local node

These commands edit the .tool-versions file located in the current directory or the nearest ancestor containing one. If no such file exists, mise creates it in the current working directory, ensuring the configuration is immediately available for the project.

Version Resolution and Persistence

When mise writes to a .tool-versions file, it preserves the existing format while adding or updating the specific tool entry. The local command handles both the discovery and persistence phases: it locates the correct configuration file through directory traversal, then writes the new entry back to that file.

The version resolution process involves multiple components working together. The ToolRequest structure processes your version string, and the backend implementation in src/backend/mod.rs determines how to interpret fuzzy matches versus exact pins. This architecture supports complex version schemes beyond simple SemVer, including channels and build metadata.

Summary

  • Use mise local to set project-specific tool versions that apply to the current directory and its subdirectories.
  • Configuration files are named .tool-versions by default (controlled by MISE_DEFAULT_TOOL_VERSIONS_FILENAME in src/env.rs).
  • Discovery mechanism traverses up the directory tree from your current working directory to find the nearest configuration file (src/cli/local.rs).
  • Version flexibility supports fuzzy matching (--fuzzy), exact pinning (--pin), and removal (--unset) through the backend resolution system in src/backend/mod.rs.
  • Automatic creation occurs when setting a version in a directory without an existing .tool-versions file.

Frequently Asked Questions

What is the difference between mise local and mise global?

The mise local command writes to a .tool-versions file in your project directory (or the nearest parent directory), making the version specific to that project. In contrast, mise global writes to your home directory's configuration file, setting a default version for your entire user account. The local configuration takes precedence when you are inside the project directory.

How does mise find the correct .tool-versions file?

mise searches for .tool-versions starting from your current working directory and walking up the directory tree until it finds a match or reaches the filesystem root. This logic is implemented in src/cli/local.rs and uses the filename defined by MISE_DEFAULT_TOOL_VERSIONS_FILENAME in src/env.rs. The first file found determines the tool versions for that location.

Can I use mise local with non-SemVer version strings?

Yes. The version resolution in src/backend/mod.rs handles various version schemes including channels (like "latest" or "stable"), partial versions, and tool-specific formats. When you use mise local --fuzzy, mise delegates to the specific backend for that tool, which knows how to resolve the version string according to the tool's own versioning rules.

What happens if no .tool-versions file exists when I run mise local?

If no .tool-versions file exists in the current directory or its ancestors, the mise local command automatically creates one in your current working directory. This new file will contain only the tool version you specified, and mise will use this file for version resolution when executing commands within that directory tree.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →