fluffy-keys
v0.4.0
Published
A local-first CLI for managing development secrets and environment values.
Maintainers
Readme
fluffy-keys
fluffy-keys 是一个本地优先的 Node.js CLI,用于管理开发环境中的 API Key、令牌、密码及其他环境变量。实际值保存在当前操作系统用户的原生安全存储中;项目只提交不含值的声明文件 .fluffy.json。
它适用于本地开发密钥管理,不替代生产环境、CI/CD 或团队共享环境的专业 Secret Manager。
特性
- 使用 Windows Credential Manager、macOS Keychain 或 Linux Secret Service 保存实际密钥值。
- 管理全局密钥:列出、读取、设置、生成、删除,以及 JSON、dotenv、YAML 导入导出。
- 通过
.fluffy.json声明项目依赖,并按“项目作用域优先、全局作用域回退”解析。 - 通过
fluffy run仅向子进程注入已声明的密钥,不修改当前 shell。 - 使用配方生成缺失的项目密钥,并支持从全局作用域安全迁移到项目作用域。
- 静态扫描 Node.js、Java 和
.env.example中的环境变量声明。 - 使用严格的 JSON 模板交换团队声明和生成配方,不交换密钥值。
- 诊断并显式清理原生 Vault 的过期 metadata 索引。
安全模型
- 实际密钥绝不写入
.fluffy.json、recipe 配置、模板、registry 或常规日志。 list、status、scan、模板和 registry 命令只输出键名、位置及 metadata,不输出值。get和export是仅有的显式敏感输出命令:值写入 stdout,export会在 stderr 发出警告。set默认使用隐藏回显输入;脚本场景必须显式使用--stdin,避免值进入命令历史。--system仅在 Windows 上读写当前用户环境变量(HKCU\\Environment),其值为明文,不是 Vault 的替代品;只适用于用户明确要求持久化的非敏感配置。修改后需重启已打开的终端或 IDE。- 安全存储不可用时命令以退出码
4失败,不会降级为明文文件。 FLUFFY_VAULT=memory仅限测试和开发调试,进程结束后数据会丢失,不能保存真实密钥。
要求
- Node.js 22 或更高版本
- npm
- 可用的原生安全存储:Windows Credential Manager、macOS Keychain 或 Linux Secret Service
Linux 上需要在当前会话中运行可用的 Secret Service/keyring;若不可用,CLI 会 fail closed。
安装与本地开发
全局安装已发布版本:
npm install --global fluffy-keys
fluffy --help从源码运行:
git clone <repository>
cd fluffy-keys
npm install
npm run build
node dist/cli/main.js --help测试或适配器开发可使用内存 Vault:
FLUFFY_VAULT=memory node dist/cli/main.js --helpWindows PowerShell 中使用:
$env:FLUFFY_VAULT = 'memory'
node dist/cli/main.js --help快速开始
1. 保存一个全局开发密钥
交互输入,不会回显值:
fluffy set API_TOKEN脚本中从标准输入读取:
printf '%s' "$API_TOKEN" | fluffy set API_TOKEN --stdin列出 metadata 或显式读取值:
fluffy list
fluffy list --prefix='redis_*'
fluffy get API_TOKENlist 支持可选 --prefix <pattern>,仅 * 为通配符,需匹配完整 key,可与 --env、--json 组合,方便筛出同一命名约定下的相关 key。get 会将实际值直接写到 stdout,请勿将其输出记录到日志或终端历史。
Windows 用户环境变量可显式使用 --system:
fluffy list --system --prefix='LOG_*'
fluffy set LOG_LEVEL --system
fluffy get LOG_LEVEL --system--system 不能与 --env 组合,且会把值明文写入当前用户环境变量,不应用于 API Key、令牌、密码等敏感值。新启动的终端和 IDE 才会继承修改后的值。
2. 初始化项目声明
cd my-app
fluffy init --project-id my-app生成的 .fluffy.json 可安全提交:
{
"$schema": "https://fluffy.dev/schemas/keys/v1.json",
"version": 1,
"projectId": "my-app",
"environment": "development",
"secrets": {
"DATABASE_URL": { "required": true },
"JWT_SECRET": { "recipe": "jwt-secret" },
"OPTIONAL_TOKEN": { "required": false }
}
}项目解析顺序为:--env 指定的环境、manifest 的 environment、默认 development。每个声明的键先查询 project/<projectId> 作用域,再回退到 global 作用域;父 shell 的同名变量不会满足声明。
3. 生成并修复缺失项
先创建一个不含值的生成配方:
fluffy recipe set jwt-secret --format base64url --length 48
fluffy recipe list查看项目状态并生成带配方的必需项:
fluffy status
fluffy fixfix 只生成缺失的必需项,不生成 optional 项。没有配方的必需项会要求安全输入。status 还会报告当前项目作用域、当前环境中未在 manifest 声明的冗余键;全局键和其他环境中的键不会被标为冗余。
4. 运行项目
fluffy run -- npm run devrun 使用参数数组启动子进程,不经 shell 拼接,并只向该子进程注入已声明且已解析的密钥。当前 shell 环境不会被修改。
命令参考
全局密钥
| 命令 | 说明 |
| -------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------- |
| fluffy list [--env <environment>] [--prefix <pattern>] [--json] [--system] | 列出 Vault metadata;--system 列 Windows 用户环境变量 key。 |
| fluffy get <KEY> [--env <environment>] [--system] | 将一个实际值写到 stdout;--system 读取 Windows 用户环境变量。 |
| fluffy set <KEY> [--env <environment>] [--stdin] [--system] | 交互式或从标准输入创建、替换 Vault 密钥;--system 写明文用户变量。 |
| fluffy gen <KEY> [--env <environment>] [--format <format>] [--length <n>] [--charset <name>] | 生成并存储安全密钥;generate 是别名。 |
| fluffy rotate <KEY> [--env <environment>] [--system] [--gen] [--format <format>] [--length <n>] [--charset <name>] [--stdin] [--yes] | 轮换已存在的 Vault 密钥或显式选择的 Windows 用户变量。 |
| fluffy remove <KEY> [--env <environment>] [--yes] | 经确认删除密钥。 |
gen 支持 random、hex、base64、base64url 和 uuid。默认生成 32 个密码学安全随机字节的 base64url 令牌;uuid 适合标识符,不适合高熵认证密钥。random 的 --charset 可选 lower、upper、numeric、alphanumeric 或 all。
rotate 只轮换已存在的密钥(缺失时报错,不会自动创建),覆盖前默认要求确认,可用 --yes 跳过。--gen 复用 gen 的生成选项;不带 --gen 时提示输入新值或从 --stdin 读取。
导入与导出
fluffy import <file> --format json|dotenv|yaml [--env <environment>] [--yes]
fluffy export --format json|dotenv|yaml [--env <environment>]导入前会显示键名预览并要求确认,但不会显示值。导出会显示敏感提示,并把值写到 stdout;请仅重定向到受保护且被 Git 忽略的位置:
fluffy export --format dotenv > .env支持的映射格式:
{
"API_TOKEN": "local-only-value",
"DATABASE_URL": "postgres://localhost/app"
}API_TOKEN=local-only-value
DATABASE_URL=postgres://localhost/appAPI_TOKEN: local-only-value
DATABASE_URL: postgres://localhost/app项目命令
| 命令 | 说明 |
| -------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------- |
| fluffy init [--cwd <directory>] [--project-id <id>] [--env <environment>] [--force] [--yes] | 创建 declaration-only .fluffy.json。 |
| fluffy status [--cwd <directory>] [--env <environment>] [--json] | 检查项目声明的解析状态和冗余项目键。 |
| fluffy fix [--cwd <directory>] [--env <environment>] [--yes] | 生成或安全输入缺失的必需项目密钥。 |
| fluffy run [--cwd <directory>] [--env <environment>] -- <command> [args...] | 向子进程注入已声明密钥。 |
| fluffy migrate [keys...] [--cwd <directory>] [--env <environment>] [--all] [--move] [--yes] | 从全局作用域复制声明密钥到项目作用域。 |
| fluffy project import <file> [keys...] --format json\|dotenv\|yaml [--cwd <directory>] [--env <environment>] [--all] [--overwrite] [--yes] | 将格式文件中的已声明 key 写入项目 scope。 |
migrate --all 使用 manifest 中的所有声明键。添加 --move 时,工具会在确认目标值已写入项目作用域后才删除全局来源。
project import 从 JSON、dotenv 或 YAML 文件读取值,必须显式列出待导入 key 或指定 --all;所有 key 都必须已经在项目 .fluffy.json 中声明。它先预览键名并要求确认,默认跳过已有项目值,只有 --overwrite 才替换;实际值不会进入 manifest、预览或日志。
配方
fluffy recipe list
fluffy recipe set <name> \
[--format random|hex|base64|base64url|uuid] \
[--length <n>] \
[--charset lower|upper|numeric|alphanumeric|all]配方是用户级、非敏感的生成规则。它只保存格式、长度和字符集,永远不保存生成结果或第三方凭据。
Agent skill
将随 npm 包发布的 skill 安装到 agent 环境:
npx skills add fluffy-keysskill 默认要求 agent 使用 Vault、先列出 metadata,并在写入、轮换或项目导入前仅展示 key 名和目标范围后等待确认。它禁止未经明确要求读取/导出实际值,也禁止将值写入命令参数、日志、聊天或项目文件。
扫描项目声明
fluffy scan [--cwd <directory>] [--json]
fluffy scan --update [--cwd <directory>] [--yes] [--json]扫描器使用有限的静态模式识别:
- Node.js:
process.env.NAME - Node.js:
process.env["NAME"]或process.env['NAME'] - Java:
System.getenv("NAME") .env.example中的键名
结果分为已声明、可新增候选和动态访问。动态访问只能提示,不能被自动写入。scan --update 会先展示静态候选,并在确认后仅新增 { "required": true } 声明;已有声明及其 required、recipe 配置不会被覆盖。
扫描会跳过真实 .env* 文件、.git、.next、node_modules、dist 和 coverage,不会读取或输出真实 .env 值。
团队声明模板
模板仅支持严格 JSON,适合共享项目所需的键、必需性、目标环境和生成配方:
fluffy template export [--cwd <directory>] > team-template.json
fluffy template import team-template.json [--cwd <directory>] [--yes]示例:
{
"version": 1,
"environment": "development",
"secrets": {
"JWT_SECRET": { "required": true, "recipe": "jwt-secret" }
},
"recipes": {
"jwt-secret": { "format": "base64url", "length": 48 }
}
}模板不包含 projectId、Vault registry metadata 或任何实际值。导入前会预览新增项和冲突项;冲突始终保留本地声明与配方。模板根级和密钥声明中的未知字段、声明中嵌入的实际值,以及引用不存在配方的声明会被拒绝。
Vault registry 诊断
fluffy vault registry diagnose [--json]
fluffy vault registry repair [--yes]原生 Vault 通过本地 registry 保存 metadata,以便在部分系统钥匙串无法枚举条目时列出密钥。diagnose 只检查 registry 已登记的条目是否仍存在于钥匙串,不能发现 registry 外的条目,且不会修改任何内容。
repair 会预览 stale metadata,并在确认后再次检查;它只删除仍 stale 的 registry metadata,绝不会删除钥匙串中的实际值。内存 Vault 不支持该诊断能力。
退出码
| 退出码 | 含义 |
| ------------ | --------------------------------- |
| 0 | 成功。 |
| 1 | 未预期的通用失败。 |
| 2 | 参数、manifest、模板或配置无效。 |
| 3 | 缺少必需项目密钥。 |
| 4 | 原生安全存储不可用或拒绝访问。 |
| 5 | 用户取消交互操作。 |
| 子进程退出码 | fluffy run 会透传子进程退出码。 |
本地质量检查
npm test
npm run typecheck
npm run lint
npm run format:check
npm run build
npm run pack:check发布由维护者手动执行 npm publish 并使用 OTP;本项目不配置 GitHub Actions CI。
设计文档
更多架构、数据边界和威胁模型说明,请阅读 概要设计。
