Утилита mise (полное название MISE-EN-PLACE) настраивает необходимое для разработки окружение:

  • Для разработчика это глобальный набор инструментов (от языков программирования до мелких утилит) нужных версий.

  • Для проектов это аналогичный набор инструментов (специфичных для этого проекта версий, одинаковых у всех разработчиков и на CI) плюс конфигурация (переменные окружения/зашифрованные секреты для конкретного dev/staging/prod/… окружения плюс локальные отличия) плюс задачи (скрипты) для сборки/тестирования/деплоя/….

Есть множество других утилит решающих те же задачи, но mise сильно выделяется:

  • mise заменяет все остальные аналогичные утилиты т.к. содержит весь необходимый функционал.

  • То, что в других утилитах работало странно или не поддерживалось - в mise сделано правильно!

  • Безумная гибкость (дающая возможность внедрять mise постепенно):

    • … настройки (имена/количество/иерархия конфиг-файлов mise)

    • … стиля использования (от полного встраивания в шелл для максимального юзабилити до использования единственной необходимой команды mise install или mise run - для тех членов команды, которым не хочется разбираться с mise, но нужно работать с проектом использующим mise)

    • … глубины внедрения в проект (нет необходимости обязательно использовать и установку инструментов и управление переменными окружения и задачи, а даже если использовать то нет необходимости обязательно управлять абсолютно всеми инструментами/переменными окружения/задачами именно через mise - можно переносить в конфиг mise всё это постепенно)

  • Фактически, все будущие аналогичные утилиты будут вынуждены равняться на mise, потому что mise задала новый стандарт "базовой функциональности" в этой области.

Разумеется, mise соответствует типовым ожиданиям от современной утилиты:

  • Написана на Rust. Т.е. для установки достаточно скачать один бинарник и работает очень быстро.

  • Работает на всех ОС (Linux/MacOS/Windows) и основных платформах (x64, arm).

  • Интегрируется (опционально) в любой шелл (bash, zsh, fish, powershell, nushell, xonsh, elvish).

Я использую mise примерно полтора года, постепенно перевожу на неё все свои проекты, и мне однозначно нравится результат! Дальше я опишу свои впечатления от использования mise, но, в общем и целом, всё необходимое есть в официальной доке.

Типовой сценарий использования mise

  1. У вас установлена (один бинарник в PATH) и активирована (одна строка в ~/.bashrc) mise.

  2. Скачиваете (git clone …) проект использующий mise.

  3. Заходите (cd …) в каталог проекта, и в текущем шелле появляются переменные окружения с конфигурацией и расшифрованными секретами этого проекта (они пропадут, когда вы выйдете из каталога проекта).

  4. Запускаете mise tasks чтобы увидеть список и описания всех задач проекта (сборка, тестирование, деплой, …) - нет необходимости искать эту информацию в README.

  5. Запускаете нужную задачу через mise run …, причём с работающим --help, автодополнением имён, флагов и аргументов для всех задач. При этом будут автоматически установлены все необходимые этому проекту инструменты, причём тех же версий, какие используют все разработчики этого проекта.

Варианты интеграции в шелл/IDE

mise позволяет задать для проекта: инструменты, переменные окружения и задачи.
Задачи запускаются через mise run и всегда видят заданные инструменты и переменные окружения. Остаётся вопрос, как получить доступ к инструментам и переменным окружения проекта вне задач, т.е. в шелле/IDE/файловом менеджере вроде mc.

Любую команду можно запустить через mise exec -- команда, и тогда она тоже будет видеть заданные инструменты и переменные окружения.

Первый вариант интеграции: никакой интеграции не требуется, но запускать всё нужно исключительно через mise run и mise exec. Это удобный вариант для использования на CI, а так же если во время работы над проектом всё необходимое запускается либо через задачи mise либо через скрипты/Makefile в которых используется mise exec.

Если доступ к инструментам нужен напрямую, без mise exec, то возникает необходимость добавить путь к инструментам в $PATH (как минимум это актуально если используются глобально установленные инструменты).

