Skip to content

Repository files navigation

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 或常规日志。
  • liststatusscan、模板和 registry 命令只输出键名、位置及 metadata,不输出值。
  • getexport 是仅有的显式敏感输出命令:值写入 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 --help

Windows 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_TOKEN

list 支持可选 --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 fix

fix 只生成缺失的必需项,不生成 optional 项。没有配方的必需项会要求安全输入。status 还会报告当前项目作用域、当前环境中未在 manifest 声明的冗余键;全局键和其他环境中的键不会被标为冗余。

4. 运行项目

fluffy run -- npm run dev

run 使用参数数组启动子进程,不经 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 支持 randomhexbase64base64urluuid。默认生成 32 个密码学安全随机字节的 base64url 令牌;uuid 适合标识符,不适合高熵认证密钥。random--charset 可选 loweruppernumericalphanumericall

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/app
API_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-keys

skill 默认要求 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 } 声明;已有声明及其 requiredrecipe 配置不会被覆盖。

扫描会跳过真实 .env* 文件、.git.nextnode_modulesdistcoverage,不会读取或输出真实 .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。

设计文档

更多架构、数据边界和威胁模型说明,请阅读 概要设计

About

一个本地密钥生成、管理cli工具。A locale secret manage node cli.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages