FrpGUI

August 19, 2026 · View on GitHub

frpc(frp 内网穿透客户端)的跨平台图形化管理工具。轻量、原生、零依赖,让你不必手改配置文件或用命令行,就能轻松配置和管理内网穿透。

平台 许可证 语言


背景与初衷

FrpGUI 立项于 2026-08-13(作者 Mirai,MIT 协议),是 frp 生态中的第三方图形化客户端。 其初衷来自一份早期需求文档,核心要点如下:

  • 目标人群与价值:让非技术用户也能轻松配置与管理内网穿透,不必手改 frpc.toml 或敲命令行。
  • 产品设计原则:跨平台原生、轻量、零依赖——交付单一原生二进制(无 GTK/Qt 等运行时,体积约 10MB 量级),下载后双击即跑。
  • 技术选型依据:采用 Go + Shirei(纯 Go、无 CGO、即时模式 IMGUI,对 AI 辅助开发友好),与 frp 核心技术栈一致、便于长期维护。
  • 部署形态:主程序 + 独立 frpc 二进制,通过 os/exec 调用外部 frpc 实现穿透,frpc 由用户从官方 Releases 下载随附(不内置、不打包源码)。
  • 协作方式:项目以「与 AI 对话迭代开发」为主要模式,因此代码保持清晰、模块化,并在关键逻辑处保留中文注释。

上述初衷提炼自项目早期的立项需求文档;该文档已完成其历史使命,相关精神已并入本 README 与开发文档。


