# @asafarim/envage 中文文档

规范地址：https://npmcn.com/package/%40asafarim/envage/

版本：0\.5\.0
npm 元数据更新时间：2026-11-04T13:04:36.693Z
中文译文更新时间：2026-11-07T09:10:36.213Z
软件包许可：MIT

本文由上游 README 翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/%40asafarim/envage
原文对照：https://npmcn.com/package/%40asafarim/envage/?lang=original
项目主页：https://alisafari-it.github.io/envage
源码仓库：https://github.com/AliSafari-IT/envage

## 关键信息（来自 npm 元数据）

- 包体积（解压后）：123 kB，75 个文件
- 模块格式：ES Module
- TypeScript 类型：包内自带
- Node.js 要求：\>=20\.0\.0
- 运行依赖：3 个
- 首次发布：2026-05-21T20:39:27.419Z
- 最新版本发布：2026-11-04T13:04:36.459Z
- 近 30 天下载量：1967（2026-10-07 至 2026-11-05，npm 官方下载统计）
- 已发布版本数：10（近 12 个月 10 个）

## 中文简介

对 .env 文件进行安全、基于年龄的加密/解密, 跨越多个环境和单一repo app文件夹

## 安装

```sh
npm install @asafarim/envage
```

也可以使用：`pnpm add @asafarim/envage`、`yarn add @asafarim/envage`、`bun add @asafarim/envage`

## README

# 自信地提交加密的.env文件

### @asafarim/envag TS套件

> **安全、基于年龄的加密 `.env` 横跨 monrepo 环境的文件.**

