FlClash:45K Stars 的多平台代理客户端,如何用 Flutter + Rust + Go 三语言拼出 ClashMeta 桌面/手机体验
posts posts 2026-07-13T03:03:54+08:00FlClash 是 ClashMeta 内核的多平台代理客户端,Flutter + Rust + Go 三语言拼装,GPL-3.0、45K Stars。本文拆开它的三层架构(lib/core 事件流、lib/manager 平台集成、lib/plugins 原生桥)、setup.dart 构建脚本、Android NDK/GCC/Inno Setup 工具链与 v0.8.94 CHANGELOG 的关键迭代。技术笔记Flutter, Dart, Clash, Rust, 代理FlClash:45K Stars 的多平台代理客户端,如何用 Flutter + Rust + Go 三语言拼出 ClashMeta 桌面/手机体验
§1 先给判断
FlClash 是一个把「Clash 内核 + Flutter UI + 跨平台系统能力」三件事缝在一起的多平台代理客户端,45K Stars、GPL-3.0、最近一次发布 v0.8.94(2026-07-11)。它值得专门拆开看的工程原因有三条:
- 三语言拼装:UI 层 Flutter(Dart),桥层 Rust(
rust_api包),内核层 Go(Clash Meta 编译产物)。Flutter 跨平台 + Rust 系统调用 + Go 高并发代理服务器——每一种语言都被钉在它最擅长的事情上。 - 四端覆盖 + 体验一致:Android / Windows / macOS / Linux 共用同一份 Dart UI,配合 Material You 动态色与平台自适应布局,把「同代码跨端」做到了代理类工具里罕见的完成度。
- 平台集成深度:Android Quick Tile(无障碍瓷砖开关)、Android 主进程拆分、Windows IPC 优化、Windows arm64 支持、macOS 性能修复、Linux tray 集成——每个平台的「反人性默认」都被单独处理过。
仓库地址:https://github.com/chen08209/FlClash。最近一年的发布节奏稳定在 6-10 周一个版本,每个版本都列出 5-10 条修复+优化项(CHANGELOG 见 CHANGELOG.md)。
文章主轴:拆开 FlClash 的三层架构(lib/core 事件流、lib/plugins 原生桥、lib/manager 平台集成)+ setup.dart 构建脚本对工具链的统一调用,给一份「Flutter 想碰系统能力时,桥层到底要堆多少」的真实样本。
§2 仓库坐标:放在代理客户端谱系里看
代理客户端项目大致分四类:
| 类型 | 代表 | 核心能力 | FlClash 位置 |
|---|---|---|---|
| 原生单平台 | Clash for Windows (CFW)、ClashX | 单平台极致体验 | 不选 |
| 跨平台 Go UI | Clash Verge、Clash Meta for Android | Go 跨平台但 UI 受限 | 部分重叠 |
| Flutter 跨平台 | FlClash、Hiddify | UI 体验优先 | 选这条 |
| 命令行内核 | clash-meta 内核 | 只负责代理流量 | 不选 |
FlClash 在「Flutter 跨平台代理」赛道里是 Stars 数最高的——它把「代理客户端」从命令行工具升级成「和 Telegram / Spotify 一类的日用软件」的设计语言。这个定位选择决定了它必须解决三件事:
- 跨端 UI 一致(Flutter 自带)
- 系统能力集成(VPN 接口、Tray、Quick Tile、开机启动、热键)
- 内核与 UI 的双向通信(Flutter 不能直接控制 Go 服务)
下面逐层拆。
§3 顶层目录:三层 + 一个构建器 + 一个文档
主目录(main 分支):
FlClash/
├── android/ # Android 工程
├── linux/ # Linux 打包脚本与 .deb 描述
├── macos/ # macOS 工程
├── windows/ # Windows 工程(Inno Setup 脚本)
├── lib/ # Flutter Dart 代码
│ ├── application.dart
│ ├── main.dart
│ ├── state.dart # 全局 Riverpod 状态根
│ ├── common/ # 通用工具
│ ├── core/ # 与 Clash 内核的桥接层
│ ├── database/ # 本地存储
│ ├── enum/
│ ├── features/ # 业务模块
│ ├── l10n/ # 国际化字符串
│ ├── manager/ # 平台能力封装(VPN/Tray/Hotkey/Window/...)
│ ├── models/ # 数据模型
│ ├── pages/ # 页面
│ ├── plugins/ # 自研 Flutter 插件(桌面/移动)
│ ├── providers/ # Riverpod 状态树
│ ├── views/ # 视图组件
│ └── widgets/ # 复用控件
├── plugins/ # Flutter 插件源码
│ ├── proxy/ # 平台代理 / VPN 接入
│ └── wifi_ssid/ # Wi-Fi SSID 信息
├── core/ # ClashMeta 内核子模块
├── services/ # 其他服务模块
├── tool/ # 构建辅助工具
├── arb/ # 翻译文件
├── assets/ # 图标、字体、动画
├── assets_source/ # 源资源(设计稿)
├── test/
├── snapshots/ # README 演示动图
├── pubspec.yaml # Flutter 依赖
├── pubspec.lock
├── setup.dart # 统一构建脚本(Dart 写的 build entry)
├── Makefile # 包装 setup.dart
├── AGENTS.md / CLAUDE.md # AI 协作约定
├── CHANGELOG.md
├── analysis_options.yaml
├── distribute_options.yaml
└── README.md / README_zh_CN.md注:plugins/ 下的 proxy/ 与 wifi_ssid/ 是自研插件源码路径,对应 pubspec.yaml 里的 proxy: { path: plugins/proxy } 和 wifi_ssid: { path: plugins/wifi_ssid }。其它依赖(如 tray_manager、launch_at_startup、window_manager、yaml_writer)是 fork 自作者的私有仓库,引用 GitHub 而非 pub.dev。
§4 lib/core:与 Clash 内核通信的桥层
lib/core/ 下的文件结构(GitHub API 列出):
core/
├── clash.dart
├── controller.dart
├── core.dart
├── event.dart
├── interface.dart
├── lib.dart
├── service.dart
└── transport.dart这八个文件几乎可以一对一映射到 Clash 内核的对外能力面:
| 文件 | 推断职责 |
|---|---|
core.dart | 核心入口(启动、关闭、生命周期) |
controller.dart | 控制器(订阅切换、模式切换) |
event.dart | 事件流定义 |
interface.dart | 抽象接口 |
lib.dart | 库管理(订阅配置加载) |
service.dart | 服务(系统代理、TUN、HTTP) |
transport.dart | 传输层封装(IPC / 进程间通信) |
clash.dart | 高层 API 聚合 |
pubspec.yaml 里同时存在 proxy: { path: plugins/proxy } 和 rust_api 引用——main.dart 顶部这两行是入口:
import 'package:rust_api/rust_api.dart';
import 'package:fl_clash/state.dart';
// ...
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
try {
if (system.isDesktop) {
await RustLib.init(); // ← Rust 桥初始化(仅桌面端)
}
final version = await system.version;
final container = await globalState.init(version);
HttpOverrides.global = FlClashHttpOverrides();
runApp(
UncontrolledProviderScope(
container: container,
child: const Application(),
),
);
} catch (e, s) {
runApp(
MaterialApp(
home: InitErrorScreen(error: e, stack: s),
),
);
}
}值得专门提的三点:
RustLib.init()仅在桌面端调用——移动端(Android/iOS)用平台 VPN API 直接接管流量,不需要 Rust 桥。HttpOverrides.global = FlClashHttpOverrides()——Dart 的 HTTP 客户端被代理覆盖,这是 Clash 类工具让应用内流量也走代理的标准做法。- 错误兜底走
InitErrorScreen——启动失败时不白屏,直接展示错误页。这对面向普通用户的客户端是基本礼貌。
§5 lib/manager:13 个 Manager 拼出平台能力全景
lib/manager/ 目录下:
manager/
├── android_manager.dart
├── app_manager.dart
├── connectivity_manager.dart
├── core_manager.dart # ← Clash 内核状态、订阅、流量统计
├── hotkey_manager.dart
├── manager.dart # ← 总入口
├── proxy_manager.dart
├── status_manager.dart
├── theme_manager.dart
├── tile_manager.dart # ← Android Quick Tile
├── tray_manager.dart # ← 系统托盘
├── vpn_manager.dart # ← VPN 接口封装
└── window_manager.dart # ← 桌面窗口管理每一类 Manager 都是把平台能力收编为可被 Riverpod 订阅的状态源。举三个例子说明这种分层的设计意图:
§5.1 vpn_manager.dart
代理客户端在 Android 上必须实现 VpnService——这是 Android 系统级 VPN 接口。vpn_manager.dart 负责:
- 创建
VpnService.Builder - 写入 TUN 设备配置(地址、DNS、路由)
- 与 Go 内核进程建立 IPC
- 启动/停止生命周期管理
§5.2 tile_manager.dart(Android Quick Tile)
CHANGELOG 多次提到「optimize android tile service」「fix android tile service」——这是 Android 7.0+ 的通知栏 Quick Settings Tile(无障碍瓷砖)。FlClash 让用户下拉通知栏点一下瓷砖就能开关代理,避免每次打开 App。
这是一个看似小、实则要解决不少平台版本碎片化问题的能力:每个 Android 厂商 ROM 对 Tile API 行为有微差异。
§5.3 tray_manager.dart
桌面端(Windows/macOS/Linux)都要系统托盘。FlClash 用作者 fork 的 tray_manager(pubspec.yaml 里直接引用 GitHub)——fork 的原因是官方版对 Linux 的 libayatana-appindicator3 支持不够好。
CHANGELOG 多次提到「optimize windows tray auto hide」「fix windows tray」「optimize tray auto hide」——可见托盘这一块也是持续打磨的对象。
§6 lib/plugins:自研 Flutter 插件
lib/plugins/ 目录只有两个:
plugins/
├── app.dart
├── service.dart
└── tile.dart这是 Android 端 Flutter plugin 的 Dart 入口(service.dart 监听 Android Service,tile.dart 对接 Quick Tile API)。对应的 plugins/ 仓库里放平台侧 Kotlin/Java 代码(不在 lib/ 下,但 pubspec.yaml 通过 proxy: { path: plugins/proxy } 引用)。
第三个自研能力是 wifi_ssid——读取当前 Wi-Fi SSID 用于判断「在家/在外」自动切换配置。这是代理类工具里常见但实现细节复杂的场景(Android 8+ 对 Wi-Fi 读取有限制)。
§7 lib/common:43 个工具文件积累
lib/common/ 目录 43 个文件(截取部分):
common/
├── app_localizations.dart # 国际化
├── archive.dart # 压缩/解压
├── cache.dart
├── color.dart # Material You 取色
├── common.dart
├── compute.dart # Dart isolate 包装
├── constant.dart
├── context.dart
├── converter.dart
├── datetime.dart
├── dav_client.dart # WebDAV 客户端(同步用)
├── file.dart
├── fixed.dart
├── function.dart
├── future.dart
├── http.dart
├── icons.dart
├── indexing.dart # fractional indexing(拖拽排序)
├── input_limits.dart
├── iterable.dart
├── javascript.dart # flutter_js 封装
├── keyboard.dart
├── launch.dart # 启动外部程序
├── link.dart
├── lock.dart
├── measure.dart
├── migration.dart # 数据迁移
├── mixin.dart
├── navigation.dart
├── navigator.dart
├── network.dart
├── num.dart
├── package.dart
├── path.dart
├── permission.dart
├── picker.dart # file_picker 封装
├── preferences.dart # shared_preferences 封装
└── ...43 个工具文件是个值得提的信号:FlClash 已经不是「一个写 UI 的项目」,而是「一个有完整工具链 + 跨平台抽象的项目」。compute.dart(异步执行)、migration.dart(老版本数据迁移)、dav_client.dart(云同步)、javascript.dart(规则脚本引擎)——每个文件背后都是一段要处理的真实复杂度。
§8 lib/features:业务模块边界
lib/features/ 目录下:
features/
├── features.dart # 总入口
└── overwrite/ # 「覆写」功能
├── overwrite.dart
└── rule.dartFlClash v0.8.93 提到「Support custom overwrite」——这是 Clash 类工具的高级玩法:用户写一段 JavaScript(在 Web 端常见),在流量被代理之前修改请求/响应。overwrite/ 目录就是这部分规则的模型和实现入口。
§9 setup.dart:跨端构建的统一入口
FlClash 没有用 Flutter 官方的 flutter build 直接打全部平台——它写了自己的 setup.dart(Dart 脚本)做平台特定的准备工作,再用 Flutter 命令编译。
setup.dart 的核心逻辑(截取):
const _allTargets = <String, String>{
'android': 'apk',
'linux': 'deb', // appimage + rpm 仅 amd64
'macos': 'dmg',
'windows': 'exe,zip',
};
const _androidFlutterTarget = {
'arm': 'android-arm',
'arm64': 'android-arm64',
'amd64': 'android-x64',
};
const _hostPlatform = {
'linux': 'linux',
'macos': 'macos',
'windows': 'windows',
};
Future<int> _package(
String platform,
String env,
String targets,
String rootDir,
String arch, {
String? androidArch,
required bool verbose,
}) async {
final coreSha256 = platform == 'windows' ? await _buildGoCore(rootDir) : null;
final file = File(p.join(rootDir, 'env.json'));
await file.writeAsString(
jsonEncode({'APP_ENV': env, 'CORE_SHA256': ?coreSha256}),
);
final flutterBuildArgs = createFlutterBuildArgs(platform: platform, verbose: verbose);
// ...
}值得讲的四点:
platform != host限制:在 Windows 主机上 build Linux 不允许(除了 android)——这是合理的:交叉编译 Flutter + Go 是个复杂的雷区。CORE_SHA256仅 Windows 注入:Windows 端的 Go 内核直接编译进二进制,需要把 SHA256 写进环境变量做完整性校验;其它平台走动态加载。appimage + rpm 仅 amd64:Linux 的桌面包格式分两类——deb 系(deb)和 rpm 系(rpm/appimage),FlClash 只在 amd64 架构提供后两种,arm Linux 没有 rpm/appimage 构建。- 环境变量
APP_ENV:分pre(预发布)和stable(稳定)——这是测试与发布分离的标准做法。
§10 Android 构建链路:Flutter + NDK + GCC
Android 端的构建步骤(README):
- 装 Android SDK、NDK
- 设
ANDROID_NDK环境变量 - 跑
dart setup.dart android
完整工具链:
- Flutter(UI 层)
- Android SDK(应用打包)
- Android NDK(编译 Go 内核为 ARM/x86 native lib)
dart setup.dart android(统一入口)
NDK 这一步对应 _buildGoCore(rootDir)——在 Android 上 ClashMeta 内核被编译为 .so 文件,运行时通过 Flutter plugin 加载。
§11 Windows 构建链路:Flutter + GCC + Inno Setup
Windows 端的构建步骤(README):
- Windows 客户端(必须)
- 装 GCC(MinGW-w64 或类似)、Inno Setup
- 跑
dart setup.dart windows
完整工具链:
- Flutter(UI 层)
- GCC(编译 Go 内核为 Windows DLL/EXE)
- Inno Setup(打包安装器为
.exe) dart setup.dart windows(统一入口)
注意 GCC——这和大多数 Go-on-Windows 项目用 MSVC 不同。推测是 ClashMeta 内核本身依赖 CGO,且作者偏好 GCC 工具链的跨平台一致性。
§12 v0.8.94 CHANGELOG 解读:稳定期的细节优化
最近 8 个版本的 CHANGELOG(节选):
| 版本 | 日期 | 关键改动 |
|---|---|---|
| v0.8.94 | 2026-07-11 | 修复 macOS 性能、支持自定义 global-ua、修复 Linux silent launch |
| v0.8.93 | 2026-05-29 | 支持 custom overwrite、支持 run on demand、优化 Windows IPC、优化 Windows arm64 |
| v0.8.92 | 2026-02-02 | 加 SQLite 存储、优化 Android Quick Tile、优化备份/恢复 |
| v0.8.91 | 2025-12-12 | 修 Windows 多个问题、优化 overwrite handle、优化 access control 页 |
| v0.8.90 | 2025-10-08 | 修 Android tile service、支持追加系统 DNS |
| v0.8.89 | 2025-09-27 | 优化 Windows service mode |
| v0.8.88 | 2025-09-23 | Android 拆分核心进程、支持 core status check 和 force restart |
| v0.8.87 | 2025-07-29 | 优化桌面视图、优化 logs/requests/connections 页、优化 Windows tray auto hide |
可读出的产品节奏:
- 持续打磨:每版 5-10 项修复,无大改架构
- 平台均衡:四端各占相当比例,没有只追一端
- 隐私优先:自定义 UA、IP 同步、Access Control 都是隐私向能力
- 进程隔离:v0.8.88 把 Android 核心进程拆出来——这是稳定性提升的关键一步
§13 任务流案例:一次「订阅切换」的代码路径
把上面拆的所有模块串起来,看一次完整的「用户切换订阅」走哪些层:
- UI 层(
lib/pages/proxies或lib/views/...):用户点击订阅源 A - Provider 层(
lib/providers/):Riverpod 状态更新,触发subscriptionProvider - Manager 层(
lib/manager/core_manager.dart):调用 Clash 内核的「reload config」 - Core 桥接(
lib/core/service.dart):通过 IPC 发送 reload 指令给 Go 内核 - Rust 桥(
rust_api):在桌面端,Rust 负责管理 Go 进程的 IPC(移动端跳过此层) - Go 内核(
core/子模块):Clash Meta 进程重新解析配置文件,更新路由表 - 事件回流(
lib/core/event.dart):内核通过事件流推送新状态 - Manager 回调(
status_manager.dart):订阅coreStateProvider,更新 UI 显示 - 系统层反馈(
vpn_manager.dart/tray_manager.dart):同步更新 VPN 状态/托盘图标
这条链路展示了 FlClash 「Flutter UI 看似简单、底下叠了六层抽象」的真实形态——这也是为什么 45K Stars 的项目代码量高达 56K+ KB(GitHub API size 字段)。
§14 决策表:你是哪类用户、该不该选 FlClash
| 你是谁 | 你的诉求 | 建议 |
|---|---|---|
| 普通 Windows/macOS 用户,想找稳定的代理 GUI | 不想折腾订阅格式 | ✅ FlClash 桌面端体验和 CFW/ClashX 同级 |
| Android 用户,对 Quick Tile 有强需求 | 通知栏瓷砖开关代理 | ✅ 自研 tile 服务,CHANGELOG 多次打磨 |
| macOS Apple Silicon 用户 | 原生 arm64 支持 | ✅ v0.8.93 优化了 Windows arm64,macOS Apple Silicon 走 Flutter 自动适配 |
| Linux 桌面用户 | 想要现代 GUI 替代命令行 clash | ✅ v0.8.94 修了 silent launch,tray 集成可用 |
| 自托管/订阅格式研究者 | 想看 ClashMeta YAML 兼容性 | ✅ FlClash 内核就是 ClashMeta,无格式阉割 |
| 想要最简 CFW 风格 | 不需要花哨 UI | ⚠️ FlClash 功能多,初次接触需要适应 |
| iOS 用户 | — | ❌ FlClash 不发布 iOS(苹果政策限制 VPN 类工具) |
| 想要开箱即用的免费节点 | — | ❌ FlClash 是客户端,需要自己准备订阅 |
§15 与同赛道项目的边界
- vs Clash Verge:同样是跨平台 GUI,Verge 是 Tauri(Rust)+ WebView,FlClash 是 Flutter + Rust + Go。Verge 安装包更小(WebView 系统自带),FlClash UI 一致性更好。
- vs ClashX(macOS):ClashX 只做 macOS,体验极致但不跨端。FlClash 在 macOS 上功能更全但启动稍慢。
- vs Hiddify:Hiddify 同样是 Flutter 跨端,但 FlClash 持续维护节奏更稳、Stars 更多。
- vs 内核项目 clash-meta:这是上游,FlClash 是消费内核的客户端。
§16 资料口径与边界
已确认(仓库可见证据):
- 45K Stars / 2851 Forks / 524 open issues(GitHub API 2026-07-12 数据)
- GPL-3.0 许可
- Dart(Flutter)语言主导
- 最近 release v0.8.94(2026-07-11)
- 主分支
main - 自带
setup.dart构建脚本、core/子模块引用 lib/下的core/、manager/、common/、features/、plugins/五个主要目录的职责划分plugins/自研两个:proxy/、wifi_ssid/- 13 个 manager 文件名(已逐项核对)
pubspec.yaml中关键 fork 依赖:window_manager、tray_manager、launch_at_startup、yaml_writer(均来自作者私有仓库)- 四平台支持:Android / Windows / macOS / Linux
已显式标注:
lib/core/下八个文件的精确职责是基于文件名推断——实际边界需要直接读源码lib/features/overwrite/的实现机制需读rule.dart才能完整确认- Rust 桥的具体通信协议(IPC 类型、消息格式)需读
rust_api源码 - 43 个
lib/common/文件的精确作用以仓库为准
不在本文覆盖:
- iOS 版本(FlClash 无 iOS 端)
- F-Droid 仓库签名链(README 给了 fingerprint,但本文不展开)
- WebDAV 同步的具体加密方案
- Android 拆分核心进程的进程间通信细节(v0.8.88)
§17 参考链接
- 仓库主链接:https://github.com/chen08209/FlClash
- 中文 README:https://github.com/chen08209/FlClash/blob/main/README_zh_CN.md
- 下载页:https://github.com/chen08209/FlClash/releases
- Telegram 频道:https://t.me/FlClash
- F-Droid 仓库:https://chen08209.github.io/FlClash-fdroid-repo/repo
- Homebrew Tap:
brew tap chen08209/tap && brew install --cask flclash - ClashMeta 内核(上游):https://github.com/MetaCubeX/Clash.Meta
§18 自测题
- FlClash 的三语言分工是什么?分别承担哪一层?
lib/manager/下 13 个 Manager 中,哪三个对应移动端最关键的系统能力?setup.dart为什么不直接用flutter build?它解决了哪些工具链衔接问题?- v0.8.94 CHANGELOG 提到 macOS 性能问题修复,但没给数字——这种「无 benchmark 报告的修复」能推出什么、不能推出什么?
- 一次「订阅切换」至少要走哪几层模块?列出至少五层。