@zqw-cli/qenv
v1.0.4
Published
Cross-platform CLI for managing environment variables
Downloads
39
Maintainers
Readme
为什么选 qenv?
在不同操作系统上管理环境变量是件令人头疼的事:Windows 用 setx,macOS/Linux 要编辑 .bashrc 或 .zshrc,项目里还有 .env 文件需要维护……
qenv 将这一切统一为一行命令。
# 不管你在什么平台,设置环境变量永远是这一行
qenv set NODE_ENV production核心亮点
| 特性 | 说明 |
|------|------|
| 🌍 跨平台统一 | 同一命令在 Windows / macOS / Linux 上行为一致 |
| 📋 Manifest 追踪 | 记录每一个由 qenv 管理过的变量,支持 list、diff、clean |
| 🐚 Shell 集成 | 通过 qenv init 安装 wrapper,支持 --local 在当前终端立即生效 |
| 📁 .env 文件支持 | 用 --file 读写项目级 .env 文件,无需额外工具 |
| 📦 批量导入导出 | qenv import / qenv export 快速迁移环境配置 |
| 🎨 友好的终端输出 | 彩色图标、表格对齐、敏感值自动脱敏 |
目录
安装
要求: Node.js >= 16
npm install -g @zqw-cli/qenv安装后即可在任意终端中使用 qenv 命令:
qenv --version
# 1.0.0快速上手
1. 设置环境变量
# 设置用户级系统环境变量(永久生效,重启终端后可用)
qenv set NODE_ENV production
# 设置后覆盖已有的变量
qenv set NODE_ENV development --overwrite2. 读取环境变量
qenv get NODE_ENV
# NODE_ENV=production
# 只输出纯值(适合在脚本中使用)
qenv get NODE_ENV --raw
# production3. 使用 .env 文件
# 写入项目 .env 文件
qenv set DATABASE_URL postgres://localhost/mydb --file
# 写入指定的 .env 文件
qenv set API_KEY sk-xxx --file .env.local
# 查看 .env 文件中的所有变量
qenv list --file .env.local4. 批量操作
# 从 .env 文件批量导入到系统变量
qenv import .env.prod
# 先预览再导入
qenv import .env.prod --dry-run
# 导出所有 qenv 管理的变量到文件
qenv export .env.backup5. 查看与维护
# 列出所有由 qenv 管理的变量
qenv list
# 对比 manifest 记录与系统实际值
qenv diff
# 清理已失效的记录
qenv clean命令参考
💡 每个命令都支持
--help查看详细用法,例如qenv set --help。
qenv set
设置环境变量。
用法: qenv set <name> <value> [options]| 选项 | 说明 |
|------|------|
| --local | 仅在当前 Shell 会话中生效(需先运行 qenv init) |
| --system | 设置系统级变量(需管理员/sudo 权限) |
| --file [path] | 写入 .env 文件,默认路径为 ./.env |
| --json | 将 value 作为 JSON 解析并校验 |
| --overwrite | 如果变量已存在,强制覆盖 |
示例:
# 基础用法:设置用户级系统变量(永久)
qenv set NODE_ENV production
# 仅当前终端会话生效(需 qenv init)
qenv set API_KEY sk-xxx --local
# 写入项目 .env 文件
qenv set PORT 3000 --file
# 写入指定 .env 文件
qenv set PORT 3000 --file .env.local
# JSON 值校验
qenv set CONFIG '{"debug":true}' --json
# 覆盖已有变量
qenv set NODE_ENV development --overwrite行为说明:
- 默认会检查变量是否已存在,若已存在则提示使用
--overwrite - 不带
--file或--local时,变量写入当前用户的系统环境(永久生效) - 写入的变量会自动记录到 manifest 中,可通过
qenv list查看
qenv get
获取环境变量的值。
用法: qenv get <name> [options]| 选项 | 说明 |
|------|------|
| --source | 显示变量来源(qenv 管理 / 系统原有 / 文件) |
| --file [path] | 从 .env 文件读取,默认路径为 ./.env |
| --json | 以 JSON 格式输出 { name, value, source } |
| --raw | 仅输出纯值,不带任何前缀(适合 $() 嵌入脚本使用) |
示例:
# 读取系统变量
qenv get NODE_ENV
# NODE_ENV=production
# 查看变量来源
qenv get NODE_ENV --source
# NODE_ENV=production
# ℹ Source: qenv (system)
# 从 .env 文件读取
qenv get DATABASE_URL --file .env.prod
# 纯值输出(适合脚本嵌入)
echo "当前环境: $(qenv get NODE_ENV --raw)"
# JSON 格式
qenv get PORT --json
# {"name":"PORT","value":"3000","source":"qenv (system)"}行为说明:
--raw模式下,如果变量不存在,进程退出码为1,stdout 无输出- 不加
--raw时,变量不存在会输出⚠ Variable "XXX" not found
qenv remove
删除环境变量。别名:qenv rm。
用法: qenv remove <name> [options]| 选项 | 说明 |
|------|------|
| --system | 删除系统级变量(需管理员/sudo 权限) |
| --local | 从当前 Shell 会话中移除(需 qenv init) |
| --file [path] | 从 .env 文件中删除 |
| --force | 跳过确认提示,直接删除 |
| --all | 配合 --file 使用,清空文件中所有变量 |
示例:
# 删除用户级系统变量(会有确认提示)
qenv remove NODE_ENV
# 跳过确认直接删除
qenv remove NODE_ENV --force
# 从 .env 文件删除
qenv remove DATABASE_URL --file .env.prod
# 清空 .env 文件中所有变量
qenv remove --all --file
# 从当前会话移除(需 qenv init)
qenv remove API_KEY --local行为说明:
- 默认删除前会弹出确认提示
(y/N),使用--force跳过 - 删除成功后同时从 manifest 中清除记录
qenv list
列出环境变量。别名:qenv ls。
用法: qenv list [options]| 选项 | 说明 |
|------|------|
| --all | 列出系统中所有环境变量(等同 printenv) |
| --file [path] | 列出 .env 文件中的变量 |
| --json | 以 JSON 格式输出 |
| --verify | 检验 manifest 记录与系统实际值是否一致 |
| --stale | 仅显示已失效的 manifest 记录 |
示例:
# 列出 qenv 管理的变量(默认)
qenv list
# 输出示例:
# NAME VALUE SCOPE UPDATED
# ─────────────────────────────────────────────────────
# NODE_ENV pro***ion system 2 days ago
# API_KEY sk-***xxx system 1 hour ago
# DATABASE_URL (not found) ⚠ system 5 days ago
#
# ⚠ 1 stale entry found. Run `qenv clean` to remove.
# 列出所有系统变量
qenv list --all
# 列出 .env 文件变量
qenv list --file .env.prod
# 仅查看失效记录
qenv list --stale
# JSON 输出
qenv list --json输出说明:
VALUE列会自动脱敏显示(保留前 3 位和后 3 位,中间用***替代)UPDATED列显示上次更新的相对时间(如2 days ago、just now)- 系统中已不存在的变量会显示
(not found) ⚠标记 --all模式展示完整值,不做脱敏处理
qenv import
从 .env 文件批量导入环境变量。
用法: qenv import <file> [options]| 选项 | 说明 |
|------|------|
| --local | 导入到当前 Shell 会话(需 qenv init) |
| --dry-run | 预览将要导入的变量,不实际执行 |
| --overwrite | 覆盖已存在的变量 |
示例:
# 将 .env 文件中的变量导入为系统环境变量
qenv import .env
# 先预览,确认后再操作
qenv import .env.prod --dry-run
# ℹ Preview of import from .env.prod:
# + NODE_ENV=production
# + API_KEY=sk-xxx
# + PORT=3000
#
# Total: 3 variables
# 覆盖已存在的变量
qenv import .env --overwrite
# 导入到当前会话(需 qenv init)
qenv import .env.dev --local行为说明:
- 默认不覆盖已存在的变量,逐条跳过并提示
.env文件格式支持:KEY=VALUE、带引号KEY="VALUE"、注释# ...
qenv export
将环境变量导出为 .env 格式。
用法: qenv export [file] [options]| 选项 | 说明 |
|------|------|
| --all | 导出系统中所有环境变量 |
| --filter <prefix> | 仅导出匹配指定前缀的变量 |
示例:
# 导出 qenv 管理的变量到 stdout
qenv export
# 导出到文件
qenv export .env.backup
# 导出所有系统变量
qenv export env-full.txt --all
# 仅导出特定前缀的变量
qenv export --filter REACT_APP_
qenv export .env.react --filter REACT_APP_行为说明:
- 不指定文件时输出到 stdout,可配合管道使用:
qenv export | grep NODE - 默认只导出 manifest 中跟踪的变量,
--all则导出系统全部
qenv diff
对比 manifest 记录与系统中的实际值。
用法: qenv diff [options]| 选项 | 说明 |
|------|------|
| --json | 以 JSON 格式输出对比结果 |
示例:
qenv diff
# 输出示例:
# NAME SCOPE STATUS
# ─────────────────────────────────────────
# NODE_ENV system ✔ in sync
# API_KEY system ✔ in sync
# OLD_VAR system ✖ missing
#
# ⚠ 1 variable missing from system. Run `qenv clean` to remove stale entries.
qenv diff --json状态说明:
| 状态 | 含义 |
|------|------|
| ✔ in sync | manifest 记录的变量在系统中存在 |
| ✖ missing | manifest 中记录了但系统中已不存在 |
qenv clean
清理 manifest 中的失效记录。
用法: qenv clean [options]| 选项 | 说明 |
|------|------|
| --force | 跳过确认提示,直接清理 |
示例:
# 交互式清理(有确认提示)
qenv clean
# ℹ Found 2 stale entries:
# ⚠ OLD_VAR_1
# ⚠ OLD_VAR_2
#
# Remove these stale entries from manifest? (y/N)
# 跳过确认直接清理
qenv clean --forceqenv init
安装 Shell 集成(wrapper function),以支持 --local 模式。
用法: qenv init [options]| 选项 | 说明 |
|------|------|
| --shell <type> | 指定 Shell 类型:bash / zsh / fish / pwsh |
| --print | 仅打印 wrapper 代码,不自动安装 |
| --uninstall | 从配置文件中移除 wrapper |
示例:
# 自动检测当前 Shell 并安装
qenv init
# 指定 Shell 类型
qenv init --shell zsh
# 只查看代码,不安装
qenv init --print
# 卸载 Shell 集成
qenv init --uninstall详见 Shell 集成详解。
全局选项
以下选项可与任意命令组合使用:
| 选项 | 说明 |
|------|------|
| -V, --version | 输出版本号 |
| -h, --help | 显示帮助信息 |
| --no-color | 禁用终端彩色输出 |
| --silent | 禁止所有 stdout 输出(仅保留 stderr 错误信息) |
| --verbose | 输出调试信息(驱动层调用详情) |
# 无色输出(适合重定向到文件)
qenv list --no-color > vars.txt
# 静默模式(CI 中使用)
qenv set CI true --silent
# 调试模式
qenv set NODE_ENV test --verboseShell 集成详解
为什么需要 Shell 集成?
qenv set NAME value 默认将变量写入系统环境(永久但需重启终端),如果你希望变量在当前终端窗口立即可用,需要使用 --local 模式。
然而,一个子进程(qenv CLI)无法直接修改父进程(你的终端)的环境变量。为了解决这个限制,qenv 使用了 shell wrapper + eval 机制:
qenv init在你的 Shell 配置文件中安装一个 wrapper function- 调用
qenv set NAME value --local时,wrapper 实际执行的是qenv --shell-eval set NAME value --local - qenv 在
--shell-eval模式下只向 stdout 输出一行 shell 表达式(如export NAME="value") - wrapper 用
eval执行这行表达式,从而修改当前 Shell 会话的环境
各 Shell 的 wrapper 代码
Bash / Zsh(写入 ~/.bashrc 或 ~/.zshrc):
# qenv shell integration
qenv() { eval "$(command qenv --shell-eval "$@")"; }
# end qenvFish(写入 ~/.config/fish/config.fish):
# qenv shell integration
function qenv
eval (command qenv --shell-eval $argv)
end
# end qenvPowerShell(写入 $PROFILE):
# qenv shell integration
function qenv { $result = & qenv.cmd --shell-eval @args; if ($result) { Invoke-Expression $result } }
# end qenv手动安装
如果不想自动修改配置文件,可以用 --print 查看代码后手动添加:
qenv init --print工作原理
平台驱动层
qenv 根据 process.platform 自动选择合适的驱动:
| 平台 | 用户级操作 | 系统级操作 (--system) |
|------|-----------|----------------------|
| Windows | setx NAME "value"(写入 HKCU\Environment) | reg add HKLM\...\Environment(需管理员) |
| macOS | 追加 export NAME="value" # qenv:managed 到 ~/.zshrc | 写入 /etc/environment(需 sudo) |
| Linux | 追加 export NAME="value" # qenv:managed 到 ~/.bashrc | 写入 /etc/environment(需 sudo) |
| .env 文件 | 直接读写指定的 .env 文件 | — |
Unix 驱动细节:
- 使用注释标记
# qenv:managed管理 Shell 配置文件中的行 - 更新变量时通过正则精准替换已标记的行,不会产生重复条目
- 自动检测当前 Shell 类型,选择正确的配置文件
Windows 驱动细节:
- 用户级变量使用
setx命令,系统级使用reg add操作注册表 - 设置变量后自动广播
WM_SETTINGCHANGE消息,通知其他进程刷新环境 - 自动校验值长度,超过
setx的 1024 字符限制时提前报错
Manifest 机制
qenv 使用 conf 库将 manifest 持久化到用户配置目录:
| 平台 | 路径 |
|------|------|
| macOS / Linux | ~/.config/qenv/config.json |
| Windows | %APPDATA%\qenv\config.json |
数据结构示例:
{
"version": 1,
"vars": {
"NODE_ENV": {
"scope": "system",
"filePath": null,
"setAt": "2026-03-16T10:00:00Z",
"updatedAt": "2026-03-16T12:00:00Z",
"setBy": "[email protected]"
},
"DATABASE_URL": {
"scope": "file",
"filePath": "D:\\projects\\myapp\\.env",
"setAt": "2026-03-16T09:00:00Z",
"updatedAt": "2026-03-16T09:00:00Z",
"setBy": "[email protected]"
}
}
}字段说明:
| 字段 | 说明 |
|------|------|
| scope | system(用户级永久)/ system-wide(系统级)/ file(.env 文件) |
| filePath | 仅 scope=file 时有值,记录 .env 文件的绝对路径 |
| setAt | 首次设置时间(ISO 8601 格式) |
| updatedAt | 最近一次更新时间 |
| setBy | 写入时的 qenv 版本号 |
⚠️ 重要边界: manifest 仅记录"qenv 操作过哪些变量",不独占管理权。如果用户或其他工具直接修改了同一变量,qenv 不会阻止,但
qenv diff可以发现变量已被删除(missing)。
Scope 说明
| Scope | 触发方式 | 生效范围 | 持久性 |
|-------|---------|---------|--------|
| system(默认) | qenv set NAME value | 新终端窗口 | ✅ 永久 |
| system-wide | qenv set NAME value --system | 所有用户的新终端 | ✅ 永久 |
| session | qenv set NAME value --local | 仅当前终端窗口 | ❌ 关闭即失效 |
| file | qenv set NAME value --file | 取决于应用是否读取 | ✅ 文件存在即有效 |
常见用法示例
CI/CD 中批量设置环境变量
# 从密钥管理中导出 .env 文件,然后导入到系统
qenv import .env.ci --overwrite --silent在脚本中获取值
# Bash / Zsh
DB_HOST=$(qenv get DB_HOST --raw)
echo "连接到数据库: $DB_HOST"# PowerShell
$dbHost = qenv get DB_HOST --raw
Write-Host "连接到数据库: $dbHost"在不同 .env 文件间切换
# 查看各环境配置
qenv list --file .env.dev
qenv list --file .env.staging
qenv list --file .env.prod
# 导入开发环境配置到当前会话
qenv import .env.dev --local导出特定前缀的变量
# 只导出 React 应用相关变量
qenv export .env.react --filter REACT_APP_
# 只导出 AWS 相关变量到 stdout
qenv export --filter AWS_项目初始化模板
# 为新同事快速搭建开发环境
qenv import .env.example --overwrite
qenv list --verify定期维护 manifest
# 检查是否有过期的记录
qenv diff
# 自动清理所有失效记录
qenv clean --force注意事项与限制
Windows 平台
| 限制 | 说明 |
|------|------|
| setx 字符上限 | 值不能超过 1024 个字符,超出时 qenv 会提前报错 |
| 需重启终端 | 通过 setx 设置的变量需要打开新终端窗口才能生效 |
| 管理员权限 | --system 模式需要以管理员身份运行终端 |
💡 提示: 使用
--local模式可以避免重启终端的问题,变量立即在当前窗口生效。
macOS / Linux 平台
| 限制 | 说明 |
|------|------|
| 需 source 配置 | 修改 .bashrc / .zshrc 后需 source 或重启终端才能生效 |
| sudo 权限 | --system 操作 /etc/environment 需要 sudo |
| Shell 兼容 | 已内置支持 Bash、Zsh、Fish;其他 Shell 可用 qenv init --print 手动适配 |
通用限制
| 限制 | 说明 |
|------|------|
| 变量名规则 | 必须匹配 /^[A-Za-z_][A-Za-z0-9_]*$/(字母或下划线开头) |
| 不存储值 | manifest 仅记录元信息,不缓存变量的实际值 |
| 非独占管理 | 其他工具可修改同一变量,qenv 不阻止但 diff 可检测差异 |
开发指南
环境准备
git clone https://github.com/af-zqw/qenv.git
cd qenv
npm install📦 npm 包名为
@zqw-cli/qenv,CLI 命令名仍为qenv。
常用命令
| 命令 | 说明 |
|------|------|
| npm run build | 使用 tsup 构建,输出到 dist/ |
| npm run dev | 开发模式(watch,文件变更自动重新构建) |
| npm test | 运行 Vitest 单元测试 |
| npm link | 本地全局链接,方便开发调试 |
本地调试
# 构建
npm run build
# 直接运行
node dist/index.js --help
# 或全局链接后使用
npm link
qenv --help技术栈
| 工具 | 用途 |
|------|------|
| TypeScript | 类型安全的开发语言 |
| tsup | 零配置打包,输出 CJS + DTS,自动加 #!/usr/bin/env node |
| Commander.js | CLI 框架,链式 API,自动 --help 生成 |
| chalk | 终端彩色输出 |
| conf | 跨平台 JSON 持久化存储(manifest) |
| ora | 终端 spinner 加载动画 |
| Vitest | 快速单元测试框架 |
发布到 npm
# prepublishOnly 会自动执行 build + test
npm publish项目结构
qenv/
├── src/
│ ├── index.ts # CLI 入口:注册全部命令 + 全局选项 + --shell-eval 处理
│ ├── commands/
│ │ ├── set.ts # qenv set — 设置环境变量
│ │ ├── get.ts # qenv get — 读取环境变量
│ │ ├── remove.ts # qenv remove (rm) — 删除环境变量
│ │ ├── list.ts # qenv list (ls) — 列出变量 + 失效标记
│ │ ├── diff.ts # qenv diff + qenv clean — 对比 & 清理 manifest
│ │ ├── init.ts # qenv init — 安装/卸载 Shell 集成
│ │ └── import.ts # qenv import + qenv export — 批量导入导出
│ ├── drivers/
│ │ ├── types.ts # EnvDriver 接口定义(get/set/remove/list)
│ │ ├── index.ts # 驱动选择器(根据 process.platform)
│ │ ├── windows.ts # Windows 驱动(setx / reg add / reg query)
│ │ ├── unix.ts # Unix 驱动(读写 .bashrc / .zshrc / config.fish)
│ │ └── dotenv.ts # .env 文件驱动(解析、写入、保留注释)
│ ├── shell/
│ │ ├── detect.ts # Shell 类型自动检测(bash/zsh/fish/pwsh/cmd)
│ │ └── eval.ts # --shell-eval 输出 eval 表达式
│ ├── manifest/
│ │ └── index.ts # Manifest 管理器(基于 conf 库的单例)
│ └── utils/
│ ├── logger.ts # 统一日志输出(success/warn/error/info/table)
│ ├── validator.ts # 变量名校验 + .env 解析 + 序列化
│ └── platform.ts # 平台判断 + 权限检测 + Home 目录
├── tests/
│ ├── validator.test.ts # 校验器 & .env 解析测试(15 cases)
│ ├── dotenv.test.ts # .env 驱动集成测试(8 cases)
│ ├── platform.test.ts # 平台工具测试(2 cases)
│ ├── shell.test.ts # Shell 检测测试(2 cases)
│ └── manifest.test.ts # Manifest 结构测试(2 cases)
├── dist/ # 构建输出(.gitignore)
├── tsup.config.ts # tsup 构建配置
├── tsconfig.json # TypeScript 编译配置
├── vitest.config.ts # Vitest 测试配置
├── package.json # 包描述 & 脚本
├── .gitignore
└── README.md # 本文档