`envage` 让您安全地执行加密任务 `.env` 保存到 Git 的文件 解密解密出版本控制. 它使用战斗测试 [年龄](https://age-encryption.org/) 加密格式——与使用的工具相同 Go, Rust, and DevSecOps toolchains worldwide. 滚,鲁斯特,和DevSecOps 工具链全球.

* * *

## 特征

-   🔐 **年龄加密** - 用途 `age-encryption` (纯类型脚本,无原生道克)
-   🌍 **多种环境** —— 说 `dev`, (中文(简体) ), `staging`, (中文(简体) ), `prod`,任何自定义名称,或 `root` 为平地 `.env` 文件
-   📁 **单发觉** - 立即加密/解密所有应用程序 `--all`
-   👥 **团队接受者** ——独立身份解密共享密码;无私钥共享
-   🔑 **密钥或密码句** ——支持 X25519 密钥派和基于密码口的加密
-   🛡 **吉特安全系统** 自动更新 `.gitignore`; 警告您是否设置已解密的文件
-   ✅ **生产警卫** ——解密所需的交互确认 `prod` 文件
-   🧩 **程序化 API** ——在您自己的脚本中用作库
-   📦 **pnpm / 单重力** 与 pnpm 工作空间无缝工作

* * *

## 兼容性

需要20号或更新的节点。 信封没有反应依赖性或对等版本 限制并工作在React 18和React 19项目工具. 其综合指数和 文件系统 API 在 Node.js 中运行,外部浏览器发送组件. 演示 使用React 18,在CI中有一个单独的React 19构建. 演示默认为黑暗 模式,记住您的主题选择,并包含 CLI/API 团队接收实例 和与当前里程碑相联系的路线图.

## 安装

```bash
# In your monorepo root
pnpm add -D @asafarim/envage

# Or globally
pnpm add -g @asafarim/envage
```

* * *

## 快速启动

### 1\. 生成键盘

```bash
npx envage init-key
```

这就产生了:

```
.age/key.txt   ← private key (mode 0600, gitignored automatically)
.age/key.pub   ← public key  (safe to share with teammates)
```

### 2\. 创建您的配置

```bash
# envage.config.json (add it to the monorepo root)
# use relative paths from the monorepo root
# use 'root' for the .env files regardless of environment, 'dev' for development environment .env.dev, 'staging' for staging environment .env.staging, 'prod' for production environment .env.prod
# use '.' for the current directory (monorepo root): "apps": [".", "apps/web"],
{
  "apps": [".", "apps/web", "apps/admin", "packages/api"],
  "envs": ["root", "dev", "staging", "prod"],
  "keyFile": ".age/key.txt"
}
```

### 3\. 加密您的内存文件

```bash
# Encrypt a single app/env
npx envage encrypt apps/web --env dev

# Encrypt all apps at once
npx envage encrypt --all --env prod

# Encrypt plain .env files across all apps (one environment per invocation)
npx envage encrypt --all --env root
```

### 4\. 检查情况

```bash
npx envage status
```

```
apps/web
  dev        🔒 encrypted
  staging    🔒 encrypted
  prod       🔒 encrypted

apps/admin
  dev        🔓 decrypted (not yet encrypted)
  prod       🔒 encrypted

packages/api
  dev        🔒 encrypted
  prod       🔒 encrypted

9 entries — 8 encrypted  1 decrypted
```

### 5\. 在新机器上解密

```bash
# Restore your own private identity from secure backup, or have an authorized
# teammate add your new public recipient (see Team encryption below).
npx envage decrypt apps/web --env dev

# Decrypt all at once
npx envage decrypt --all --env dev
```

* * *

## CLI 参考

### `envage init-key`

生成新时代的X25519 keypair.

```bash
envage init-key [--output <folder>]
```

| 选项 | 默认 | 说明 |
| --- | --- | --- |
| `--output` | `.age` | 输出文件夹 `key.txt` 财务报告和审定财务报表 `key.pub` |

* * *

### `envage encrypt`

加密 `.env.<env>` → `.env.<env>.age` (或 `.env` → `.env.age` 何时 `--env root`) (中文(简体) ).

```bash
envage encrypt [path] [options]
```

| 选项 | 默认 | 说明 |
| --- | --- | --- |
| `--env` | `dev` | 环境名称 |
| `--key` | 自动检测 | 年龄密钥文件路径 |
| `--passphrase` | —— 说 | 密码句( 如果省略了 ) |
| `--all` | —— 说 | 加密所有应用程序 `envage.config.json` |

**实例:**

```bash
envage encrypt apps/web --env dev
envage encrypt apps/web --env prod --key .age/key.txt
envage encrypt --all --env staging
envage encrypt apps/web --env dev --passphrase "my secret"

# Root env — targets the plain .env file (no suffix)
envage encrypt apps/portal --env root
envage encrypt --all --env root
```

* * *

### `envage decrypt`

解密 `.env.<env>.age` → `.env.<env>` (或 `.env.age` → `.env` 何时 `--env root`) (中文(简体) ).

```bash
envage decrypt [path] [options]
```

| 选项 | 默认 | 说明 |
| --- | --- | --- |
| `--env` | `dev` | 环境名称 |
| `--key` | 自动检测 | 年代私钥文件路径 |
| `--passphrase` | —— 说 | 密码句 |
| `--all` | —— 说 | 解密所有应用程序 `envage.config.json` |

> 解密 `prod` 或者说 `production` 环境总是促使 手动确认.

**实例:**

```bash
envage decrypt apps/web --env dev
envage decrypt --all --env prod

# Root env — targets .env.age → .env
envage decrypt apps/portal --env root
envage decrypt --all --env root
```

* * *

### `envage recipient add/list/remove`

管理团队成员并重新加密所有已配置的密码文本 . `add` 财务报告和审定财务报表 `remove` 带一个完整的公共收件人 加上可选 `--key <identity-file>`。 。 。 . 见 [团队加密](https://npmcn.com/package/%40asafarim/envage/#readme-team-encryption-v050) 用于配置、恢复和撤销限制.

### `envage status`

显示所有配置的应用程序和环境的加密状态 .

```bash
envage status [path]
```

| 选项 | 说明 |
| --- | --- |
| `--env` | 过滤输出到单个环境 |

* * *

## 配置 - `envage.config.json`

将此文件放入您单曲的根 :

```json
{
  "apps": [
    "apps/web",
    "apps/admin",
    "packages/api"
  ],
  "envs": ["dev", "staging", "prod"],
  "keyFile": ".age/key.txt",
  "keyPubFile": ".age/key.pub"
}
```

### 根内-平面 `.env` 文件

使用 `"root"` 作为锁定赤裸的巢穴名称 `.env` 每个应用程序文件夹中的文件(无后缀). 这对已经使用单个的项目有用 `.env` 并且不想重命名它.

```json
{
  "apps": [".", "apps/web", "apps/admin", "packages/api"],
  "envs": ["root", "dev", "staging", "prod"],
  "keyFile": ".age/key.txt"
}
```

| 内存名称 | 纯文本文件 | 加密文件 |
| --- | --- | --- |
| `root` | `.env` | `.env.age` |
| `dev` | `.env.dev` | `.env.dev.age` |
| `staging` | `.env.staging` | `.env.staging.age` |
| `prod` | `.env.prod` | `.env.prod.age` |

### 球形图案在 `apps`

App 条目可能使用 glob 模式, 相对于文件系统扩展 选择 **目录** 这是存在的。 这对单簧管有帮助 你不想逐个列出.

```json
{
  "apps": [".", "apps/*", "packages/*"],
  "envs": ["root", "production"],
  "keyFile": ".age/key.txt",
  "keyPubFile": ".age/key.pub"
}
```

-   `*` 匹配单个路径段(例如). `apps/*` → `apps/web`, (中文(简体) ), `apps/admin`) (中文(简体) ).
-   `**` 匹配任何深度的嵌入目录.
-   只匹配已有目录; 文件被忽略 .
-   非 glob 条目( 如 `.` 或者说 `apps/web`) 保存为-s,即使文件夹 目前还不存在.
-   结果是去重复的,所以重叠的模式是安全的.

### 配置字段

| 外地 | 类型 | 默认 | 说明 |
| --- | --- | --- | --- |
| `apps` | `string[]` | `[]` | App文件夹路径( 相对 cwd) 。 支持球状图案(见下文) |
| `envs` | `string[]` | `["dev","staging","prod"]` | 管理的环境名称 |
| `keyFile` | `string` | `.age/key.txt` | 私钥路径 |
| `keyPubFile` | `string` | `.age/key.pub` | 公钥路径 |
| `recipients` | `string[]` | 删除 | 公共年龄接受者; 省略保留遗留的单键模式 |

* * *

## 程序化 API

```typescript
import {
  encryptEnv,
  decryptEnv,
  generateKeyPair,
  generateKeyPairToFolder,
  getEnvStatus,
  loadConfig,
  resolveApps,
  ensureGitignore,
  updateRecipient,
} from "@asafarim/envage";

// Generate a keypair
const { identity, recipient } = await generateKeyPair();

// Write keypair to disk
await generateKeyPairToFolder(".age");

// Encrypt a named env file (.env.dev → .env.dev.age)
await encryptEnv({
  folder: "apps/web",
  env: "dev",
  keyFile: ".age/key.txt",
});

// Encrypt the root env (.env → .env.age)
await encryptEnv({
  folder: "apps/portal",
  env: "root",
  keyFile: ".age/key.txt",
});

// Passphrase-based encryption
await encryptEnv({
  folder: "apps/web",
  env: "dev",
  passphrase: "my-secret-passphrase",
});

// Decrypt a named env file (.env.dev.age → .env.dev)
await decryptEnv({
  folder: "apps/web",
  env: "dev",
  keyFile: ".age/key.txt",
});

// Decrypt the root env (.env.age → .env)
await decryptEnv({
  folder: "apps/portal",
  env: "root",
  keyFile: ".age/key.txt",
});

// Expand app globs ("apps/*") to actual folder paths
const config = await loadConfig();
const folders = await resolveApps(config);
// → ["/repo/apps/web", "/repo/apps/admin", ...]

// Check status (globs in config are expanded automatically)
const statuses = await getEnvStatus(config);
statuses.forEach((s) => {
  console.log(`${s.folder} [${s.env}]: encrypted=${s.encrypted} decrypted=${s.decrypted}`);
});

// Ensure .gitignore rules are present
await ensureGitignore();
```

* * *

## 团队加密(v0.5.0)

每个队友跑 `envage init-key` 当地份额 **仅限** 他们的公众 `key.pub`将私人身份保存在他们所有者的机器上或安全备份中. 现有获得授权的成员可登上另一个公共接收人:

```bash
envage recipient add age1... --key .age/key.txt
envage recipient list
envage recipient remove age1... --key .age/key.txt
```

替换 `age1...` 完全年龄的X25519公用钥匙。 命令从 项目根并需要已有 `envage.config.json` 无空 `apps` 财务报告和审定财务报表 `envs`添加/重新加密 **所有已存在的密码文本** 在那些配置中 插槽,包括被扩大的应用程序和 `root` 环境。 未配置的文件 不属于他们的范围。 缺少的密码文本被跳过 。 密码句加密或 不可解密的文件在替换开始前中止整个操作 .

公共收件人保存在版本配置中 :

```json
{
  "apps": [".", "apps/*"],
  "envs": ["root", "dev", "prod"],
  "keyFile": ".age/key.txt",
  "recipients": ["age1...", "age1..."]
}
```

将更新的配置和密码文本一起提交。 普通 CLI 加密用途 配置收件人, 即使当 `--key` ,不需要私钥. 明确 `--passphrase` 选择密码句加密。 无配置 `recipients` 保持传统的单键行为。 第一个 `recipient add` 保留所提供身份的公用钥匙作为初始授权成员. 重复的,无效的,未知的,或最后接收的清除请求安全地失败.

方案API接受明确的公共接受者:

```ts
await encryptEnv({ folder: "apps/web", env: "dev", recipients: [alicePublic, bobPublic] });
await updateRecipient("add", bobPublic, { cwd: projectRoot, keyFile: ".age/key.txt" });
```

`encryptEnv` 不自动装入配置; 通过 `config.recipients` 你自己来. 收件人仅在内存中更改解密, 绝不更改为纯文本文件 。 替换 使用同名目录的临时文件和原子重命名. 写作失败时, 完成的替换被卷回。 多文件替换为 **没有** 一个 文件系统交易: 不运行并行加密/配置作者。 锁 防止同时接收者更新。 原件和清单保存在 私营 `.envage-recovery-*` 目录直到成功或回滚成功. 在进程中断或回滚失败后, 停止所有写入, 恢复 **每个** 该目录中的原始列表 `manifest.json`,验证解密,然后 删除回收目录 `envage.config.json.lock`从不执行这些 回收文物。 在更改前保持安全备份或清理 Git 检查站 .

仅删除新加密文件的收件人屏蔽访问 。 旧吉特 历史 密码副本 以及以前学到的秘密. 如果必须取消访问, 则单独旋转基本的 API 证书 .

* * *

## Git 整合

### `.gitignore` 规则

运行 `envage init-key` 规则自动添加到您 `.gitignore`数字 :

```gitignore
# --- envage managed ---
# Decrypted env files — never commit
.env*
!.env*.age
!.env.example
!.env.template
# Age private key
.age/key.txt
# --- end envage ---
```

### 已分阶段文件警告

如果你不小心的话 `git add` 加密前解密的内存文件 `encrypt` 命令将抓取并退出 :

```
✖ You are trying to commit a decrypted env file.
✖ Only encrypted .age files are allowed.
  apps/web/.env.prod
```

### 可选: 承诺前钩

将此添加到 `.git/hooks/pre-commit` 完全防止意外犯罪:

```bash
#!/usr/bin/env bash
npx envage status 2>/dev/null | grep -q "decrypted" && \
  echo "❌ You have decrypted env files. Run: npx envage encrypt --all" && \
  exit 1
exit 0
```

* * *

## Monorepo 结构

```
monorepo/
├── .age/
│   ├── key.txt              ← private key (gitignored)
│   └── key.pub              ← public key  (commit this)
├── apps/
│   ├── web/
│   │   ├── .env.dev         ← decrypted (gitignored)
│   │   ├── .env.dev.age     ← encrypted (committed ✅)
│   │   ├── .env.prod        ← decrypted (gitignored)
│   │   └── .env.prod.age    ← encrypted (committed ✅)
│   ├── admin/
│   │   ├── .env.dev.age
│   │   └── .env.prod.age
│   └── portal/              ← app using root env (plain .env)
│       ├── .env             ← decrypted (gitignored)
│       ├── .env.age         ← encrypted (committed ✅)
│       └── .env.staging.age ← encrypted (committed ✅)
├── packages/
│   └── api/
│       ├── .env.dev.age
│       └── .env.prod.age
├── envage.config.json       ← committed ✅
└── .gitignore               ← auto-updated by envage
```

* * *

## 安全说明

-   **永不承诺或共享 `.age/key.txt`** - 这是你的私人身份. 给每个队友自己的身份,只增加他们的公收人.
-   **解密的数值从未被记录** ——不采用动词模式,不采用出错模式
-   **生产解密设闸** - 总是要求明确 `y` 确认
-   **加密文件为 二进制** ——不能不小心读作正文
-   这个 `age` 格式提供认证加密; 篡改可被检测到

* * *

## 发展

```bash
# Install dependencies
pnpm install

# Build
pnpm build

# Run tests
pnpm test

# Type-check only
pnpm lint
```

* * *

## 许可证

麻省理工学院 [阿里·萨法里姆](https://github.com/asafarim)

## 常见问题

### @asafarim/envage 是什么？

对 \.env 文件进行安全、基于年龄的加密/解密, 跨越多个环境和单一repo app文件夹

### 如何安装 @asafarim/envage？

在项目目录运行 npm install @asafarim/envage，或使用 pnpm add / yarn add / bun add。它还提供命令行工具 envage，可以用 npx envage 直接运行。

### @asafarim/envage 支持 TypeScript 吗？

支持。包内自带 TypeScript 类型声明（package\.json 声明了 types 入口），安装后即可获得类型提示，无需再安装 @types 包。

### @asafarim/envage 支持 ESM 还是 CommonJS？

以 ES Module 形式发布，推荐使用 import 引入。在 CommonJS 项目中，Node\.js 20\.19\+ / 22\.12\+ 可以直接 require\(\) 不含顶层 await 的 ES Module，更早的版本需要改用动态 import\(\)。

### @asafarim/envage 需要什么版本的 Node\.js？

package\.json 的 engines 字段要求 Node\.js \>=20\.0\.0。版本不符时 npm 默认只给出警告，开启 engine-strict 后会拒绝安装。

### @asafarim/envage 可以商用吗？

@asafarim/envage 使用 MIT 许可。宽松许可：允许商业使用、修改和再分发，通常只需在分发时保留原版权与许可声明。以上为概括，不构成法律意见，请以许可原文为准。

### @asafarim/envage 的下载量有多少？

根据 npm 官方下载统计，@asafarim/envage 在 2026/10/07 – 2026/11/05 这 30 天内被下载 1,967 次，日均约 66 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入，适合横向比较热度，不能直接等同于使用人数。

### @asafarim/envage 还在维护吗？

最新版本 0\.5\.0 发布于 2026/11/04（3 天前）；至今共发布 10 个版本，其中过去 12 个月发布了 10 个；首次发布于 2026/05/22。发布频率只是参考信号：功能稳定的工具可能很少需要更新，建议结合源码仓库的 issue 和提交记录判断。

