当前位置: 首页 > news >正文

用 Go 写了一个极简 API Key 管理工具,两个字母搞定一切

前言

日常开发中,我们每个人手里都有十几个甚至几十个 API Key:OpenAI、Anthropic、AWS、GitHub Token、Stripe……

它们通常散落在这些地方:

  • 项目里的.env文件
  • ~/.bashrc~/.zshrc里的环境变量
  • 浏览器书签或备忘录
  • 各种配置文件

用的时候到处翻,找到了还要手动复制。更糟糕的是,.env文件一不小心就提交到 Git 了,Key 泄露到 GitHub 上……

所以我写了mk (My Keys)—— 一个极简的终端工具,把所有 API Key 存到系统 Keychain 里,两个字母就能管理。

效果演示

$ mk set openai sk-proj-abc123... ✓ Set openai $ mk set nvidia nvapi-xyz789... ✓ Set nvidia $ mk ls ● nvidia ● openai $ mk get openai sk-proj-abc123... $ mk cp openai ✓ Copied openai to clipboard $ mk rm openai ✓ Removed openai

为什么不用 .env?

我对比了一下常见的方案:

方案安全性便捷性跨项目
.env文件❌ 明文存磁盘⚠️ 需要 cd 到项目目录❌ 每个项目都要配
1Password✅ 加密存储⚠️ 需要打开 App✅ 全局可用
pass(GPG)✅ 加密存储❌ 需要 GPG 配置✅ 全局可用
mk✅ 系统级加密✅ 两个字母✅ 全局可用

mk 的优势在于:零配置,零依赖,跟系统登录密码同级安全。

实际使用场景

1. 嵌入命令

curl-H"Authorization: Bearer$(mk get openai)"https://api.openai.com/v1/models

2. 设置环境变量

exportANTHROPIC_API_KEY=$(mk get anthropic)

3. 复制到剪贴板(终端不留痕迹)

mkcpopenai

这个特别实用。直接mk get会在终端里打印 Key,而mk cp只复制到剪贴板,终端历史里不会留下任何痕迹。

安装

macOS

brew tap axliupore/tap brewinstallaxliupore/tap/mk

Linux

从 GitHub Releases 下载安装包:

# Debian / Ubuntusudodpkg-imk_*_linux_amd64.deb# Fedora / RHELsudorpm-imk_*_linux_amd64.rpm# Alpinesudoapkadd--allow-untrusted mk_*_linux_amd64.apk

Windows

scoop bucket add axliupore https://github.com/axliupore/scoop-bucket scoop install mk

从源码编译

goinstallgithub.com/axliupore/mk@latest

技术实现

整体架构

mk/ ├── main.go # 入口 ├── cmd/ # Cobra 命令 │ ├── root.go │ ├── set.go │ ├── get.go │ ├── cp.go │ ├── ls.go │ └── rm.go ├── internal/ # 内部包 │ ├── keyring.go # go-keyring 封装 │ ├── style.go # lipgloss 终端美化 │ ├── list_darwin.go # macOS ls 实现 │ ├── list_linux.go # Linux ls 实现 │ └── list_windows.go # Windows ls 实现 ├── go.mod └── .goreleaser.yaml # 跨平台构建配置

技术栈

  • Go 1.26— 单二进制,零依赖
  • Cobra— CLI 框架
  • go-keyring— 跨平台 Keychain 访问
  • lipgloss— 终端输出美化(charmbracelet 出品)
  • GoReleaser— 跨平台自动构建发布

核心难点:实现mk ls

go-keyring库只提供了SetGetDelete三个 API,没有 List。所以我需要自己解析各平台的原生命令输出来实现列表功能。

macOS:解析security dump-keychain

这是最复杂的一个。security dump-keychain的输出格式非常不一致:

属性标签有三种写法:

"svce"<blob>="mk" # 带引号 svce<blob>="mk" # 不带引号 0x00000007 <blob>="mk" # 十六进制代码

更坑的是,当属性值包含非 ASCII 字符(比如中文别名)时,值会被十六进制编码:

0x00000008 <blob>=0xE58898E58898...

而不是正常的 UTF-8:

0x00000008 <blob>="刘"

我写了 6 种模式匹配器来覆盖所有组合,加上encoding/hex解码十六进制的 blob 值。

Windows:cmdkey /list的多语言问题

在中文 Windows 上,cmdkey /list的输出是这样的:

目标: LegacyGeneric:target=mk:openai

而不是英文的:

Target: LegacyGeneric:target=mk:openai