功能特性

  • 跨平台原生程序:Windows / macOS / Linux 均以原生二进制运行,界面风格自然。
  • 单一二进制、零依赖:无 GTK / Qt 等运行时;最终产物体积小(约 10MB 量级)。
  • 配置管理:图形化创建、编辑、加载 frpc.toml 配置(改动自动保存,无需手动保存;服务端地址、端口、Token、代理规则增删改)。
  • 进程控制:通过「启动 / 停止」按钮管理后台 frpc 子进程的生命周期。
  • 运行状态与日志:清晰显示「已停止 / 运行中 / 启动失败 / 连接失败」等状态,并实时滚动展示 frpc 运行日志(支持一键复制)。
  • 导入 / 导出配置:通过文件对话框导入或导出 frpc.toml
  • 系统托盘(Windows):关闭按钮最小化到托盘;单击 / 双击托盘图标恢复窗口;右键菜单含「主界面 / 启动 / 停止 / 退出」。
  • 多语言:内置 16 种语言(简体中文 / 繁體中文 / 英文 / 日文 / 韩文 / 西班牙文 / 意大利文 / 俄文 / 法文 / 德文 / 葡萄牙文 / 阿拉伯文 / 越南文 / 印尼文 / 泰文 / 土耳其文),语言包「放文件即生效」,可在「语言」菜单中热切换。
  • 字体选择:动态枚举系统全部字体,可一键恢复「系统默认」。
  • 主题配色:单一主题维度。内置仅「简约」(浅色默认)与「深色 Dark」两套保底(永不消失,删光主题文件也不会没主题用);其余彩色主题(蓝 / 绿 / 粉 / 橙 / 咖啡 / 薄荷)均为 theme/*.toml 文件扩展,随仓库提供范例、可删可自制。顶部「主题」菜单热切换并持久化。
  • 顶部标签页:固定顶部标签栏切换「服务端 / 代理 / 工具 / 日志」四个主功能区,点击即时切换;上方控制条(状态 / 启停 / 已加载预设 / 导入导出)常驻,宽度随窗口自适应并按标签页钳制表单列宽。

下载与运行

  1. Releases 下载对应平台的可执行文件(或自行从源码构建,见下)。
  2. 把官方 frp 的 frpcfrpc.exe 放到 FrpGUI 可执行文件同目录(或确保其在 PATH 中)。
  3. 双击 FrpGUIFrpGUI.exe)启动即可。

UI 默认语言按操作系统区域推断(中文环境默认简体中文,否则英文);用户偏好(语言、字体)持久化在程序同目录的 settings.json


界面截图

以下截图基于 Windows 平台,展示 FrpGUI 的主要界面。

服务端配置

服务端配置界面

代理配置

代理配置界面

工具页

工具界面

日志页

日志界面

主题配色选择

主题配色选择

字体选择

字体选择界面

语言选择

语言选择


从源码构建

需要 Go 1.25 或更高(本项目以 Go 1.26.5 验证)。

# 仓库根目录执行
go mod tidy

# Windows(GUI 子系统,无控制台黑框)
go build -ldflags="-s -w -H windowsgui" -o FrpGUI.exe ./cmd/frpguiapp

# macOS / Linux
go build -ldflags="-s -w" -o FrpGUI ./cmd/frpguiapp

构建产物为单一二进制 FrpGUI(或 FrpGUI.exe)。

推荐使用仓库自带的跨平台构建助手(自动设置 CGO / -H windowsgui / 按平台命名): go run ./tools [windows|linux|darwin]。产物统一输出到 build/<平台>-amd64/ 子目录 (如 build/windows-amd64/FrpGUI.exebuild/linux-amd64/FrpGUI),按平台区分且被 .gitignorebuild/ 规则忽略,不会污染仓库根目录、也不会误提交。构建助手还会顺带把 lang/theme/frpc.example.toml 等运行时资产复制到产物目录,因此 build/<平台>-amd64/ 是一个可直接运行的完整包(应用按 exe 同级查找语言包与主题,无需再从仓库根启动)。上面的手动 go build -o 则按你指定的 -o 路径输出(多为仓库根),需自行把 lang/theme/ 放到 exe 同级。


参与开发与治理 / Development & Governance

以上文档均提供英文版(文件名加 _EN 后缀,例如 docs/ARCHITECTURE_EN.mdCONTRIBUTING_EN.mdSECURITY_EN.mddocs/RELEASE_EN.md)。

本地一键复现 CI 门禁:make ci(gofmt 检查 + go vet + go test -race + 跨平台构建)。


使用说明

配置 frpc

程序的服务器配置与代理规则都对应标准 frpc.toml 格式。你可以:

  • 在界面里直接填写「服务端地址 / 端口 / Token」并「新增代理」;
  • 所有修改会自动保存frpc.toml(无需点击保存按钮);
  • 或用「导入配置 / 导出配置」在文件间搬运。

首次启动若找不到 frpc.toml,会载入默认空配置(界面顶部显示「已加载:默认配置」)。可参考仓库内的 frpc.example.toml 模板。

导入 / 导出配置

  • 导出:把当前配置「另存为」一个 frpc.toml 文件到任意位置;导出不会改变当前已加载的预设(不会切换档案)。
  • 导入:先解析目标文件。解析失败会弹窗提示错误;解析成功则在 profiles/ 下创建同名预设(profiles/<文件名>.toml):
    • frpc 正在运行:弹窗提示「导入成功」,并询问是否停止并切换到新导入的配置;可取消,取消后新配置仍保留在 profiles/ 供后续手动切换。
    • frpc 未运行:直接切换并弹窗提示「导入成功」。

启动 / 停止

点击「启动」会通过 os/exec 拉起同目录(或 PATH 中)的 frpc 子进程,并实时捕获其 stdout/stderr 日志到界面日志区;「停止」按 PID 精确终止该子进程。程序只管理自己启动的 frpc,不会误杀你机器上其它正在运行的 frpc。

开机自启(工具页)

「工具」页提供「开机自启」开关:启用后登录系统时自动启动(Windows 写注册表 Run 键、Linux 写 ~/.config/autostart.desktop、macOS 写 ~/Library/LaunchAgents 的 plist)。

  • 开关状态不写入 settings.json,而是实时读取操作系统自身的开机项——真相源就是系统,程序退出 / 重装 / 换盘后状态依然正确,也不会出现「JSON 说已启用、系统实际未启用」的漂移。
  • 工具页实时显示当前状态(启用 / 禁用),点击「启用 / 禁用」立即生效。

系统托盘行为(Windows)

关闭按钮的行为取决于 frpc 运行状态:

  • 运行中:点击右上角关闭按钮 → 最小化到托盘(不直接退出程序),可从托盘恢复。
  • 未运行:点击关闭按钮 → 直接退出程序。

托盘交互:

  • 单击 / 双击托盘图标 → 恢复主窗口
  • 右键托盘图标 → 菜单:主界面 / 启动 / 停止 / 退出
  • 「退出」会干净地停止 frpc、移除托盘图标并关闭程序
  • 防误触:frpc 运行中时,从菜单切换预设、或在托盘菜单选择「退出」这类「会导致 frpc 关闭、连接断开」的操作,会先弹出确认框警告「将断开连接」并询问是否继续;非运行中则直接执行。

macOS / Linux 暂未实现托盘,关闭按钮行为保持系统默认(直接关闭窗口)。


日志系统

程序内置一套异步文件日志,便于排查问题,且不影响主程序性能:

  • 分级DEBUG < INFO < WARN < ERROR,默认级别 INFO。级别写在 settings.jsonlog_level 字段,修改后重启生效。
  • 非阻塞:所有日志经带缓冲的 channel 派发到后台 goroutine 写入,调用方永不阻塞(通道极端满载时丢弃并计数,避免拖慢主程序)。
  • 按月分目录、按天分文件logs/<YYYY-MM>/app-<YYYY-MM-DD>.loglogs/<YYYY-MM>/frpc-<YYYY-MM-DD>.log,跨零点自动新建当日文件、跨月自动新建当月目录。
  • 两个日志文件
    • app-<YYYY-MM-DD>.log —— 程序自身运行日志(自检、配置加载、启动/停止、导入导出、错误等),受 log_level 过滤。
    • frpc-<YYYY-MM-DD>.log —— frpc 子进程的 stdout/stderr 原始输出,始终记录(frpc 自身已带级别,不做过滤)。
  • 目录位置
    • Windows:程序所在目录的 logs/(便携,随程序同目录)。
    • macOS / Linux:遵循 XDG 规范,位于用户缓存目录 ~/Library/Caches/FrpGUI/logs(macOS)或 $XDG_CACHE_HOME/FrpGUI/logs(Linux)。
  • GUI 内的实时日志面板照常显示,与文件日志相互独立、互不影响。
  • 界面日志面板:单一统一缓冲把程序自身日志与 frpc 子进程输出按到达顺序混合显示——无需每帧重算、也无跨天排序问题。GUI 行带 HH:MM:SS 前缀,frpc 行保留 HH:MM:SS.mmm(已去除 ANSI、去掉日期)。界面仅保留最近 1000 条,更早的完整带日期历史在上面的文件里。复制选中(或全部)行写入剪贴板后,会在「复制」按钮旁显示一条带 HH:MM:SS 前缀的「已复制」瞬时提示,3 秒后自动消失(连续复制会刷新时间戳)。

多语言与字体

  • 新增语言:复制 lang/zh-CN.tomllang/<语言码>.toml,翻译右侧值并在文件内设置 lang_name,无需改代码,「语言」菜单会自动列出。
  • 内置保底语言(3 套,永不消失)zh-CN(简体中文)、zh-TW(繁體中文)、en(English) 经 go:embed 编译进二进制(见 lang_builtin.go),即便用户删光了所有 lang/*.toml, 也始终可选可用、不会出现「没有语言可选」的窘境。磁盘上若存在同名 <code>.toml,则覆盖 内置版本(同名则覆盖),与主题的内置/文件关系一致。其余 13 种语言仍为纯文件扩展(删了即从菜单消失)。
  • 语言菜单顺序:固定把 zh-CNzh-TWen 排在菜单最前,其余语言(内嵌或磁盘)统一按字母升序跟在后面,顺序稳定、便于查找。
  • 默认启用语言:优先使用用户已持久化的选择;若无,则按操作系统界面语言(detectOSLang 依次看 LC_ALL/LC_MESSAGES/LANG 与 Windows GetUserPreferredUILanguages)推断,命中可用语言包即用;都未命中则默认回退英文(en)兜底,保证初次启动总有可读界面。
  • 字体在「字体」菜单中动态枚举系统字体选择,可随时恢复「系统默认」。

字体策略:不内置任何字体

FrpGUI 不打包、不内嵌任何字体文件(包括 Noto Sans 等),以守住「单一二进制、零依赖、体积小」的初衷。

  • 为什么不内嵌:实测表明 go:embed 对 TTF 几乎不压缩——嵌入本机 17.7MB 的 Noto Sans SC,二进制仅增约 17MB(压缩比 1.001),即「实付 ≈ 字体文件大小」。要内嵌整族 Noto 覆盖 800+ 语种需数百 MB,得不偿失。详细实测见开发踩坑文档 §21
  • 程序怎么取字形:通过 Shirei 的字体子系统 + 应用层「字体回退链」自动回退——已枚举 16 个覆盖字体(Nirmala UI / Leelawadee UI / Microsoft JhengHei / Yu Gothic UI / Nyala / Ebrima 等),把系统已安装的字体作为兜底,零体积代价。
  • 冷门语种显示不出来怎么办:若某语言(如韩文、泰文、阿拉伯文、天城文等)出现方块或空白,说明你的系统缺少对应字形字体。请自行在操作系统安装相应字体(Windows:设置 → 字体,或从 Microsoft Store 安装 Noto Sans 系列、或系统自带的韩文/泰文/阿拉伯字体;Linux/macOS 同理),安装后重启 FrpGUI(或点「字体」菜单里的刷新)即可自动识别并回退显示。无需修改程序、无需重编译。

主题配色

配色按「语义角色」集中管理,只有一个维度——主题(theme),均「放文件即生效」,无需改代码。

  • 内置保底主题(2 套,永不消失)minimal(简约,浅色默认,马卡龙中性灰 + 黑字)、dark (深色 Dark,低亮度背景 + 白色文字,即「简约」的中性灰暗色版)。二者硬编码在程序中, 即便用户删光了所有 theme/*.toml,也始终可用,不会出现「没有主题可选」的窘境。
  • 文件扩展主题(仓库自带范例,可删可改)blue / green / pink / orange / coffee / mint 等彩色主题,各自对应一份 theme/<id>.toml,取色完全由文件里的 hue/sat 决定。 它们不是内置——删掉文件即从菜单消失,用户可照葫芦画瓢自制(复制一份改名改 hue 即可)。
  • 切换主题:顶部「主题」菜单先列出内置保底(简约置顶、深色紧随其后),再按字母序枚举 theme/*.toml,选择即热重载并持久化。

新增 / 自定义浅色主题:复制任意一份范例(如 theme/blue.toml)为 theme/<id>.toml,只需声明主色相与饱和度即可——

theme_name = "示例 Example"   # 菜单显示名
hue = 280                     # 主色相 0-360(紫色)
sat = 65                      # 主饱和度 0-100
light_tint = 10              # 可选:浅色模式下交互色额外饱和度(马卡龙感)
dark_tint  = 20              # 可选:深色模式下交互色额外饱和度(更明艳;仅当该主题为深色时生效)
dark_accent_l = 62           # 可选:深色模式强调色亮度 L(越高越亮)

语义角色由程序按色相/饱和度自动派生(浅色主题用 buildLight,深色主题用 buildDark),无需逐字段手写。 minimaldark 均为纯内置(无对应 toml 文件,删光 theme/*.toml 也始终可用);若想微调主题, 复制任意一份彩色范例(如 theme/blue.toml)改名改 hue 即可,或在 theme/ 下放一份 dark.toml 覆盖 dark_accent_l 来微调深色主题的强调色亮度。


项目结构

FrpGUI/
├── cmd/frpguiapp/                 # 全部源码(package main,按职责拆分同包多文件)
│   ├── main.go                    # 入口:偏好/语言/配置加载、窗口/图标/托盘初始化、退出清理
│   ├── state.go                   # 全局应用状态(统一日志缓冲、日志选区、复制提示、当前标签等)
│   ├── panels.go                  # 主界面 RootView 与 服务端/代理/工具/日志 四个面板
│   ├── menu.go                    # 顶部菜单(档案/主题/字体/语言/帮助)与字体弹窗
│   ├── handlers.go                # 按钮回调(启动/停止/导入导出/诊断)
│   ├── widgets.go                 # 复用的小型 UI 控件
│   ├── config.go                  # frpc.toml 全字段读写(自定义 Marshal/Unmarshal)
│   ├── prefs.go                   # settings.json 偏好持久化(语言/字体/日志级别/主题)
│   ├── profiles.go                # 多配置预设(profiles/<name>.toml 管理)
│   ├── clear_creds.go             # 清除凭据入口(与脱敏白名单同步)
│   ├── logger.go                  # 异步、分级、按月分目录按天分文件日志(app / frpc 两个日志器)
│   ├── crash.go                   # 未捕获 panic 落盘崩溃日志
│   ├── diagnostics.go             # 导出诊断信息(脱敏 settings + frpc + 日志打包)
│   ├── process.go                 # frpc 子进程管理(通用 FrpcManager + 日志采集)
│   ├── process_{windows,other}.go # 启动 frpc 的平台拆分
│   ├── stop_{windows,other}.go    # 停止 frpc 的平台拆分(SIGTERM / 强杀回退)
│   ├── integrity.go               # frpc 二进制完整性校验(SHA256 比对基准)
│   ├── netcheck.go                # 后台连通性 / 延迟测试
│   ├── tray_windows.go            # 系统托盘(Windows 实装,子类化 WM_CLOSE)
│   ├── tray_{common,other}.go     # 托盘公共逻辑 / 非 Windows 空实现
│   ├── single_instance_{windows,other}.go  # 单实例锁(平台拆分)
│   ├── startup_{windows,linux,darwin}.go   # 开机自启(平台拆分)
│   ├── theme.go                   # 主题(单一维度,hue+sat 派生 25 个语义角色)
│   ├── lang.go                    # 语言包加载与动态枚举(文件优先,缺失回退内置)
│   ├── lang_builtin.go            # 内嵌兜底语言包(zh-CN/zh-TW/en,go:embed)
│   ├── locale_{windows,other}.go  # OS 语言推断(平台拆分)
│   ├── filepicker.go              # 自绘纯 Go 文件选择弹窗(替代 sqweek/dialog)
│   ├── confirm.go                 # 通用确认弹窗
│   ├── icon/                      # 图标源(icon.png 经 go:embed;Windows 资源 resource_windows.syso)
│   └── *_test.go                  # 22 个测试文件(覆盖率门禁 go test -race;Go 要求与源码同目录,go build 自动忽略、不进二进制)
├── lang/                          # 16 份语言包(zh-CN/zh-TW/en 亦内嵌进二进制作兜底 + 13 种其它语言)
├── theme/                         # 6 份彩色主题(blue/coffee/green/mint/orange/pink);minimal/dark 为内置
├── profiles/                      # 多配置预设(运行期用户数据,含明文 Token,已被 .gitignore 排除,不入库)
├── tools/                         # 构建与供应链工具:build.go(跨平台构建)、sbom.go(SBOM 生成)
├── docs/                          # 架构/踩坑/发布/安全 文档(ARCHITECTURE/DEVELOPMENT_PITFALLS/RELEASE 均提供 _EN 英文版)
├── frp_*/                         # 官方 frpc 解压目录(运行期放置 frpc 二进制;gitignored,不入库)
├── logs/                          # 运行期日志(按月分目录;gitignored)
├── frpc.example.toml              # 配置示例模板(可入库)
├── go.mod / go.sum
├── Makefile                       # ci / build / sbom / supply-chain 等目标
├── README.md / README_EN.md / CONTRIBUTING.md / CONTRIBUTING_EN.md / SECURITY.md / SECURITY_EN.md
└── .gitignore