Второй вариант интеграции: использование shims. В этом варианте в $PATH необходимо добавить один каталог ~/.local/share/mise/shims, который содержит симлинки для всех инструментов из всех конфигов mise (глобального и всех проектов) ведущие на саму mise. В результате, при запуске любого из этих инстументов будет запущена mise, которая обработает конфиги относящиеся к текущему каталогу/проекту, загрузит переменные окружения и запустит нужную версию инструмента. Задержка при таком запуске незначительная (порядка 30ms). Этот вариант рекомендуется использовать для запуска IDE и файловых менеджеров вроде mc, которые могут открывать разные проекты и запускать в них разные инструменты без mise exec.

Третий вариант интеграции: вызов eval "$(mise activate шелл)" при запуске шелла (т.е. добавление этой команды в ~/.bashrc и т.п.). В этом варианте будут установлены хуки в шелл, которые будут устанавливать $PATH и переменные окружения в зависимости от текущего проекта. Т.е. при cd в/из каталога проекта в $PATH будут добавляться/удаляться пути к индивидуальным инструментам (да, если у вас 100 инструментов, в то в $PATH будет 100 отдельных записей для них - и нет, тормозить это не будет) плюс перед выполнением каждой команды шелла будут добавляться/удаляться переменные окружения проекта. Это самый инвазивный вариант, но и самый удобный для интерактивной работы в шелле, потому что изменения конфигов mise сразу же отражаются в текущем шелле - в отличие от альтернатив вроде запуска шелла в каталоге проекта через mise exec -- bash или mise en, при которых PATH и переменные окружения задаются при запуске шелла и больше не обновляются.

Для некоторых IDE есть поддержка mise, позволяющая в т.ч. обеспечить доступ к переменным окружения.

Конфигурация

Конфиг mise пишется в формате TOML, и обычно хватает двух файлов: ~/.config/mise/config.toml (с глобальными настройками и инструментами) и mise.toml в корне текущего проекта.

На первый взгляд может показаться, что если разработчик не сильно заинтересован в mise и вынужден ей пользоваться только потому, что mise используется в текущем проекте, то глобальный конфиг ему не нужен вообще. Но есть несколько нюансов, из-за которых глобальный конфиг всё-таки стоит создать почти всем:

  • Удобство. Для работы автодополнения в шелле флагов/аргументов самой mise и флагов/аргументов задач проекта (mise run …) нужно установить дополнительную утилиту usage. Она не нужна конкретному проекту, поэтому в mise.toml проекта её никто не впишет, так что единственный способ её установить - добавить её в глобальный конфиг.

  • Функциональность. Для поддержки автозапуска задач mise при изменении файлов проекта (через mise watch …) тоже нужна дополнительная утилита watchexec. Та же история, что с usage.

  • Производительность. Для установки инструментов через некоторые бэкенды доступны альтернативные, более эффективные альтернативы. Например использование bun или pnpm вместо npm для бэкенда npm. Это имеет смысл настроить именно в глобальном конфиге.

  • Безопасность. В mise есть поддержка "параноидального" режима. Поскольку конфиги mise могут приводить к выполнению любых команд и изменять переменные окружения при входе в каталог проекта, и при этом они скачиваются/обновляются из чужих репозиториев, то есть смысл их просматривать перед использованием. Параноидальный режим обеспечивает более строгую защиту, и для его включения и настройки тоже нужно использовать глобальный конфиг.

В результате, минимальный глобальный конфиг эффективного параноика :) выглядит примерно так:

[settings]
disable_default_registry = true
paranoid = true
# В ~/proj/ только личные проекты, рабочие и форки чужих в других каталогах.
trusted_config_paths = ["~/proj/"]

[settings.npm]
package_manager = "pnpm"

[tools]
# Нужна для поддержки автокомлита в шелле для mise и mise tasks проектов.
usage = "latest"
# Нужна для поддержки `mise watch`.
watchexec = "latest"
# Нужна для settings.npm.package_manager.
pnpm = "latest"
# Ускоряет установку для бэкенда "cargo:".
cargo-binstall = "latest"