一开始我加了中英文两种匹配,但后来想到日文、韩文怎么办?最终方案是匹配LegacyGeneric:target=mk:这个内部标识符——它在任何语言系统下都是英文的。

Linux:secret-tool search

这个反而是最简单的。secret-tool search --all service mk输出很干净。唯一要注意的是,没有匹配项时返回退出码 1,需要单独处理。

管道兼容性

mk get的输出是纯文本,不带任何 ANSI 颜色代码。这是刻意的设计,确保$(mk get alias)在脚本中直接可用,不需要额外处理。

mk lsmk set等命令的输出则用 lipgloss 做了美化,有颜色和图标。

跨平台构建

用 GoReleaser 统一构建 macOS、Linux、Windows 三个平台的二进制。一开始踩了个坑:以为 Linux 上 go-keyring 依赖 dbus 需要 CGO_ENABLED=1,结果交叉编译时各种报错。后来发现 godbus/dbus 是纯 Go 实现,CGO_ENABLED=0 就够了。

安全性

  • Key 存储在操作系统原生的加密凭据库中(macOS Keychain / Windows Credential Manager / Linux Secret Service)
  • mk 不会往磁盘写任何文件
  • 不联网,不上传,完全离线
  • mk cp直接复制到剪贴板,终端里不打印
  • MIT 开源,代码可审计

总结

如果你也经常为管理 API Key 发愁,可以试试 mk。两个字母,从此安心。

  • GitHub:https://github.com/axliupore/mk
  • 开源协议:MIT

觉得有用的话,欢迎 Star ⭐

http://www.jsqmd.com/news/683750/

相关文章:

  • 股市学习心得-固态电池核心上市公司
  • Nature 图表复现 | 样本分布图
  • OpenClaw35万Star-AI编程进入多智能体协同时代
  • 2026年山东到哈萨克斯坦物流公司最新推荐:山东到吉尔吉斯斯坦物流、山东到塔吉克斯坦物流、山东到乌兹别克斯坦物流、山东到土库曼斯坦物流公司选择指南 - 海棠依旧大
  • Logback日志格式实战:解决特殊字符与多行日志采集的5个坑
  • 别再手动写packages了!用setuptools的find_packages()自动打包你的Python多模块项目
  • 展讯A16摄像头插值到非代码中预设值时处理方法
  • 网络安全实战干货:从个人防护到企业防护,全场景避坑指南
  • 告别IP盲猜:为你的STM32设备加上“网络身份证”(基于LwIP 2.1.2的HostName与DHCP深度集成教程)
  • 2026年如何部署OpenClaw?8分钟华为云保姆级安装及百炼Coding Plan步骤
  • STM32CubeIDE新手必知的10个快捷键,效率提升不止一倍(附重定义printf避坑指南)
  • Altium Designer 导出Gerber和坐标文件保姆级教程(附常见报错排查)
  • 什么是数据库?什么是关系数据库?什么是非关系型数据库?
  • 告别手动推导噩梦:用Matlab符号工具箱快速搞定球坐标拉普拉斯算子转换
  • 告别Demo版限制:手把手教你搞定CANoe 17.0的License激活与疑难杂症排查
  • 高效构建由对称子矩阵组成的三维数组
  • Claude-Opus-47-VS-GLM-51-2026编程能力王者之争
  • 区块链与AI融合:10大产业变革深度解析
  • Qt信号量QSemaphore避坑指南:tryAcquire非阻塞调用、release过量释放,这些多线程‘暗雷’你踩过吗?
  • 猫抓浏览器扩展:轻松捕获网页媒体资源的终极指南
  • Python变量相关性分析:原理、实现与实战应用
  • 别再写硬编码了!MyBatis-Plus的apply方法,这样用才安全又灵活(附日期查询实战)
  • 1篇5章2节:macOS 必备开源包管理器 Homebrew
  • 生化危机8修改器 风灵月影 支持最新版本
  • Element UI 表格合并踩坑记:从官网示例到真实业务场景的完整避坑指南
  • ROS+Catkin项目如何正确生成compile_commands.json?让clangd在VSCode里精准补全
  • Python 工程化开发与性能优化实践
  • 别再到处找数据了!手把手教你从三大GWAS数据库(IEU、MiBioGen、FinnGen)一键下载与清洗
  • 光学设计避坑指南:反射棱镜选型、展开与光轴计算的3个关键步骤
  • 前端性能优化实战:用FormData和axios拦截器改造el-upload,轻松合并上传请求