返回更新列表
新发布Sep 3, 2026

envsec v1.0.0-rc.2

使用原生操作系统凭据存储(macOS Keychain、Linux Secret Service、Windows Credential Manager)管理环境密钥的安全CLI工具

分享

envsec

使用操作系统原生凭据存储进行安全的环境密钥管理。

演示

Image

功能特性

  • 将密钥存储在操作系统原生凭据存储中(而非纯文本文件)
  • 跨平台:macOS、Linux、Windows
  • 按上下文组织密钥(例如 myapp.dev、stripe-api.prod、work.staging)
  • 通过 SQLite 跟踪密钥元数据(键名、时间戳)
  • 使用 glob 模式搜索上下文和密钥
  • 运行带有密钥插值的命令
  • 使用 cmd 保存并重新运行命令(搜索、列出、运行、删除)
  • 将密钥导出为 .env 文件(通过 audit 进行生成跟踪)
  • 将密钥导出为 shell 环境变量(eval $(envsec env))
  • 从 .env 文件加载密钥(带冲突检测)
  • 使用 GPG 加密共享密钥给团队成员
  • 交互式终端 UI(envsec tui),无需记忆命令即可管理密钥

包

这是一个包含以下包的 monorepo:

包描述npm
envsec用于管理密钥的 CLI 工具npm
@envsec/sdk用于以编程方式加载密钥的 Node.js / Bun SDKnpm
@envsec/core核心引擎 — 操作系统凭据存储适配器 + 元数据数据库npm
@envsec/tui用于密钥管理的交互式终端 UInpm

SDK 快速开始

如需从 Node.js 或 Bun 以编程方式访问密钥,请使用 @envsec/sdk:

npm install @envsec/sdk
import { loadSecrets } from "@envsec/sdk";

// Load and inject into process.env
await loadSecrets({ context: "myapp.dev", inject: true });

// Or use the client for full control
import { EnvsecClient } from "@envsec/sdk";
const client = await EnvsecClient.create({ context: "myapp.dev" });
const apiKey = await client.get("api.key");
await client.close();

查看完整的 SDK 文档 以了解所有 API、多上下文支持及选项。

环境要求

  • Node.js >= 22

macOS

无需额外依赖。通过 security CLI 工具使用内置的钥匙串。

Linux

需要 libsecret-tools(提供 secret-tool 命令),它通过 D-Bus 与 GNOME Keyring、KDE Wallet 或任何 Secret Service API 提供程序通信。

# Debian / Ubuntu
sudo apt install libsecret-tools

# Fedora
sudo dnf install libsecret

# Arch
sudo pacman -S libsecret

必须有一个正在运行的 D-Bus 会话和一个密钥环守护进程(例如 gnome-keyring-daemon)。大多数桌面环境会自动处理这一点。

Windows

无需额外依赖。通过 cmdkey 和 PowerShell 使用内置的 Windows 凭据管理器。

安装

Homebrew(macOS / Linux)

brew tap davidnussio/homebrew-tap
brew install envsec

npm

npm install -g envsec

npx(无需安装)

npx envsec

mise

mise use -g npm:envsec

用法

大多数命令需要通过 --context(或 -c)指定一个上下文。上下文是用于对密钥进行分组的自由格式标签——例如 myapp.dev、stripe-api.prod、work.staging。

全局选项

这些选项在所有命令中均可用:

  • --context、-c — 上下文名称(例如 myapp.dev、stripe-api.prod)。同时读取 ENVSEC_CONTEXT 环境变量
  • --debug、-d — 启用调试日志
  • --json — 以 JSON 格式输出,便于脚本处理
  • --db — SQLite 数据库文件的路径(默认:~/.envsec/store.sqlite)。同时读取 ENVSEC_DB 环境变量

自定义数据库路径

默认情况下,元数据存储在 ~/.envsec/store.sqlite。你可以通过 --db 或 ENVSEC_DB 环境变量覆盖此路径:

# Use a project-local database
envsec --db ./local-store.sqlite -c myapp.dev list

# Or via environment variable
export ENVSEC_DB=/shared/team/envsec.sqlite
envsec -c myapp.dev list

--db 标志优先于 ENVSEC_DB。使用场景包括按项目划分的数据库、网络驱动器上的团队共享数据库,以及使用临时存储的 CI/CD。

添加密钥

将密钥存储到操作系统凭据存储中。

  • <key> — 密钥名称(例如 api.key、db.password)
  • --value、-v — 要存储的值(省略则进入交互式掩码输入提示)
  • --expires、-e — 过期时长(例如 30m、2h、7d、4w、3mo、1y)
# Store a value inline
envsec -c myapp.dev add api.key --value "sk-abc123"

# Or use the short alias
envsec -c myapp.dev add api.key -v "sk-abc123"

# Omit --value for an interactive masked prompt
envsec -c myapp.dev add api.key

# Set an expiry duration with --expires (-e)
envsec -c myapp.dev add api.key -v "sk-abc123" --expires 30d