Файл mise.toml в корне проекта - это далеко не единственный вариант имени и расположения конфига mise. Это может показаться спорным решением, но mise поддерживает больше десятка базовых вариантов - разное расположение (в корне, в подкаталогах mise/, .config/, .config/mise/), разное именование (имена могут начинаться и на mise и на .mise), разная структура (один файл или каталог с файлами). Добавим локальные версии этих конфиг-файлов (заканчивающиеся на .local.toml, которые должны быть указаны в .gitignore). Плюс добавим версии файлов для разных окружений (dev/staging/prod). В результате легко получить с полсотни возможных путей к конфигам mise. Плюс рекурсивная подгрузка конфигов из вышестоящих каталогов… Тем не менее, для всех этих вариантов чётко определены приоритеты и правила объединения настроек, так что если не пытаться специально создать максимальный бардак, и придерживаться в рамках проекта какого-то одного стиля, то никаких реальных проблем эта гибкость не создаст. Команда mise config покажет, какие конфиги и в каком порядке загружаются для текущего каталога.

Конфиги mise можно редактировать двумя способами: либо как обычный файл, либо через соответствующие команды mise (mise edit, mise use …, mise settings …, etc.). Я рекомендую использовать какой-то один из этих двух подходов, потому что редактирование командами может приводить к удалению вручную добавленных комментариев и перемещению записей в конфиге.

Инструменты

mise возвращает контроль над установленными глобально (для текущего пользователя, а не конкретного проекта) инструментами. В глобальном конфиге mise можно добавить комментарии, помогающие вспомнить зачем был нужен когда-то установленный инструмент. mise даёт возможность одной командой обновить все инструменты, узнать какие версии каждого инструмента установлены и удалить уже не нужные (отсутствующие в конфиге) инструменты/версии. Переход на mise позволил мне капитально почистить свои ~/.local/bin/ и ~/go/bin/ от непонятных бинарников, установленных много лет назад.

Что можно установить через mise? Практически всё! Сама mise реализует установку языков программирования (Go, Java, NodeJS, Python, …), а всё остальное устанавливается через кучу разных "бэкендов" реализующих совместимость с разными источниками приложений. Например:

  • бэкенд github позволяет установить любой бинарник выложеный в GitHub Releases

  • бэкенд go позволяет установить любое приложение поддерживающее установку через go install

  • бэкенды aqua, asdf, vfox позволяют установить любое приложение которое умеют устанавливать эти утилиты

  • бэкенды npm, pipx, gem позволяют установить пакеты из соответствующих репозиториев

  • … и это далеко не полный список бэкендов

А что делать, если нужный инструмент всё-таки отсутствует? Написать для установки этого инструмента свой плагин для vfox (на lua) или asdf (на bash), после чего его сможет установить и mise через соответствующий бэкенд.

В mise есть собственный реестр инструментов, который позволяет указать инструмент без бэкенда, т.е. сделать mise install rg вместо mise install aqua:BurntSushi/ripgrep или mise install cargo:ripgrep или mise install github:BurntSushi/ripgrep. В этом реестре сейчас под 1000 инструментов, но это не значит, что через mise можно установить только эту 1000 - просто для установки остальных нужно явно задавать backend и полное имя инструмента.

Так же через mise довольно удобно пробовать новые инструменты. Например, сегодня в новостях прочитал про утилиту llm-checker: открыл гитхаб, увидел что она написана на JS, и этого хватило чтобы запустить её через mise exec npm:llm-checker -- llm-checker -h. При первом запуске она скачалась и установилась, но поскольку ни в какие конфиги mise я её не добавил, то когда в будущем будет запущен mise prune она будет удалена.

mise позволяет одновременно установить кучу разных версий одного инструмента. Если у этих версий разные названия бинарников (напр. python3.12) то они будут доступны все одновременно, а если бинарник называется одинаково то можно выбрать какую версию использовать запустив команду через mise exec TOOL@VERSION -- команда. А при запуске задач mise можно прямо в конфиге mise для конкретной задачи задать какие версии каких инструментов должны быть видны в этой задаче (например, чтобы прогонять тесты на предыдущих версиях языка).