注:运行期生成的 frpc.toml(默认配置)与构建产物 FrpGUI(.exe)、以及 profiles/frp_*/logs/ 均被 .gitignore 排除,不入库;仓库内 theme/ 仅含 6 份彩色范例,minimal/dark 为主题内置、无需文件。


技术栈

  • 语言:Go
  • GUI 框架Shirei(纯 Go、无 CGO、即时模式 IMGUI)——契合「单一二进制、零依赖」目标。
  • 依赖go.hasen.dev/shirei(GUI)、github.com/pelletier/go-toml/v2(TOML 解析)、golang.org/x/sys(平台 API)。文件对话框为自绘纯 Go 实现(filepicker.go),无第三方对话框库;Windows/Linux 为 CGO_ENABLED=0 纯 Go 单二进制,macOS 因 Shirei 的 cocoabackend 经 AppKit 走 cgo,须 CGO_ENABLED=1 且在 Mac 上构建(见 tools/build.go)。

已知限制 / 后续计划

  • macOS / Linux 托盘未实现:当前关闭即退出(Windows 已按运行状态动态处理:运行中→托盘,未运行→退出)。
  • 日志优雅退出(已基本闭环):正常退出路径(app.Run() 返回后 defer)已统一兜底——先停 frpc 子进程再优雅落盘,macOS / Linux / Windows 关窗均零丢失;另注册 SIGINT/SIGTERM/SIGHUP 信号处理器,覆盖 kill、终端中断、桌面会话注销/系统关机等信号类终止;后台写入线程的 flush 周期由 1s 收紧到 250ms,任何绕过清理的异常终止最多丢失约 250ms 日志。唯一残余风险是 macOS 经 Cocoa 的 exit() 直接退出的 Quit 路径(不经过 POSIX 信号、也不触发 Go defer)。
  • 打包分发(安装包 / 签名)尚未处理。

许可证

MIT License © 2026 Mirai. FrpGUI 是 frp 生态的第三方图形化工具,遵循 frp 的开源精神。第三方组件的许可证与归因详见 THIRD-PARTY-LICENSES.md