
前言
前阵子换了新电脑,我在整理本地开发环境时,看到一堆需要重新装的,顿时感觉好麻烦。想着都过去这么久了,应该有工具可以做到统一管理,实现快速安装、更新、切换版本吧。
经过一番查找后,找到了mise这个东西,只需要简单的一句命令就能安装java、node、redis、go等工具,而且还支持对这些工具做统一管理(更新、删除),支持三大主流平台(macOS/Windows/Linux)
命令行始终不方便,于是我萌生了一个做GUI的想法,花了亿点时间用Flutter把它开发出来了,欢迎各位有需要的开发者阅读本文。
项目地址

主要解决什么问题?
对于我这种经常切换项目的人来说,纯命令行总感觉不是很直观。
比如我想知道:
- 当前电脑装了哪些工具?
- node、python、java、go这些工具当前用的是哪个版本?
- 哪些项目里的
mise.toml覆盖了全局版本? - 我现在执行安装、切换、卸载,到底会影响哪些文件?
- 上一次通过界面执行命令失败了,具体错误是什么?
这些事情,命令行当然都能查,但需要来回敲命令,有时候还要打开配置文件对比。Mise GUI想做的就是把这些常用信息集中到一个界面里,让本地环境管理更直观一点。
实现效果
目前主要做了4个功能:
- 环境总览
- 工具版本
- 项目覆盖
- 配置管理
环境总览
总览页主要用于快速查看当前机器的开发环境状态。
这里会展示当前系统、已安装工具数量、项目覆盖情况、mise版本以及最近通过界面执行过的操作。

工具版本
工具模块是本软件的核心功能之一。
它会展示每个工具的当前版本和最新版本,比如Flutter、Go、Java、Python等。

点进某个工具后,可以查看这个工具的已安装版本、远端可安装版本、当前版本来源,以及这个版本会影响哪些项目。
这里还做了一些操作入口,比如:
- 安装新版本
- 切换当前版本
- 升级到推荐版本
- 卸载工具
- 查看实际命令
这些操作不会直接执行,每次都会先进入命令预览。
安装新工具
安装工具时,只需要输入工具名和版本号。
如果工具支持远端版本查询,界面会把可选版本列出来,方便直接选择。

确认后不会立刻执行,而是先展示即将运行的命令,例如:
mise install redis@8.6.2
mise use --global redis@8.6.2
同时也会提示这次操作会影响哪些文件、影响范围是什么、可能有什么风险。
这个设计主要是为了避免“点一下按钮,背后偷偷执行了一堆命令”的情况。毕竟本地开发环境这种东西,改之前最好知道自己在改什么。
项目覆盖
mise支持项目级配置,比如在项目目录里放一个mise.toml,就可以指定这个项目使用的工具版本。
这个很好用,但是项目一多之后,就很容易忘记哪个项目覆盖了全局版本。
所以我做了一个项目覆盖页面。

你可以添加多个扫描目录,软件会递归查找里面的mise.toml,然后只展示和全局版本存在差异的项目。
比如全局node是20,但是某个项目指定了18,那么这里就能很直观地看出来。
比如:当你想排查“为什么这个项目跑出来的node版本和我想的不一样”,这个功能就派上用场了。
配置管理
配置页主要是用来查看和编辑全局配置以及项目配置。

目前支持:
- 查看全局配置文件:
~/.config/mise/config.toml - 选择某个项目查看项目级
mise.toml - 编辑配置文件
- 保存前查看diff差异
- 配置文件变化后自动刷新
此处我特意加了保存前的差异预览。因为配置文件不像普通表单,改错一个版本号或者删错一行,可能就会影响很多项目。
技术栈
这个项目是用Flutter写的,主要技术栈如下:
- Flutter Desktop:用于构建跨平台桌面应用
- Dart:主要开发语言
- Riverpod:状态管理
- GoRouter:页面路由
- file_selector:选择扫描目录
- Process.run:调用本机mise命令
整体代码结构大概是这样:
lib/
app/ # 应用启动、路由、主题和外壳
features/
dashboard/ # 环境总览
tools/ # 工具版本、安装、升级、卸载
projects/ # 扫描目录和项目覆盖
config/ # 全局与项目配置管理
repositories/ # 页面数据聚合
services/ # mise CLI、配置、历史、更新等底层服务
shared/ui/ # 通用面板、状态、对话框和预览组件
我没有把命令执行逻辑直接写在页面里,而是拆成了:
- Page:负责界面展示和用户交互
- Provider:负责页面状态
- Repository:负责聚合页面需要的数据
- Service:负责调用mise、读取配置、记录历史等底层逻辑
这样做的好处是后面要扩展功能时,不至于所有逻辑都堆在页面文件里。
和mise CLI的交互
这个软件本质上不是替代mise,而是给mise套了一层图形界面。
所以核心逻辑还是调用本机的mise CLI,例如:
mise --version
mise ls --json
mise current
mise outdated
mise ls-remote --json node
mise install node@20
mise use --global node@20
Flutter里通过Process.run来执行这些命令,然后把输出结果解析成界面需要的数据。
这里有个比较麻烦的点:桌面应用启动时拿到的环境变量,不一定和终端里的环境变量完全一致。
比如你在终端里能执行mise,但GUI应用直接执行可能找不到。
所以我在这里做了一些兜底:
- 优先读取常见路径,比如
/opt/homebrew/bin/mise、/usr/local/bin/mise - 尝试读取shell环境
- 如果仍然找不到,就进入安装引导页
- 给出当前系统对应的安装命令
为什么选择Flutter
这类工具其实用很多技术都能做,比如Electron、Tauri、Qt、SwiftUI等。
最后选择Flutter,主要有几个原因:
- 我对Flutter比较熟悉
- 桌面端支持macOS/Windows/Linux
- UI写起来比较直接
- 状态管理和组件拆分比较适合做这种工具型应用
- 最终打包出来是一个桌面应用,使用门槛比较低
用Flutter写的时候,也遇到了一些坑,比如:系统文件选择、macOS打包、公证、不同平台的命令执行差异,这些都需要额外处理。
整体写下来,这种小型桌面工具开发体验还是很不错的。
如何使用
目前可以直接去Release页面下载对应系统的版本:
https://github.com/likaia/mise_gui/releases
如果电脑里还没有安装mise,软件启动后会提示安装命令。
也可以先手动安装:
# macOS
brew install mise
# Windows
winget install jdx.mise
# Linux
curl https://mise.run | sh
如果你想本地运行源码:
git clone https://github.com/likaia/mise_gui.git
cd mise_gui
flutter pub get
flutter run -d macos
其他平台可以把运行目标换成:
flutter run -d linux
flutter run -d windows
写在最后
这个软件算是我给自己做的一个小工具,也是我第一个用Flutter作为开发语言写的开源项目。一开始只是因为换电脑时嫌重新配置环境太麻烦,后来越写越觉得这种东西挺适合做成可视化工具。
至此,文章就分享完毕了。
我是神奇的程序员,一位前端开发工程师。
如果你对我感兴趣,请移步我的个人网站,进一步了解。
- 文中如有错误,欢迎在评论区指正,如果这篇文章帮到了你,欢迎点赞和关注😊
- 本文首发于神奇的程序员公众号,未经许可禁止转载💌
评论区