Есть два способа задать нужную проекту версию инструмента: либо указать её непосредственно в конфиге mise, либо использовать для этого отдельный lockfile. На мой взгляд, в конфиге mise лучше указывать принципиально поддерживаемое проектом подмножество версий - обычно либо "latest" если требуется поддержка любой новой версии, либо префикс версии вроде "1.2" если поддерживаются все "1.2.x - это заметно упростит регулярное обновление инструментов через mise up и явно покажет, что поддержки других версий нет. А lockfile при этом будет содержать конкретную версию "1.2.3", заданную последним вызовом mise up, что обеспечит использование именно этой версии всеми разработчиками и на CI. Для использования lockfile нужно добавить в mise.toml в разделе [settings] опцию lockfile = true, плюс вручную создать пустой lockfile: touch mise.lock - и я рекомендую делать это во всех проектах.

Ещё полезные нюансы/фичи:

  • Нужную версию инструмента лучше всегда указывать без префикса "v".

  • Если одна версия инструмента нужна разным проектам то она устанавливается однократно.

  • Есть возможность использовать локально модифицированную версию инструмента вместо стандартной.

  • При установке инструмента проверяются подписи/контрольные суммы (если это поддерживается бэкендом, через который устанавливается данный инструмент).

  • Многие инструменты можно установить через несколько разных бэкендов, поэтому лучше придерживаться какого-то общего приоритета при выборе бэкенда, чтобы не создавать лишний бардак и не устанавливать одну и ту же версию одного инструмента несколько раз.

  • (Актуально на 2026-02-22, надеюсь это поправят в будущем.) При использовании lockfile, если не запускать вручную mise lock после каждого добавления/обновления инструментов, этот lockfile может внезапно изменяться во время mise install (из-за того, что нужный инструмент не был ранее установлен локально или установка выполняется на другой ОС). Это может создавать проблемы на CI (если там проверяется что рабочий каталог git не dirty) плюс замусоривать не связанные с обновлением mise PR-ы других членов команды. На CI это проще всего решить добавив git reset --hard после mise install.

Переменные окружения и секреты

  • Адекватный, интуитивно ожидаемый приоритет установки значений переменных.

  • Можно задавать значения новых переменных используя значения ранее заданных переменных.

  • Можно задавать значения переменных используя вывод внешней команды.

  • Загрузка переменных из файлов в формате dotenv.

  • Загрузка переменных экспортируемых sh-скриптом.

  • Полноценный язык шаблонов позволяет гибко трансформировать значения переменных.

  • Отложенная установка переменных позволяет переопределять в mise.local.toml промежуточные переменные (напр. $PORT), и использовать переопределённые значения при установке "отложенных" переменных в mise.toml (напр. $URL содержащая внутри $PORT).

  • Установка переменных для секретов, зашифрованных как непосредственно в конфиге mise (утилитой age), так и в удалённых сервисах (Vault, AWS KMS/SM, Azure, GCP, 1Password, …).

Задачи

Задачи можно задавать прямо в TOML конфиге mise (удобно для однострочных команд, приемлемо для двух-трёх строчных) и в отдельных скриптах (для более многострочных задач). Причём даже внутри конфига задача не обязательно должна быть шелл-командой, это вполне может быть код на python и т.п.

Если в проекте уже есть что-то вроде каталога со скриптами для типовых задач (напр. ./scripts/build, ./scripts/test, …), то mise сможет подхватить эти скрипты как свои задачи. А для того, чтобы в этих задачах воспользоваться дополнительными фичами mise (задать описание, alias, переменные окружения, зависимости, версии нужных инструментов, автодополнение флагов/аргументов) достаточно добавить в начале скрипта комментарии #MISE … и #USAGE ….

Для новых задач, не важно они в конфиге mise или отдельных скриптах, помимо автодополнения флагов/аргументов при запуске, флаги/аргументы будут автоматически разобраны и их значения будут доступны в переменных окружения $usage_… - это упрощает реализацию задач.

Для максимальной ленивости удобно добавить в шелл alias mr='mise run' плюс самую часто используемую задачу проекта указать как "default", тогда она будет запускаться по mr.

Ещё полезные фичи:

  • Просмотр названий и описаний всех задач.

  • Флаги и аргументы для задач с поддержкой --help и автодополнения в шелле.

  • Настройка версий инструментов, переменных окружения и рабочего каталога для отдельных задач.

  • Зависимости между задачами.

  • Параллельное выполнение задач.

  • Пропуск задачи если конкретные файлы не изменились с предыдущего запуска этой задачи.

  • Автоматический запуск задач (через mise watch) при изменении конкретных файлов.

Разное

mise версионируется по CalVer, и релизы очень частые (почти каждый день). Обычно они совместимы и острой необходимости обновляться нет, но у меня уже выработалась привычка каждый день плюс к обновлению ОС запускать mise self-update для обновления mise плюс mise up для обновления всех установленных через mise глобальных утилит. В случае необходимости форсировать обновление mise у всех разработчиков проекта в конфиге mise можно указать минимально необходимую версию mise.

Есть поддержка монорепо.

Ваша команда может даже не подозревать, что вы используете mise при работе с проектом. Для этого достаточно написать личный конфиг для проекта в mise.local.toml и добавить игнорирование этого файла в ~/.gitconfig.

Для отладки проблем с mise запустите mise doctor.

Примеры mise.toml для проектов разных типов: утилита на Go, библиотека на Go, плагин для KDE Plasma на JavaScript, плагин для Neovim на Lua.

Комментарии (28)


  1. anaxita
    22.02.2026 11:56

    Ещё один швейцарский нож который зашёл одному разработчику и теперь он думает, что все хотят ещё одну зависимость вместо мейкфайла?


    1. powerman Автор
      22.02.2026 11:56

      Ну, выбор не велик - либо "ещё одна зависимость" либо бардак. Makefile не поставит используемые утилиты нужных проекту версий, не задаст переменные окружения и секреты проекта. Задачи описать в Makefile можно, но, будем откровенны, это не особо удобно, и это не основная задача make, а скорее misuse. В результате плюс к Makefile появляются .env или env.sh и дополнительные инструкции в README описывающие какие утилиты нужно самостоятельно установить для работы с проектом. Дальше версии этих утилит у разных разработчиков и на CI разъезжаются, что периодически создаёт странные проблемы. Утилиты, которые призваны эти проблемы порешать (asdf, direnv, taskfile, …) решают только часть да ещё и сами новые проблемы привносят. На этом фоне mise приятно выделяется. Но если не вникать в детали - то да, будет ровно такое впечатление, как Вы сказали.


      1. action52champion
        22.02.2026 11:56

        Вообще обычно для подобных случаев использутеся связка из:

        • require-dev блока в композере, npm и т.п., чтобы ставить зависимости нужные для разработки только если они нужны

        • .env все же более универсальный механизм и позволяет не хранить все секреты в одном месте

        Что касается разъезжающихся версий у разрабов - если человек по каким-то причинам не обновляет инструментарий, ему утилиты не помогут.

        Но может ваша утилита и взлетит, питоновский uv вон набирает популярность, хотя его смысл вообще мне не понятен.


        1. powerman Автор
          22.02.2026 11:56

          В том-то и дело, что упомянутые в статье задачи нужно решать на всех проектах, и при этом полно решений, которые как-то эти задачи решают - но обычно они это делают не очень хорошо, ограничено или специфичным для конкретного языка способом. Например, для того же .env до сих пор нет единого стандарта, что в нём можно делать более сложного чем A=5. Ключевое отличие mise как раз в том, что она делает сразу всё и делает это правильно и очень гибко. Т.е. на сегодня это объективно лучшее решение, на которое действительно есть смысл перейти.

          Что касается разъезжающихся версий у разрабов - если человек по каким-то причинам не обновляет инструментарий, ему утилиты не помогут.

          Во-первых, утилиты помогут - об этом и речь в статье. А во-вторых тупым обновлением инструментария можно обойтись если работаешь над единственным проектом. А если проектов несколько, то у всех будут свои требования к инструментарию, и соблюдать их без помощи таких утилит будет крайне сложно.


        1. rSedoy
          22.02.2026 11:56

          питоновский uv вон набирает популярность, хотя его смысл вообще мне не понятен.

          а смысл poetry, pipenv и т.п. понятен? тот же package manager, но с очень быстрым вычислением зависимостей + куча фич, которые нужны в управлении проектом.


          1. economist75
            22.02.2026 11:56

            uv это ещё и менеджер "всего остального что есть в огромном мире python" с uv run *.py и uv python install


            1. thethee
              22.02.2026 11:56

              It just works (c) (tm)

              Причем без шуток. Сидишь на чистом pip - мучаешься с зависимостями, которые обновляются неизвестно когда, причем якобы минорный багфикс, но меняется поведение, пересаживаешься на conda - мучаешься с тем насколько долго это работает, все ещё требует активации, и dependency hell продолжается, потому что тут нужен conda forge, там какой то другой сборник пакетов. Перешёл на uv - just works. Хочешь поставить чисто torch из репы Nvidia - пожалуйста, хочешь поставить все "как нибудь" - окей, вот тебе через 0.1 секунду ошибка несовместимости, причем конкретная и иногда с путями решения.

              Кажется что source .venv/bin/activate это всего несколько символов, но насколько же удобнее без этого, просто uv run из нужной директории и все работает. Причем это обратно совместимо, если нужен чистый venv - он доступен.

              Я через uv иногда просто для старых проектов venv собираю потому что он и с requirements.txt работает и позволяет получить преимущество удобства/скорости в установке и потом все равно uv run работает. Даже залочить зависимости можно без pyproject.toml, если мне не изменяет память.

              Это инструмент который помимо общего улучшения приносит кучу мелких удобств. Это как работа с проектом без git и с git. Абсолютно другой уровень, хотя идея простая. Просто "правильно" реализована.


  1. iamkisly
    22.02.2026 11:56

    mise заменяет все остальные аналогичные утилиты т.к. содержит весь необходимый функционал

    Какие утилиты, какой функционал? Введения о том какую проблему оно решает нет, зато дохрена рассказов как это настроить.


    1. powerman Автор
      22.02.2026 11:56

      Честно говоря, я просто не хотел превращать статью в перечисление тучи заменяемых утилит с описанием проблем каждой. Но, если хотите, вот краткий список:

      • Установка/обновление инструментов: asdf, aqua, nvm, pyenv, rbenv, go get -tool, …

      • Настройка конфигурации: direnv, dotenv, env.sh, …

      • Выполнение задач проекта: make, taskfile, just, mage, ./scripts/test, …

      И это только для основного функционала. А помимо этого есть ещё поддержка секретов, автозапуск задач при изменении файлов - и для этого тоже есть существующие утилиты, которые заменяет mise.


      1. iamkisly
        22.02.2026 11:56

        Так в этом то вся соль. Вы должны были мотивировать как-то отказ от простых утилит, большинство из которых успешно следуют unix way и де-факто являются стандартами в своей области. Но вы этого не сделали.. поэтому статья читается как "зачем.. зачем.. пролистать, минус"

        Что касается концепции "швейцарского ножа", то имхо она в принципе своём ущербна. Утилита должна исполнять только свою маленькую роль в большом оркестре, а не пытаться быть этим самым оркестром. Это та атомарность, которая позволяет поддерживать их и в любой момент заменить каждый из компонентов на альтернативу.


        1. powerman Автор
          22.02.2026 11:56

          Я сам люблю unix way, но иногда ради юзабилити приходится от него отходить, и это нормально - unix way это не абсолютный идеал для вообще всех приложений.

          Впрочем, лично для меня не очевидно, что в случае mise действительно необходимо в одной утилите объединить весь этот функционал. И меня немного беспокоит дальнейшее расширение её функционала. Именно поэтому я в статье не писал, что mise идеальна, но я писал, что она задала минимальную планку для будущих утилит в этом классе - потому что mise первая, кто действительно хорошо решил все три задачи.

          Вообще, часть функционала автор mise реализует в отдельных утилитах: usage, fnox, pitchfork; равно как и использует чужие утилиты: watchexec. Ну т.е. про unix way он в курсе, и для объединения трех разных функций в mise возможно есть веские причины.

          Вы должны были мотивировать как-то отказ от простых утилит

          Это не совсем так. Лично я до mise никакими из этих утилит не пользовался. Пытался, но довольно быстро обнаруживал серьёзные проблемы, из-за чего отказывался от них и возвращался к самопальным решениям (env.sh, скрипты, tools.go). mise - первая утилита без серьёзных проблем, из всех что я видел. Поэтому статья мотивирует не отказ от других утилит, а использование именно mise. Более того, по этой причине я ничего не написал про совместимость с другими утилитами (в основном asdf и direnv), которую старается поддерживать mise для упрощения миграции.


  1. asoneofus
    22.02.2026 11:56

    Для чего эта куча букывок?

    Для тооо чтобы не читать Readme? )))


  1. albalyu
    22.02.2026 11:56

    mise — утилита, необходимая каждому разработчику и в каждом проекте

    Это Вы провели опрос каждого разработчика на планете? Или как?


  1. Hlorabi
    22.02.2026 11:56

    Write programs that do one thing and do it well.


  1. oeditus
    22.02.2026 11:56

    mise соответствует типовым ожиданиям от современной утилиты:
      • Написана на Rust

    У меня примерно миллион ожиданий от каждой современной утилиты, но уж язык, на котором она написана — меня точно не волнует.

    Я пишу постоянно на трех языках, спорадически — еще на пяти, у каждого свои разной степени игривости танцы с бубном по настройке окружения, но asdf меня лично не подводил никогда; буквально, не было случая, чтобы я столкнулся с «чёрт, не получается».

    Чем mise лучше? Столько букв, а ответа на этот очевидный вопрос нет.


    1. powerman Автор
      22.02.2026 11:56

      Есть коротко: безопаснее, быстрее, удобнее, устанавливает больше инструментов, плюс поддержка переменных окружения и задач. Изначально mise разрабатывалась как drop-in replacement именно для asdf (в то время mise называлась rtx, если не путаю).

      Вот детальное сравнение с asdf: https://mise.jdx.dev/dev-tools/comparison-to-asdf.html


      1. oeditus
        22.02.2026 11:56

        Я читал этот текст, когда мне в прошлый раз повстречался миссионер дислектических мышей. Вот мои ¢2:

        • безопаснее — актуально для людей, которые устанавливают какую-то совсем экзотику, но ленятся пробежать глазами шеллскрипт;

        • быстрее — это смешно, пардон, когда речь идет про доли секунды и команду выполняемую раз в год;

        • удобнее — вкусовщина, я с asdf 15 лет живу (а кота этого впервые вижу);

        • устанавливает больше инструментов — очевидный минус, я не хочу, чтобы мне кто-то зачем-то устанавливал больше каких-то там еще инструментов;

        • поддержка переменных окружения — три раза нет, ну может быть, иногда удобно, хотя для этого тоже есть миллион инструментов;

        • поддержка переменных задач — это я не понял, что такое.

        В общем, неангажированный вывод для тех кто сюда забредет: если у вас уже asdf, вам вряд ли понравится, если нет — лучше, наверное, начинать прямо с mise.


        1. powerman Автор
          22.02.2026 11:56

          Не совсем так. Учитывая, что в большинстве случаев asdf заменяется на mise как drop-in, т.е. просто вместо команды asdf выполняете mise с теми же аргументами, то все эти плюсы начинают выглядеть намного интереснее даже если пока нет понимания зачем они лично Вам - просто потому, что их можно получить практически бесплатно.

          По скорости - команда выполняется не раз в год, а регулярно. В случае asdf - это запуск любого инструмента, т.к. они все запускаются через shims. В старом asdf на шелле это тормозило вообще неприлично, в новом asdf на go уже приемлемо, но mise всё-равно быстрее. Но да, есть люди которых такие задержки бесят, а есть те, кто их не замечает.

          Безопасность экосистемы asdf - это реальная проблема, потому что авторы asdf-плагинов это не авторы самой asdf и не авторы нужной утилиты, а абсолютно случайные товарищи, которые получают возможность выполнить любой шелл-код на вашем компе. Эти товарищи - совершенно лишние в цепочке доверия поставкам.

          Больше инструментов сами по себе не установятся, просто через mise есть возможность установить такие инструменты, которые asdf устанавливать не умеет.

          Миллион инструментов для работы с переменными окружения страдают от кучи разных проблем, которых нет в mise.


  1. Robanni-resu
    22.02.2026 11:56

    Прочитал статью, прочитал комменты, ладно, продано)

    Пока не смотрел репо, но как понял штука классная когда у тебя несколько стеков и несколько рабочих девайсов.

    Так же онбординг упростить очень сильно с виду.

    Очередную тулзу учить конечно в падлу, но с виду оно того стоит.

    Вопрос к автору, насколько убервафля применима для раскати ci/cd ? Есть примеры ?


    1. powerman Автор
      22.02.2026 11:56

      Интеграция с CI обычно в одну-две строки в конфиге CI: https://mise.jdx.dev/continuous-integration.html

      Что до CD - если напишете логику деплоя в задаче "deploy", то на CI деплой запустится командой mise run deploy. В смысле, ничего именно mise-специфичного в CD нет.


  1. Robanni-resu
    22.02.2026 11:56

    По поводу написания, воды ОЧЕНЬ много, в моменте появляется вайб tldr. На хабре вообще хочется видеть перед статьей сноску небольшую сверхсжатую с основной информацией.


  1. IlyaBIS
    22.02.2026 11:56

    Есть nix-shell, который даёт гарантированную воспроизводимость, но имеется более крутая кривая обучения:

    https://www.cecg.io/blog/nix-shell-vs-mise

    Стоит посмотреть в сторону nix/NixOS, если занимаетесь проектами со сложными зависимостями, есть необходимость в гарантированной воспроизводимости и не пугает кривая обучения языка nix.


    1. powerman Автор
      22.02.2026 11:56

      Nix реально нужен в проектах со сложными зависимостями от уровня C (системные библиотеки, компилятор C, etc.) - и через mise это контролировать невозможно. Но и там в плане юзабилити есть смысл использовать mise (в т.ч. и потому, что nix не особо позволяет управлять переменными окружения/секретами и задачами проекта). Просто запускать mise в этом случае нужно будет внутри nix-shell, ну и плюс можно будет упростить конфиг nix, ограничив его исключительно тем, что нельзя устанавливать/контролировать через mise.


      1. IlyaBIS
        22.02.2026 11:56

        в т.ч. и потому, что nix не особо позволяет управлять переменными окружения/секретами и задачами проекта

        Можешь по подробнее расписать?

        Вроде для секретов в nix есть Agenix, Sops-nix, Git-crypt.


        1. powerman Автор
          22.02.2026 11:56

          Возьмём типовой пример: разработчику локально нужно иметь возможность переопределить номер порта, который используется в url нужной проекту.

          Вот как ИИ предлагает решать эту задачу на nix:

          • shell.nix

            { pkgs ? import <nixpkgs> {}
            , port ? 8080
            }:
            
            let
              url = "http://localhost:${toString port}";
            in
            pkgs.mkShell {
              shellHook = ''
                export PORT=${toString port}
                export URL=${url}
              '';
            }
          • shell.local.nix

            let
              base = import ./shell.nix;
            in
            base {
              port = 9090;
            }

          А вот как это делается на mise:

          • mise.toml

            [env]
            PORT = '8080'
            URL = { value = 'http://localhost:$PORT', tools = true }
          • mise.local.toml

            [env]
            PORT = '9090'

          Поддержки работы с секретам в nix вообще нет, предлагается запускать утилиту для расшировки (age/sops/gpg/etc.) и как-то подставлять её вывод в значение переменной окружения.

          Те простыни, которые ИИ показывает в формате nix для того, чтобы реализовать запуск задачи "test" при которой выполнится команда go test -race ./... мне сюда даже копипастить страшно. Ну т.е. nix формально это может, но это настолько больно и длинно, что проще (и рекомендуется) вызывать стороннюю запускалку задач вроде make/taskfile/just/свой скрипт или собственно mise.


          1. IlyaBIS
            22.02.2026 11:56

            Т.е. работа с переменными окружения в nix сложнее чем в mise из-за функционального языка nix, а работа с секретами упирается в лишние телодвижения с Agenix/Sops-nix/Git-crypt?


            1. powerman Автор
              22.02.2026 11:56

              Т.е. nix просто не предназначен для этого, он решает другие проблемы, которые mise решить не в состоянии. Да, в nix ногами можно запихать и такое тоже, но это будет больно и неудобно. Те проблемы, которые решает mise, намного удобнее решать именно через mise, в т.ч. используя его совместно с nix-shell если нужен контроль окружения уровня C, который mise реализовать не в состоянии.


  1. denisemenov
    22.02.2026 11:56

    То, что в других утилитах работало странно или не поддерживалось - в mise сделано правильно!

    У нас в клубе принято джентльменам верить на слово!