# Supported duration units: m (minutes), h (hours), d (days), w (weeks), mo (months), y (years)
# Combinable: 1y6mo, 2w3d, 1d12h
envsec -c myapp.dev add api.key -v "sk-abc123" -e 6mo

获取密钥

从操作系统凭据存储中检索密钥值。

  • <key> — 要检索的密钥名称
  • --quiet、-q — 仅打印原始值(无警告或额外输出)
  • --json — 以 JSON 格式输出(包含 context、key、value、expires_at)
envsec -c myapp.dev get api.key

# Print only the raw value (no warnings or extra output)
envsec -c myapp.dev get api.key --quiet
envsec -c myapp.dev get api.key -q

删除密钥

从操作系统凭据存储中移除密钥。

  • <key> — 要删除的密钥名称(如果使用 --all 则为可选)
  • --yes,-y — 跳过确认提示
  • --all — 删除上下文中的所有密钥
envsec -c myapp.dev delete api.key

# or use the alias
envsec -c myapp.dev del api.key

重命名密钥

在同一上下文中重命名密钥。值和过期元数据将被保留。

  • <old-key> — 当前密钥名称
  • <new-key> — 新密钥名称
  • --force、-f — 如果目标已存在则覆盖
# Rename a key
envsec -c myapp.dev rename old.key new.key

# Overwrite target if it already exists
envsec -c myapp.dev rename old.key existing.key --force

列出上下文中的所有密钥

列出上下文中的所有密钥键和元数据。

  • --json — 以 JSON 格式输出
envsec -c myapp.dev list

列出所有上下文

列出所有可用的上下文及其密钥数量。

  • --json — 以 JSON 格式输出
# Without --context, lists all available contexts with secret counts
envsec list

搜索密钥

使用 glob 模式搜索密钥或上下文。

  • <pattern> — 要搜索的 glob 模式(例如 api.*、myapp.*)
  • --json — 以 JSON 格式输出
# Search secrets within a context
envsec -c myapp.dev search "api.*"

# Search contexts by pattern (without --context)
envsec search "myapp.*"

在上下文之间移动密钥

将密钥从一个上下文移动到另一个上下文。移动后,源密钥将被移除。

  • <pattern> — 要移动的 Glob 模式或精确密钥(如果使用 --all 则可选)
  • --to、-t — 要将密钥移动到的目标上下文
  • --all — 从源上下文移动所有密钥
  • --force、-f — 覆盖目标上下文中现有的密钥
  • --yes、-y — 跳过确认提示
# Move a single secret
envsec -c myapp.dev move api.token --to myapp.prod

# Move secrets matching a glob pattern
envsec -c myapp.dev move "redis.*" --to myapp.prod -y

# Move all secrets from one context to another
envsec -c myapp.dev move --all --to myapp.prod -y

# Overwrite existing secrets in the target context
envsec -c myapp.dev move "redis.*" --to myapp.prod --force -y

在上下文之间复制密钥

将密钥从一个上下文复制到另一个上下文。源密钥保持不变。

  • <pattern> — 要复制的 Glob 模式或精确密钥(如果使用 --all 则可选)
  • --to、-t — 要将密钥复制到的目标上下文
  • --all — 从源上下文复制所有密钥
  • --force、-f — 覆盖目标上下文中现有的密钥
  • --yes、-y — 跳过确认提示
# Copy a single secret
envsec -c myapp.dev copy api.token --to myapp.staging

# Copy secrets matching a glob pattern
envsec -c myapp.dev copy "redis.*" --to myapp.staging -y

# Copy all secrets from one context to another
envsec -c myapp.dev copy --all --to myapp.staging -y

# Overwrite existing secrets in the target context
envsec -c myapp.dev copy "redis.*" --to myapp.staging --force -y

使用密钥运行命令

执行命令时,通过占位符插值或作为环境变量注入密钥值。

  • <command> — 要执行的命令。使用 {key} 占位符进行密钥插值
  • --inject、-i — 将所有上下文密钥作为环境变量注入(KEY.NAME → KEY_NAME)
  • --save、-s — 保存此命令以供后续使用
  • --name、-n — 已保存命令的名称(若与 --save 一起省略,则交互式提示输入)
# Placeholders {key} are resolved with secret values before execution
envsec -c myapp.dev run 'curl {api.url} -H "Authorization: Bearer {api.token}"'

# Any {dotted.key} in the command string is replaced with its value
envsec -c myapp.prod run 'psql {db.connection_string}'

# Inject ALL context secrets as environment variables (KEY.NAME → KEY_NAME)
envsec -c myapp.dev run --inject 'node server.js'
envsec -c myapp.dev run -i 'docker compose up'

# Combine --inject with placeholders
envsec -c myapp.dev run --inject 'curl {api.url} -H "Authorization: Bearer $API_TOKEN"'

# Save the command for later use with --save (-s) and --name (-n)
envsec -c myapp.dev run --save --name deploy 'kubectl apply -f - <<< {k8s.manifest}'

# If you use --save without --name, you'll be prompted interactively
envsec -c myapp.dev run --save 'psql {db.connection_string}'

如果任何占位符引用了不存在的密钥,命令将不会执行,你会看到明确的错误提示:

分类