Skill: airoyi/seedance-2-0 (version 1.0.1)

--- name: seedance-2-0 display_name: Seedance 2.0 description: 字节跳动 Seedance 2.0 AI 视频生成技能，支持文生图、文生视频，提供申请指南和快速生成封装 version: 1.0.0 author: Zoe --- # Seedance 2.0 - 字节跳动AI视频生成技能 ## 功能描述 帮助用户申请开通 Seedance 2.0 白名单，并提供便捷的API调用封装，支持提示词配置化快速生成视频。 Seedance 2.0 是字节跳动最新的AI视频生成模型，支持文生视频、图生视频等功能。 ## 功能 1. **申请指南** - 引导未开通的用户通过邀请链接申请Seedance 2.0白名单 2. **快速生成** - 封装API调用，支持常见场景提示词模板配置化 3. **支持多种参数配置** - 模型选择、时长、分辨率、比例等 4. **下载结果** - 自动下载生成的视频文件到本地 ## 申请开通流程 ### 前置条件 - 和合作伙伴关联 - 企业实名认证（未实名无法申请） ### 申请步骤 1. 通过邀请链接注册/登录火山引擎合作伙伴平台 2. 提交申请后，提供公司名称 + 客户账号ID给渠道联系人 3. 内部帮忙申请开白 4. 留资报名通过后，在官网签署协议并下单购买 5. 开通后即可使用API生成视频 ## 权益差异 | 权益项 | 普通用户 | 保底客户 | 备注 | |--------|----------|----------|------| | 基本功能 | ✅ | ✅ | - | | 公共虚拟人像库 | ✅ | ✅ | - | | 信任Seedance产物 | ✅ | ✅ | - | | 信任Seedream产物 | ✅ | ✅ | - | | 排队序列 | ❌低优先级 | ✅高优先级 | 保底客户高优队列 | | 并发数 | ❌ 默认Pro 10 & fast 10，不支持提升 | ✅ | 可单独提升 | | 自定义虚拟人像库 | ❌ | ✅ | Hi-level客户专享 | | 真人人像 | ❌ | ✅ | Hi-level客户专享 | | 版权IP | ❌ | ✅ | Hi-level客户专享 | ## 配置 本技能读取环境变量 `ARK_API_KEY` 和 `ARK_BASE_URL` 配置： - `ARK_API_KEY` - 火山引擎API密钥（从火山引擎控制台获取） - `ARK_BASE_URL` - 默认 `https://ark.cn-beijing.volces.com/api/v3` - 默认模型：`doubao-seedance-1-5-pro` ## 使用方式 ### 申请开通 ``` 帮我申请开通Seedance 2.0 ``` 会输出完整的申请指南和邀请链接。 ### 生成视频 ``` 用seedance生成视频，提示词：... ``` 支持参数： - 模型选择（pro/fast/lite） - 时长（5s/10s/15s） - 比例（9:16/16:9/1:1） - 分辨率（720p/1080p） ## 合规说明 必须遵守内容审核： - 通用安全：禁涉黄、涉恐、涉敏 - 版权：禁未授权IP作品、公众人物、版权音乐 - 人脸：未开白直接拦截

path: README.md
content: # Seedance 2.0 Skill for OpenClaw

字节跳动 Seedance 2.0 AI视频生成技能，为 OpenClaw 提供开箱即用的视频生成能力，同时包含完整的申请开通指南。

## 功能特性

- 📋 **完整申请指南** - 引导用户通过邀请链接申请Seedance 2.0白名额
- 🎨 **提示词模板** - 内置常见场景提示词模板（宣传、活动、vlog等）
- ⚙️ **可配置参数** - 支持模型选择、时长、分辨率、比例等配置
- 📥 **自动下载** - 生成完成后自动下载视频文件到本地

## 安装依赖

```bash
cd /root/.openclaw/workspace/skills/seedance2.0
bun install
```

## 配置

复制环境变量模板：
```bash
cp .env.example .env
```

编辑 `.env` 文件，填入你的 `ARK_API_KEY`：
```
ARK_API_KEY=your-actual-api-key-here
```

## 使用

### 查看申请指南

```bash
bun run seedance2.0.ts --guide
```

这会输出完整的申请开通流程和邀请链接。

### 直接生成视频

```bash
# 使用自定义提示词
bun run seedance2.0.ts --prompt "麓湖社区丰富多彩的社群活动，邻里互动温馨热闹" --output output.mp4

# 使用模板 + 自定义提示词
bun run seedance2.0.ts --template promo --prompt "春季促销活动，限时5折优惠" --output promo.mp4

# 自定义参数
bun run seedance2.0.ts --prompt "产品演示" --model pro --duration 10 --ratio 16:9 --resolution 1080p --output video.mp4
```

## 可用模板

| 模板名 | 用途 |
|--------|------|
| promo | 产品宣传促销 |
| event | 活动预告 |
| vlog | 日常生活vlog |
| education | 知识科普 |
| marketing | 营销短视频 |

## 可用模型

| 模型名 | 模型ID | 说明 |
|--------|--------|------|
| pro | doubao-seedance-2-0-260128 | Seedance 2.0 Pro 最新版 |
| fast | doubao-seedance-1-0-fast | 快速版，生成更快 |
| lite | doubao-seedance-1-0-lite | 轻量版 |

## 完整参数说明

| 参数 | 说明 | 必填 | 默认值 |
|------|------|------|------|
| `--guide` | 输出申请开通指南 | 否 | - |
| `--prompt "text"` | 生成提示词 | 是* | - |
| `--template name` | 使用内置提示词模板 | 否* | - |
| `--model pro/fast/lite` | 选择模型 | 否 | `pro` |
| `--duration N` | 视频时长（秒），支持 5/10/16 | 否 | `5` |
| `--ratio 9:16/16:9/1:1` | 视频宽高比 | 否 | `9:16` |
| `--no-audio` | 关闭音频生成 | 否 | 默认开启 |
| `--watermark` | 开启水印 | 否 | 默认关闭 |
| `--ref-image URL` | 添加参考图片（可多次使用） | 否 | - |
| `--ref-video URL` | 添加参考视频（可多次使用） | 否 | - |
| `--ref-audio URL` | 添加参考音频（可多次使用） | 否 | - |
| `--output file.mp4` | 输出文件路径 | 否 | 自动生成 |

\* `--prompt` 和 `--template` 必须至少提供一个

## 申请开通

如果你还没有开通 Seedance 2.0 白名额，可以通过以下方式申请：

### 邀请链接
https://partner.volcengine.com/partners/auth/confirm?inviteToken=Z804VS6L0OUHUALB0UA450PEUPSJ4TYN4LA4JPO6F652OBSUUKI94FYKM5FL5YC2&partnerType=101&partnerName=%E6%99%BA%E7%BB%B4%E7%95%8C%EF%BC%88%E6%88%90%E9%83%BD%EF%BC%89%E7%A7%91%E6%8A%80%E6%9C%89%E9%99%90%E5%85%AC%E5%8F%B8&InvitationSource=1&ActivityCode=Seedance2.0

### 手机扫码
二维码文件存放在 `qrcode.png`，手机扫码直接绑定申请。

详细说明查看 [SKILL.md](./SKILL.md)


path: node_modules/dotenv/CHANGELOG.md
content: # Changelog

All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.

## [Unreleased](https://github.com/motdotla/dotenv/compare/v16.6.1...master)

## [16.6.1](https://github.com/motdotla/dotenv/compare/v16.6.0...v16.6.1) (2025-06-27)

### Changed

- Default `quiet` to true – hiding the runtime log message ([#874](https://github.com/motdotla/dotenv/pull/874))
- NOTICE: 17.0.0 will be released with quiet defaulting to false. Use `config({ quiet: true })` to suppress.
- And check out the new [dotenvx](https://github.com/dotenvx/dotenvx). As coding workflows evolve and agents increasingly handle secrets, encrypted .env files offer a much safer way to deploy both agents and code together with secure secrets. Simply switch `require('dotenv').config()` for `require('@dotenvx/dotenvx').config()`.

## [16.6.0](https://github.com/motdotla/dotenv/compare/v16.5.0...v16.6.0) (2025-06-26)

### Added

- Default log helpful message `[dotenv@16.6.0] injecting env (1) from .env` ([#870](https://github.com/motdotla/dotenv/pull/870))
- Use `{ quiet: true }` to suppress
- Aligns dotenv more closely with [dotenvx](https://github.com/dotenvx/dotenvx).

## [16.5.0](https://github.com/motdotla/dotenv/compare/v16.4.7...v16.5.0) (2025-04-07)

### Added

- 🎉 Added new sponsor [Graphite](https://graphite.dev/?utm_source=github&utm_medium=repo&utm_campaign=dotenv) - *the AI developer productivity platform helping teams on GitHub ship higher quality software, faster*.

> [!TIP]
> **[Become a sponsor](https://github.com/sponsors/motdotla)**
> 
> The dotenvx README is viewed thousands of times DAILY on GitHub and NPM.
> Sponsoring dotenv is a great way to get in front of developers and give back to the developer community at the same time.

### Changed

- Remove `_log` method. Use `_debug` [#862](https://github.com/motdotla/dotenv/pull/862)

## [16.4.7](https://github.com/motdotla/dotenv/compare/v16.4.6...v16.4.7) (2024-12-03)

### Changed

- Ignore `.tap` folder when publishing. (oops, sorry about that everyone. - @motdotla) [#848](https://github.com/motdotla/dotenv/pull/848)

## [16.4.6](https://github.com/motdotla/dotenv/compare/v16.4.5...v16.4.6) (2024-12-02)

### Changed

- Clean up stale dev dependencies [#847](https://github.com/motdotla/dotenv/pull/847)
- Various README updates clarifying usage and alternative solutions using [dotenvx](https://github.com/dotenvx/dotenvx)

## [16.4.5](https://github.com/motdotla/dotenv/compare/v16.4.4...v16.4.5) (2024-02-19)

### Changed

- 🐞 Fix recent regression when using `path` option. return to historical behavior: do not attempt to auto find `.env` if `path` set. (regression was introduced in `16.4.3`) [#814](https://github.com/motdotla/dotenv/pull/814)

## [16.4.4](https://github.com/motdotla/dotenv/compare/v16.4.3...v16.4.4) (2024-02-13)

### Changed

- 🐞 Replaced chaining operator `?.` with old school `&&` (fixing node 12 failures) [#812](https://github.com/motdotla/dotenv/pull/812)

## [16.4.3](https://github.com/motdotla/dotenv/compare/v16.4.2...v16.4.3) (2024-02-12)

### Changed

- Fixed processing of multiple files in `options.path` [#805](https://github.com/motdotla/dotenv/pull/805)

## [16.4.2](https://github.com/motdotla/dotenv/compare/v16.4.1...v16.4.2) (2024-02-10)

### Changed

- Changed funding link in package.json to [`dotenvx.com`](https://dotenvx.com)

## [16.4.1](https://github.com/motdotla/dotenv/compare/v16.4.0...v16.4.1) (2024-01-24)

- Patch support for array as `path` option [#797](https://github.com/motdotla/dotenv/pull/797)

## [16.4.0](https://github.com/motdotla/dotenv/compare/v16.3.2...v16.4.0) (2024-01-23)

- Add `error.code` to error messages around `.env.vault` decryption handling [#795](https://github.com/motdotla/dotenv/pull/795)
- Add ability to find `.env.vault` file when filename(s) passed as an array [#784](https://github.com/motdotla/dotenv/pull/784)

## [16.3.2](https://github.com/motdotla/dotenv/compare/v16.3.1...v16.3.2) (2024-01-18)

### Added

- Add debug message when no encoding set [#735](https://github.com/motdotla/dotenv/pull/735)

### Changed

- Fix output typing for `populate` [#792](https://github.com/motdotla/dotenv/pull/792)
- Use subarray instead of slice [#793](https://github.com/motdotla/dotenv/pull/793)

## [16.3.1](https://github.com/motdotla/dotenv/compare/v16.3.0...v16.3.1) (2023-06-17)

### Added

- Add missing type definitions for `processEnv` and `DOTENV_KEY` options. [#756](https://github.com/motdotla/dotenv/pull/756)

## [16.3.0](https://github.com/motdotla/dotenv/compare/v16.2.0...v16.3.0) (2023-06-16)

### Added

- Optionally pass `DOTENV_KEY` to options rather than relying on `process.env.DOTENV_KEY`. Defaults to `process.env.DOTENV_KEY` [#754](https://github.com/motdotla/dotenv/pull/754)

## [16.2.0](https://github.com/motdotla/dotenv/compare/v16.1.4...v16.2.0) (2023-06-15)

### Added

- Optionally write to your own target object rather than `process.env`. Defaults to `process.env`. [#753](https://github.com/motdotla/dotenv/pull/753)
- Add import type URL to types file [#751](https://github.com/motdotla/dotenv/pull/751)

## [16.1.4](https://github.com/motdotla/dotenv/compare/v16.1.3...v16.1.4) (2023-06-04)

### Added

- Added `.github/` to `.npmignore` [#747](https://github.com/motdotla/dotenv/pull/747)

## [16.1.3](https://github.com/motdotla/dotenv/compare/v16.1.2...v16.1.3) (2023-05-31)

### Removed

- Removed `browser` keys for `path`, `os`, and `crypto` in package.json. These were set to false incorrectly as of 16.1. Instead, if using dotenv on the front-end make sure to include polyfills for `path`, `os`, and `crypto`. [node-polyfill-webpack-plugin](https://github.com/Richienb/node-polyfill-webpack-plugin) provides these.

## [16.1.2](https://github.com/motdotla/dotenv/compare/v16.1.1...v16.1.2) (2023-05-31)

### Changed

- Exposed private function `_configDotenv` as `configDotenv`. [#744](https://github.com/motdotla/dotenv/pull/744)

## [16.1.1](https://github.com/motdotla/dotenv/compare/v16.1.0...v16.1.1) (2023-05-30)

### Added

- Added type definition for `decrypt` function

### Changed

- Fixed `{crypto: false}` in `packageJson.browser`

## [16.1.0](https://github.com/motdotla/dotenv/compare/v16.0.3...v16.1.0) (2023-05-30)

### Added

- Add `populate` convenience method [#733](https://github.com/motdotla/dotenv/pull/733)
- Accept URL as path option [#720](https://github.com/motdotla/dotenv/pull/720)
- Add dotenv to `npm fund` command
- Spanish language README [#698](https://github.com/motdotla/dotenv/pull/698)
- Add `.env.vault` support. 🎉 ([#730](https://github.com/motdotla/dotenv/pull/730))

ℹ️ `.env.vault` extends the `.env` file format standard with a localized encrypted vault file. Package it securely with your production code deploys. It's cloud agnostic so that you can deploy your secrets anywhere – without [risky third-party integrations](https://techcrunch.com/2023/01/05/circleci-breach/). [read more](https://github.com/motdotla/dotenv#-deploying)

### Changed

- Fixed "cannot resolve 'fs'" error on tools like Replit [#693](https://github.com/motdotla/dotenv/pull/693)

## [16.0.3](https://github.com/motdotla/dotenv/compare/v16.0.2...v16.0.3) (2022-09-29)

### Changed

- Added library version to debug logs ([#682](https://github.com/motdotla/dotenv/pull/682))

## [16.0.2](https://github.com/motdotla/dotenv/compare/v16.0.1...v16.0.2) (2022-08-30)

### Added

- Export `env-options.js` and `cli-options.js` in package.json for use with downstream [dotenv-expand](https://github.com/motdotla/dotenv-expand) module

## [16.0.1](https://github.com/motdotla/dotenv/compare/v16.0.0...v16.0.1) (2022-05-10)

### Changed

- Minor README clarifications
- Development ONLY: updated devDependencies as recommended for development only security risks ([#658](https://github.com/motdotla/dotenv/pull/658))

## [16.0.0](https://github.com/motdotla/dotenv/compare/v15.0.1...v16.0.0) (2022-02-02)

### Added

- _Breaking:_ Backtick support 🎉 ([#615](https://github.com/motdotla/dotenv/pull/615))

If you had values containing the backtick character, please quote those values with either single or double quotes.

## [15.0.1](https://github.com/motdotla/dotenv/compare/v15.0.0...v15.0.1) (2022-02-02)

### Changed

- Properly parse empty single or double quoted values 🐞 ([#614](https://github.com/motdotla/dotenv/pull/614))

## [15.0.0](https://github.com/motdotla/dotenv/compare/v14.3.2...v15.0.0) (2022-01-31)

`v15.0.0` is a major new release with some important breaking changes.

### Added

- _Breaking:_ Multiline parsing support (just works. no need for the flag.)

### Changed

- _Breaking:_ `#` marks the beginning of a comment (UNLESS the value is wrapped in quotes. Please update your `.env` files to wrap in quotes any values containing `#`. For example: `SECRET_HASH="something-with-a-#-hash"`).

..Understandably, (as some teams have noted) this is tedious to do across the entire team. To make it less tedious, we recommend using [dotenv cli](https://github.com/dotenv-org/cli) going forward. It's an optional plugin that will keep your `.env` files in sync between machines, environments, or team members.

### Removed

- _Breaking:_ Remove multiline option (just works out of the box now. no need for the flag.)

## [14.3.2](https://github.com/motdotla/dotenv/compare/v14.3.1...v14.3.2) (2022-01-25)

### Changed

- Preserve backwards compatibility on values containing `#` 🐞 ([#603](https://github.com/motdotla/dotenv/pull/603))

## [14.3.1](https://github.com/motdotla/dotenv/compare/v14.3.0...v14.3.1) (2022-01-25)

### Changed

- Preserve backwards compatibility on exports by re-introducing the prior in-place exports 🐞 ([#606](https://github.com/motdotla/dotenv/pull/606))

## [14.3.0](https://github.com/motdotla/dotenv/compare/v14.2.0...v14.3.0) (2022-01-24)

### Added

- Add `multiline` option 🎉 ([#486](https://github.com/motdotla/dotenv/pull/486))

## [14.2.0](https://github.com/motdotla/dotenv/compare/v14.1.1...v14.2.0) (2022-01-17)

### Added

- Add `dotenv_config_override` cli option
- Add `DOTENV_CONFIG_OVERRIDE` command line env option

## [14.1.1](https://github.com/motdotla/dotenv/compare/v14.1.0...v14.1.1) (2022-01-17)

### Added

- Add React gotcha to FAQ on README

## [14.1.0](https://github.com/motdotla/dotenv/compare/v14.0.1...v14.1.0) (2022-01-17)

### Added

- Add `override` option 🎉 ([#595](https://github.com/motdotla/dotenv/pull/595))

## [14.0.1](https://github.com/motdotla/dotenv/compare/v14.0.0...v14.0.1) (2022-01-16)

### Added

- Log error on failure to load `.env` file ([#594](https://github.com/motdotla/dotenv/pull/594))

## [14.0.0](https://github.com/motdotla/dotenv/compare/v13.0.1...v14.0.0) (2022-01-16)

### Added

- _Breaking:_ Support inline comments for the parser 🎉 ([#568](https://github.com/motdotla/dotenv/pull/568))

## [13.0.1](https://github.com/motdotla/dotenv/compare/v13.0.0...v13.0.1) (2022-01-16)

### Changed

* Hide comments and newlines from debug output ([#404](https://github.com/motdotla/dotenv/pull/404))

## [13.0.0](https://github.com/motdotla/dotenv/compare/v12.0.4...v13.0.0) (2022-01-16)

### Added

* _Breaking:_ Add type file for `config.js` ([#539](https://github.com/motdotla/dotenv/pull/539))

## [12.0.4](https://github.com/motdotla/dotenv/compare/v12.0.3...v12.0.4) (2022-01-16)

### Changed

* README updates
* Minor order adjustment to package json format

## [12.0.3](https://github.com/motdotla/dotenv/compare/v12.0.2...v12.0.3) (2022-01-15)

### Changed

* Simplified jsdoc for consistency across editors

## [12.0.2](https://github.com/motdotla/dotenv/compare/v12.0.1...v12.0.2) (2022-01-15)

### Changed

* Improve embedded jsdoc type documentation

## [12.0.1](https://github.com/motdotla/dotenv/compare/v12.0.0...v12.0.1) (2022-01-15)

### Changed

* README updates and clarifications

## [12.0.0](https://github.com/motdotla/dotenv/compare/v11.0.0...v12.0.0) (2022-01-15)

### Removed

- _Breaking:_ drop support for Flow static type checker ([#584](https://github.com/motdotla/dotenv/pull/584))

### Changed

- Move types/index.d.ts to lib/main.d.ts ([#585](https://github.com/motdotla/dotenv/pull/585))
- Typescript cleanup ([#587](https://github.com/motdotla/dotenv/pull/587))
- Explicit typescript inclusion in package.json ([#566](https://github.com/motdotla/dotenv/pull/566))

## [11.0.0](https://github.com/motdotla/dotenv/compare/v10.0.0...v11.0.0) (2022-01-11)

### Changed

- _Breaking:_ drop support for Node v10 ([#558](https://github.com/motdotla/dotenv/pull/558))
- Patch debug option ([#550](https://github.com/motdotla/dotenv/pull/550))

## [10.0.0](https://github.com/motdotla/dotenv/compare/v9.0.2...v10.0.0) (2021-05-20)

### Added

- Add generic support to parse function
- Allow for import "dotenv/config.js"
- Add support to resolve home directory in path via ~

## [9.0.2](https://github.com/motdotla/dotenv/compare/v9.0.1...v9.0.2) (2021-05-10)

### Changed

- Support windows newlines with debug mode

## [9.0.1](https://github.com/motdotla/dotenv/compare/v9.0.0...v9.0.1) (2021-05-08)

### Changed

- Updates to README

## [9.0.0](https://github.com/motdotla/dotenv/compare/v8.6.0...v9.0.0) (2021-05-05)

### Changed

- _Breaking:_ drop support for Node v8

## [8.6.0](https://github.com/motdotla/dotenv/compare/v8.5.1...v8.6.0) (2021-05-05)

### Added

- define package.json in exports

## [8.5.1](https://github.com/motdotla/dotenv/compare/v8.5.0...v8.5.1) (2021-05-05)

### Changed

- updated dev dependencies via npm audit

## [8.5.0](https://github.com/motdotla/dotenv/compare/v8.4.0...v8.5.0) (2021-05-05)

### Added

- allow for `import "dotenv/config"`

## [8.4.0](https://github.com/motdotla/dotenv/compare/v8.3.0...v8.4.0) (2021-05-05)

### Changed

- point to exact types file to work with VS Code

## [8.3.0](https://github.com/motdotla/dotenv/compare/v8.2.0...v8.3.0) (2021-05-05)

### Changed

- _Breaking:_ drop support for Node v8 (mistake to be released as minor bump. later bumped to 9.0.0. see above.)

## [8.2.0](https://github.com/motdotla/dotenv/compare/v8.1.0...v8.2.0) (2019-10-16)

### Added

- TypeScript types

## [8.1.0](https://github.com/motdotla/dotenv/compare/v8.0.0...v8.1.0) (2019-08-18)

### Changed

- _Breaking:_ drop support for Node v6 ([#392](https://github.com/motdotla/dotenv/issues/392))

# [8.0.0](https://github.com/motdotla/dotenv/compare/v7.0.0...v8.0.0) (2019-05-02)

### Changed

- _Breaking:_ drop support for Node v6 ([#302](https://github.com/motdotla/dotenv/issues/392))

## [7.0.0] - 2019-03-12

### Fixed

- Fix removing unbalanced quotes ([#376](https://github.com/motdotla/dotenv/pull/376))

### Removed

- Removed `load` alias for `config` for consistency throughout code and documentation.

## [6.2.0] - 2018-12-03

### Added

- Support preload configuration via environment variables ([#351](https://github.com/motdotla/dotenv/issues/351))

## [6.1.0] - 2018-10-08

### Added

- `debug` option for `config` and `parse` methods will turn on logging

## [6.0.0] - 2018-06-02

### Changed

- _Breaking:_ drop support for Node v4 ([#304](https://github.com/motdotla/dotenv/pull/304))

## [5.0.0] - 2018-01-29

### Added

- Testing against Node v8 and v9
- Documentation on trim behavior of values
- Documentation on how to use with `import`

### Changed

- _Breaking_: default `path` is now `path.resolve(process.cwd(), '.env')`
- _Breaking_: does not write over keys already in `process.env` if the key has a falsy value
- using `const` and `let` instead of `var`

### Removed

- Testing against Node v7

## [4.0.0] - 2016-12-23

### Changed

- Return Object with parsed content or error instead of false ([#165](https://github.com/motdotla/dotenv/pull/165)).

### Removed

- `verbose` option removed in favor of returning result.

## [3.0.0] - 2016-12-20

### Added

- `verbose` option will log any error messages. Off by default.
- parses email addresses correctly
- allow importing config method directly in ES6

### Changed

- Suppress error messages by default ([#154](https://github.com/motdotla/dotenv/pull/154))
- Ignoring more files for NPM to make package download smaller

### Fixed

- False positive test due to case-sensitive variable ([#124](https://github.com/motdotla/dotenv/pull/124))

### Removed

- `silent` option removed in favor of `verbose`

## [2.0.0] - 2016-01-20

### Added

- CHANGELOG to ["make it easier for users and contributors to see precisely what notable changes have been made between each release"](http://keepachangelog.com/). Linked to from README
- LICENSE to be more explicit about what was defined in `package.json`. Linked to from README
- Testing nodejs v4 on travis-ci
- added examples of how to use dotenv in different ways
- return parsed object on success rather than boolean true

### Changed

- README has shorter description not referencing ruby gem since we don't have or want feature parity

### Removed

- Variable expansion and escaping so environment variables are encouraged to be fully orthogonal

## [1.2.0] - 2015-06-20

### Added

- Preload hook to require dotenv without including it in your code

### Changed

- clarified license to be "BSD-2-Clause" in `package.json`

### Fixed

- retain spaces in string vars

## [1.1.0] - 2015-03-31

### Added

- Silent option to silence `console.log` when `.env` missing

## [1.0.0] - 2015-03-13

### Removed

- support for multiple `.env` files. should always use one `.env` file for the current environment

[7.0.0]: https://github.com/motdotla/dotenv/compare/v6.2.0...v7.0.0
[6.2.0]: https://github.com/motdotla/dotenv/compare/v6.1.0...v6.2.0
[6.1.0]: https://github.com/motdotla/dotenv/compare/v6.0.0...v6.1.0
[6.0.0]: https://github.com/motdotla/dotenv/compare/v5.0.0...v6.0.0
[5.0.0]: https://github.com/motdotla/dotenv/compare/v4.0.0...v5.0.0
[4.0.0]: https://github.com/motdotla/dotenv/compare/v3.0.0...v4.0.0
[3.0.0]: https://github.com/motdotla/dotenv/compare/v2.0.0...v3.0.0
[2.0.0]: https://github.com/motdotla/dotenv/compare/v1.2.0...v2.0.0
[1.2.0]: https://github.com/motdotla/dotenv/compare/v1.1.0...v1.2.0
[1.1.0]: https://github.com/motdotla/dotenv/compare/v1.0.0...v1.1.0
[1.0.0]: https://github.com/motdotla/dotenv/compare/v0.4.0...v1.0.0


path: node_modules/dotenv/README-es.md
content: <div align="center">
🎉 announcing <a href="https://github.com/dotenvx/dotenvx">dotenvx</a>. <em>run anywhere, multi-environment, encrypted envs</em>.
</div>

&nbsp;

<div align="center">

<p>
  <sup>
    <a href="https://github.com/sponsors/motdotla">Dotenv es apoyado por la comunidad.</a>
  </sup>
</p>
<sup>Gracias espaciales a:</sup>
<br>
<br>

<a href="https://graphite.dev/?utm_source=github&utm_medium=repo&utm_campaign=dotenv"><img src="https://res.cloudinary.com/dotenv-org/image/upload/v1744035073/graphite_lgsrl8.gif" width="240" alt="Graphite" /></a>

<a href="https://graphite.dev/?utm_source=github&utm_medium=repo&utm_campaign=dotenv">
  <b>Graphite is the AI developer productivity platform helping teams on GitHub ship higher quality software, faster.</b>
</a>
<hr>
</div>

# dotenv [![NPM version](https://img.shields.io/npm/v/dotenv.svg?style=flat-square)](https://www.npmjs.com/package/dotenv)

<img src="https://raw.githubusercontent.com/motdotla/dotenv/master/dotenv.svg" alt="dotenv" align="right" width="200" />

Dotenv es un módulo de dependencia cero que carga las variables de entorno desde un archivo `.env` en [`process.env`](https://nodejs.org/docs/latest/api/process.html#process_process_env). El almacenamiento de la configuración del entorno separado del código está basado en la metodología [The Twelve-Factor App](http://12factor.net/config).

[![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat-square)](https://github.com/feross/standard)
[![LICENSE](https://img.shields.io/github/license/motdotla/dotenv.svg)](LICENSE)

## Instalación

```bash
# instalación local (recomendado)
npm install dotenv --save
```

O installación con yarn? `yarn add dotenv`

## Uso

Cree un archivo `.env` en la raíz de su proyecto:

```dosini
S3_BUCKET="YOURS3BUCKET"
SECRET_KEY="YOURSECRETKEYGOESHERE"
```

Tan prónto como sea posible en su aplicación, importe y configure dotenv:

```javascript
require('dotenv').config()
console.log(process.env) // elimine esto después que haya confirmado que esta funcionando
```

.. o usa ES6?

```javascript
import * as dotenv from 'dotenv' // vea en https://github.com/motdotla/dotenv#como-uso-dotenv-con-import
// REVISAR LINK DE REFERENCIA DE IMPORTACIÓN
dotenv.config()
import express from 'express'
```

Eso es todo. `process.env` ahora tiene las claves y los valores que definiste en tu archivo `.env`:

```javascript
require('dotenv').config()

...

s3.getBucketCors({Bucket: process.env.S3_BUCKET}, function(err, data) {})
```

### Valores multilínea

Si necesita variables de varias líneas, por ejemplo, claves privadas, ahora se admiten en la versión (`>= v15.0.0`) con saltos de línea:

```dosini
PRIVATE_KEY="[REDACTED_SECRET]"
```

Alternativamente, puede usar comillas dobles y usar el carácter `\n`:

```dosini
PRIVATE_KEY="[REDACTED_SECRET]\n"
```

### Comentarios

Los comentarios pueden ser agregados en tu archivo o en la misma línea:

```dosini
# This is a comment
SECRET_KEY=YOURSECRETKEYGOESHERE # comment
SECRET_HASH="something-with-a-#-hash"
```

Los comentarios comienzan donde existe un `#`, entonces, si su valor contiene un `#`, enciérrelo entre comillas. Este es un cambio importante desde la versión `>= v15.0.0` en adelante.

### Análisis

El motor que analiza el contenido de su archivo que contiene variables de entorno está disponible para su uso. Este Acepta una Cadena o un Búfer y devolverá un Objeto con las claves y los valores analizados.

```javascript
const dotenv = require('dotenv')
const buf = Buffer.from('BASICO=basico')
const config = dotenv.parse(buf) // devolverá un objeto
console.log(typeof config, config) // objeto { BASICO : 'basico' }
```

### Precarga

Puede usar el `--require` (`-r`) [opción de línea de comando](https://nodejs.org/api/cli.html#-r---require-module) para precargar dotenv. Al hacer esto, no necesita requerir ni cargar dotnev en el código de su aplicación.

```bash
$ node -r dotenv/config tu_script.js
```

Las opciones de configuración a continuación se admiten como argumentos de línea de comandos en el formato `dotenv_config_<option>=value`

```bash
$ node -r dotenv/config tu_script.js dotenv_config_path=/custom/path/to/.env dotenv_config_debug=true
```

Además, puede usar variables de entorno para establecer opciones de configuración. Los argumentos de línea de comandos precederán a estos.

```bash
$ DOTENV_CONFIG_<OPTION>=value node -r dotenv/config tu_script.js
```

```bash
$ DOTENV_CONFIG_ENCODING=latin1 DOTENV_CONFIG_DEBUG=true node -r dotenv/config tu_script.js dotenv_config_path=/custom/path/to/.env
```

### Expansión Variable

Necesitaras agregar el valor de otro variable en una de sus variables? Usa [dotenv-expand](https://github.com/motdotla/dotenv-expand).

## Ejemplos

Vea [ejemplos](https://github.com/dotenv-org/examples) sobre el uso de dotenv con varios frameworks, lenguajes y configuraciones.

* [nodejs](https://github.com/dotenv-org/examples/tree/master/dotenv-nodejs)
* [nodejs (depurar en)](https://github.com/dotenv-org/examples/tree/master/dotenv-nodejs-debug)
* [nodejs (anular en)](https://github.com/dotenv-org/examples/tree/master/dotenv-nodejs-override)
* [esm](https://github.com/dotenv-org/examples/tree/master/dotenv-esm)
* [esm (precarga)](https://github.com/dotenv-org/examples/tree/master/dotenv-esm-preload)
* [typescript](https://github.com/dotenv-org/examples/tree/master/dotenv-typescript)
* [typescript parse](https://github.com/dotenv-org/examples/tree/master/dotenv-typescript-parse)
* [typescript config](https://github.com/dotenv-org/examples/tree/master/dotenv-typescript-config)
* [webpack](https://github.com/dotenv-org/examples/tree/master/dotenv-webpack)
* [webpack (plugin)](https://github.com/dotenv-org/examples/tree/master/dotenv-webpack2)
* [react](https://github.com/dotenv-org/examples/tree/master/dotenv-react)
* [react (typescript)](https://github.com/dotenv-org/examples/tree/master/dotenv-react-typescript)
* [express](https://github.com/dotenv-org/examples/tree/master/dotenv-express)
* [nestjs](https://github.com/dotenv-org/examples/tree/master/dotenv-nestjs)

## Documentación

Dotenv expone dos funciones:

* `configuración`
* `analizar`

### Configuración

`Configuración` leerá su archivo `.env`, analizará el contenido, lo asignará a [`process.env`](https://nodejs.org/docs/latest/api/process.html#process_process_env),
y devolverá un Objeto con una clave `parsed` que contiene el contenido cargado o una clave `error` si falla.

```js
const result = dotenv.config()

if (result.error) {
  throw result.error
}

console.log(result.parsed)
```

Adicionalmente, puede pasar opciones a `configuracion`.

#### Opciones

##### Ruta

Por defecto: `path.resolve(process.cwd(), '.env')`

Especifique una ruta personalizada si el archivo que contiene las variables de entorno se encuentra localizado en otro lugar.

```js
require('dotenv').config({ path: '/personalizado/ruta/a/.env' })
```

##### Codificación

Por defecto: `utf8`

Especifique la codificación del archivo que contiene las variables de entorno.

```js
require('dotenv').config({ encoding: 'latin1' })
```

##### Depurar

Por defecto: `false`

Active el registro de ayuda para depurar por qué ciertas claves o valores no se inician como lo esperabas.

```js
require('dotenv').config({ debug: process.env.DEBUG })
```

##### Anular

Por defecto: `false`

Anule cualquier variable de entorno que ya se haya configurada en su maquina con los valores de su archivo .env.

```js
require('dotenv').config({ override: true })
```

### Analizar

El motor que analiza el contenido del archivo que contiene las variables de entorno está disponible para su uso. Acepta una Cadena o un Búfer y retornará un objecto con los valores analizados.

```js
const dotenv = require('dotenv')
const buf = Buffer.from('BASICO=basico')
const config = dotenv.parse(buf) // devolverá un objeto
console.log(typeof config, config) // objeto { BASICO : 'basico' }
```

#### Opciones

##### Depurar

Por defecto: `false`

Active el registro de ayuda para depurar por qué ciertas claves o valores no se inician como lo esperabas.

```js
const dotenv = require('dotenv')
const buf = Buffer.from('hola mundo')
const opt = { debug: true }
const config = dotenv.parse(buf, opt)
// espere por un mensaje de depuración porque el búfer no esta listo KEY=VAL
```

## FAQ

### ¿Por qué el archivo `.env` no carga mis variables de entorno correctamente?

Lo más probable es que su archivo `.env` no esté en el lugar correcto. [Vea este stack overflow](https://stackoverflow.com/questions/42335016/dotenv-file-is-not-loading-environment-variables).

Active el modo de depuración y vuelva a intentarlo...

```js
require('dotenv').config({ debug: true })
```

Recibirá un error apropiado en su consola.

### ¿Debo confirmar mi archivo `.env`?

No. Recomendamos **enfáticamente** no enviar su archivo `.env` a la versión de control. Solo debe incluir los valores especificos del entorno, como la base de datos, contraseñas o claves API.

### ¿Debería tener multiples archivos `.env`?

No. Recomendamos **enfáticamente** no tener un archivo `.env` "principal" y un archivo `.env` de "entorno" como `.env.test`. Su configuración debe variar entre implementaciones y no debe compartir valores entre entornos.

> En una Aplicación de Doce Factores, las variables de entorno son controles diferenciados, cada uno totalmente independiente a otras variables de entorno. Nunca se agrupan como "entornos", sino que se gestionan de manera independiente para cada despliegue. Este es un modelo que se escala sin problemas a medida que la aplicación se expande de forma natural en más despliegues a lo largo de su vida.
>
> – [La Apliación de los Doce Factores](https://12factor.net/es/)

### ¿Qué reglas sigue el motor de análisis?

El motor de análisis actualmente admite las siguientes reglas:

- `BASICO=basico` se convierte en `{BASICO: 'basico'}`
- las líneas vacías se saltan
- las líneas que comienzan con `#` se tratan como comentarios
- `#` marca el comienzo de un comentario (a menos que el valor esté entre comillas)
- valores vacíos se convierten en cadenas vacías (`VACIO=` se convierte en `{VACIO: ''}`)
- las comillas internas se mantienen (piensa en JSON) (`JSON={"foo": "bar"}` se convierte en `{JSON:"{\"foo\": \"bar\"}"`)
- los espacios en blanco se eliminan de ambos extremos de los valores no citanos (aprende más en [`trim`](https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Global_Objects/String/Trim)) (`FOO=  algo ` se convierte en `{FOO: 'algo'}`)
- los valores entre comillas simples y dobles se escapan (`CITA_SIMPLE='citado'` se convierte en `{CITA_SIMPLE: "citado"}`)
- los valores entre comillas simples y dobles mantienen los espacios en blanco en ambos extremos  (`FOO="  algo  "` se convierte en `{FOO: '  algo  '}`)
- los valores entre comillas dobles expanden nuevas líneas (`MULTILINEA="nueva\nlínea"` se convierte en

```
{MULTILINEA: 'nueva
línea'}
```

- se admite la comilla simple invertida (`` SIGNO_ACENTO=`Esto tiene comillas 'simples' y "dobles" en su interior.` ``)

### ¿Qué sucede con las variables de entorno que ya estaban configuradas?

Por defecto, nunca modificaremos ninguna variable de entorno que ya haya sido establecida. En particular, si hay una variable en su archivo `.env` que colisiona con una que ya existe en su entorno, entonces esa variable se omitirá.

Si por el contrario, quieres anular `process.env` utiliza la opción `override`.

```javascript
require('dotenv').config({ override: true })
```

### ¿Por qué mis variables de entorno no aparecen para React?

Su código React se ejecuta en Webpack, donde el módulo `fs` o incluso el propio `process` global no son accesibles fuera-de-la-caja. El módulo `process.env` sólo puede ser inyectado a través de la configuración de Webpack.

Si estás usando [`react-scripts`](https://www.npmjs.com/package/react-scripts), el cual se distribuye a través de [`create-react-app`](https://create-react-app.dev/), tiene dotenv incorporado pero con una singularidad. Escriba sus variables de entorno con `REACT_APP_`. Vea [este stack overflow](https://stackoverflow.com/questions/42182577/is-it-possible-to-use-dotenv-in-a-react-project) para más detalles.

Si estás utilizando otros frameworks (por ejemplo, Next.js, Gatsby...), debes consultar su documentación para saber cómo injectar variables de entorno en el cliente.

### ¿Puedo personalizar/escribir plugins para dotenv?

Sí! `dotenv.config()` devuelve un objeto que representa el archivo `.env` analizado. Esto te da todo lo que necesitas para poder establecer valores en `process.env`. Por ejemplo:

```js
const dotenv = require('dotenv')
const variableExpansion = require('dotenv-expand')
const miEnv = dotenv.config()
variableExpansion(miEnv)
```

### Cómo uso dotnev con `import`?

Simplemente..

```javascript
// index.mjs (ESM)
import * as dotenv from 'dotenv' // vea https://github.com/motdotla/dotenv#como-uso-dotenv-con-import
dotenv.config()
import express from 'express'
```

Un poco de historia...

> Cuando se ejecuta un módulo que contiene una sentencia `import`, los módulos que importa serán cargados primero, y luego se ejecuta cada bloque del módulo en un recorrido en profundidad del gráfico de dependencias, evitando los ciclos al saltarse todo lo que ya se ha ejecutado.
>
> – [ES6 en Profundidad: Módulos](https://hacks.mozilla.org/2015/08/es6-in-depth-modules/)

¿Qué significa esto en lenguaje sencillo? Significa que se podrías pensar que lo siguiente funcionaría pero no lo hará.

```js
// notificarError.mjs
import { Cliente } from 'mejor-servicio-para-notificar-error'

export default new Client(process.env.CLAVE_API)

// index.mjs
import dotenv from 'dotenv'
dotenv.config()

import notificarError from './notificarError.mjs'
notificarError.report(new Error('ejemplo documentado'))
```

`process.env.CLAVE_API` será vacio.

En su lugar, el código anterior debe ser escrito como...

```js
// notificarError.mjs
import { Cliente } from 'mejor-servicio-para-notificar-errores'

export default new Client(process.env.CLAVE_API)

// index.mjs
import * as dotenv from 'dotenv'
dotenv.config()

import notificarError from './notificarError.mjs'
notificarError.report(new Error('ejemplo documentado'))
```

¿Esto tiene algo de sentido? Esto es poco poco intuitivo, pero es como funciona la importación de módulos en ES6. Aquí hay un ejemplo [ejemplo práctico de esta trampa](https://github.com/dotenv-org/examples/tree/master/dotenv-es6-import-pitfall).

Existen dos arternativas a este planteamiento:

1. Precarga dotenv: `node --require dotenv/config index.js` (_Nota: no es necesario usar `import` dotenv con este método_)
2. Cree un archivo separado que ejecutará `config` primero como se describe en [este comentario #133](https://github.com/motdotla/dotenv/issues/133#issuecomment-255298822)

### ¿Qué pasa con la expansión de variable?

Prueba [dotenv-expand](https://github.com/motdotla/dotenv-expand)

## Guía de contribución

Vea [CONTRIBUTING.md](CONTRIBUTING.md)

## REGISTRO DE CAMBIOS

Vea [CHANGELOG.md](CHANGELOG.md)

## ¿Quiénes utilizan dotenv?

[Estos módulos npm dependen de él.](https://www.npmjs.com/browse/depended/dotenv)

Los proyectos que lo amplían suelen utilizar la [palabra clave "dotenv" en npm](https://www.npmjs.com/search?q=keywords:dotenv).


path: node_modules/dotenv/README.md
content: <div align="center">
🎉 announcing <a href="https://github.com/dotenvx/dotenvx">dotenvx</a>. <em>run anywhere, multi-environment, encrypted envs</em>.
</div>

&nbsp;

<div align="center">

**Special thanks to [our sponsors](https://github.com/sponsors/motdotla)**

<br>
<a href="https://graphite.dev/?utm_source=github&utm_medium=repo&utm_campaign=dotenv"><img src="https://res.cloudinary.com/dotenv-org/image/upload/v1744035073/graphite_lgsrl8.gif" width="240" alt="Graphite" /></a>
<br>
<a href="https://graphite.dev/?utm_source=github&utm_medium=repo&utm_campaign=dotenv">
  <b>Graphite is the AI developer productivity platform helping teams on GitHub ship higher quality software, faster.</b>
</a>
<hr>
</div>

# dotenv [![NPM version](https://img.shields.io/npm/v/dotenv.svg?style=flat-square)](https://www.npmjs.com/package/dotenv)

<img src="https://raw.githubusercontent.com/motdotla/dotenv/master/dotenv.svg" alt="dotenv" align="right" width="200" />

Dotenv is a zero-dependency module that loads environment variables from a `.env` file into [`process.env`](https://nodejs.org/docs/latest/api/process.html#process_process_env). Storing configuration in the environment separate from code is based on [The Twelve-Factor App](https://12factor.net/config) methodology.

[![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat-square)](https://github.com/feross/standard)
[![LICENSE](https://img.shields.io/github/license/motdotla/dotenv.svg)](LICENSE)
[![codecov](https://codecov.io/gh/motdotla/dotenv-expand/graph/badge.svg?[REDACTED_SECRET])](https://codecov.io/gh/motdotla/dotenv-expand)

* [🌱 Install](#-install)
* [🏗️ Usage (.env)](#%EF%B8%8F-usage)
* [🌴 Multiple Environments 🆕](#-manage-multiple-environments)
* [🚀 Deploying (encryption) 🆕](#-deploying)
* [📚 Examples](#-examples)
* [📖 Docs](#-documentation)
* [❓ FAQ](#-faq)
* [⏱️ Changelog](./CHANGELOG.md)

## 🌱 Install

```bash
npm install dotenv --save
```

You can also use an npm-compatible package manager like yarn, bun or pnpm:

```bash
yarn add dotenv
```
```bash
bun add dotenv
```
```bash
pnpm add dotenv
```

## 🏗️ Usage

<a href="https://www.youtube.com/watch?v=YtkZR0NFd1g">
<div align="right">
<img src="https://img.youtube.com/vi/YtkZR0NFd1g/hqdefault.jpg" alt="how to use dotenv video tutorial" align="right" width="330" />
<img src="https://simpleicons.vercel.app/youtube/ff0000" alt="youtube/@dotenvorg" align="right" width="24" />
</div>
</a>

Create a `.env` file in the root of your project (if using a monorepo structure like `apps/backend/app.js`, put it in the root of the folder where your `app.js` process runs):

```dosini
S3_BUCKET="YOURS3BUCKET"
SECRET_KEY="YOURSECRETKEYGOESHERE"
```

As early as possible in your application, import and configure dotenv:

```javascript
require('dotenv').config()
console.log(process.env) // remove this after you've confirmed it is working
```

.. [or using ES6?](#how-do-i-use-dotenv-with-import)

```javascript
import 'dotenv/config'
```

That's it. `process.env` now has the keys and values you defined in your `.env` file:

```javascript
require('dotenv').config()
// or import 'dotenv/config' if you're using ES6

...

s3.getBucketCors({Bucket: process.env.S3_BUCKET}, function(err, data) {})
```

### Multiline values

If you need multiline variables, for example private keys, those are now supported (`>= v15.0.0`) with line breaks:

```dosini
PRIVATE_KEY="[REDACTED_SECRET]"
```

Alternatively, you can double quote strings and use the `\n` character:

```dosini
PRIVATE_KEY="[REDACTED_SECRET]\n"
```

### Comments

Comments may be added to your file on their own line or inline:

```dosini
# This is a comment
SECRET_KEY=YOURSECRETKEYGOESHERE # comment
SECRET_HASH="something-with-a-#-hash"
```

Comments begin where a `#` exists, so if your value contains a `#` please wrap it in quotes. This is a breaking change from `>= v15.0.0` and on.

### Parsing

The engine which parses the contents of your file containing environment variables is available to use. It accepts a String or Buffer and will return an Object with the parsed keys and values.

```javascript
const dotenv = require('dotenv')
const buf = Buffer.from('BASIC=basic')
const config = dotenv.parse(buf) // will return an object
console.log(typeof config, config) // object { BASIC : 'basic' }
```

### Preload

> Note: Consider using [`dotenvx`](https://github.com/dotenvx/dotenvx) instead of preloading. I am now doing (and recommending) so.
>
> It serves the same purpose (you do not need to require and load dotenv), adds better debugging, and works with ANY language, framework, or platform. – [motdotla](https://github.com/motdotla)

You can use the `--require` (`-r`) [command line option](https://nodejs.org/api/cli.html#-r---require-module) to preload dotenv. By doing this, you do not need to require and load dotenv in your application code.

```bash
$ node -r dotenv/config your_script.js
```

The configuration options below are supported as command line arguments in the format `dotenv_config_<option>=value`

```bash
$ node -r dotenv/config your_script.js dotenv_config_path=/custom/path/to/.env dotenv_config_debug=true
```

Additionally, you can use environment variables to set configuration options. Command line arguments will precede these.

```bash
$ DOTENV_CONFIG_<OPTION>=value node -r dotenv/config your_script.js
```

```bash
$ DOTENV_CONFIG_ENCODING=latin1 DOTENV_CONFIG_DEBUG=true node -r dotenv/config your_script.js dotenv_config_path=/custom/path/to/.env
```

### Variable Expansion

You need to add the value of another variable in one of your variables? Use [dotenv-expand](https://github.com/motdotla/dotenv-expand).

### Command Substitution

Use [dotenvx](https://github.com/dotenvx/dotenvx) to use command substitution.

Add the output of a command to one of your variables in your .env file.

```ini
# .env
DATABASE_URL="postgres://$(whoami)@localhost/my_database"
```
```js
// index.js
console.log('DATABASE_URL', process.env.DATABASE_URL)
```
```sh
$ dotenvx run --debug -- node index.js
[dotenvx@0.14.1] injecting env (1) from .env
DATABASE_URL postgres://yourusername@localhost/my_database
```

### Syncing

You need to keep `.env` files in sync between machines, environments, or team members? Use [dotenvx](https://github.com/dotenvx/dotenvx) to encrypt your `.env` files and safely include them in source control. This still subscribes to the twelve-factor app rules by generating a decryption key separate from code.

### Multiple Environments

Use [dotenvx](https://github.com/dotenvx/dotenvx) to generate `.env.ci`, `.env.production` files, and more.

### Deploying

You need to deploy your secrets in a cloud-agnostic manner? Use [dotenvx](https://github.com/dotenvx/dotenvx) to generate a private decryption key that is set on your production server.

## 🌴 Manage Multiple Environments

Use [dotenvx](https://github.com/dotenvx/dotenvx)

Run any environment locally. Create a `.env.ENVIRONMENT` file and use `--env-file` to load it. It's straightforward, yet flexible.

```bash
$ echo "HELLO=production" > .env.production
$ echo "console.log('Hello ' + process.env.HELLO)" > index.js

$ dotenvx run --env-file=.env.production -- node index.js
Hello production
> ^^
```

or with multiple .env files

```bash
$ echo "HELLO=local" > .env.local
$ echo "HELLO=World" > .env
$ echo "console.log('Hello ' + process.env.HELLO)" > index.js

$ dotenvx run --env-file=.env.local --env-file=.env -- node index.js
Hello local
```

[more environment examples](https://dotenvx.com/docs/quickstart/environments)

## 🚀 Deploying

Use [dotenvx](https://github.com/dotenvx/dotenvx).

Add encryption to your `.env` files with a single command. Pass the `--encrypt` flag.

```
$ dotenvx set HELLO Production --encrypt -f .env.production
$ echo "console.log('Hello ' + process.env.HELLO)" > index.js

$ DOTENV_PRIVATE_KEY_PRODUCTION="<.env.production private key>" dotenvx run -- node index.js
[dotenvx] injecting env (2) from .env.production
Hello Production
```

[learn more](https://github.com/dotenvx/dotenvx?tab=readme-ov-file#encryption)

## 📚 Examples

See [examples](https://github.com/dotenv-org/examples) of using dotenv with various frameworks, languages, and configurations.

* [nodejs](https://github.com/dotenv-org/examples/tree/master/usage/dotenv-nodejs)
* [nodejs (debug on)](https://github.com/dotenv-org/examples/tree/master/usage/dotenv-nodejs-debug)
* [nodejs (override on)](https://github.com/dotenv-org/examples/tree/master/usage/dotenv-nodejs-override)
* [nodejs (processEnv override)](https://github.com/dotenv-org/examples/tree/master/usage/dotenv-custom-target)
* [esm](https://github.com/dotenv-org/examples/tree/master/usage/dotenv-esm)
* [esm (preload)](https://github.com/dotenv-org/examples/tree/master/usage/dotenv-esm-preload)
* [typescript](https://github.com/dotenv-org/examples/tree/master/usage/dotenv-typescript)
* [typescript parse](https://github.com/dotenv-org/examples/tree/master/usage/dotenv-typescript-parse)
* [typescript config](https://github.com/dotenv-org/examples/tree/master/usage/dotenv-typescript-config)
* [webpack](https://github.com/dotenv-org/examples/tree/master/usage/dotenv-webpack)
* [webpack (plugin)](https://github.com/dotenv-org/examples/tree/master/usage/dotenv-webpack2)
* [react](https://github.com/dotenv-org/examples/tree/master/usage/dotenv-react)
* [react (typescript)](https://github.com/dotenv-org/examples/tree/master/usage/dotenv-react-typescript)
* [express](https://github.com/dotenv-org/examples/tree/master/usage/dotenv-express)
* [nestjs](https://github.com/dotenv-org/examples/tree/master/usage/dotenv-nestjs)
* [fastify](https://github.com/dotenv-org/examples/tree/master/usage/dotenv-fastify)

## 📖 Documentation

Dotenv exposes four functions:

* `config`
* `parse`
* `populate`
* `decrypt`

### Config

`config` will read your `.env` file, parse the contents, assign it to
[`process.env`](https://nodejs.org/docs/latest/api/process.html#process_process_env),
and return an Object with a `parsed` key containing the loaded content or an `error` key if it failed.

```js
const result = dotenv.config()

if (result.error) {
  throw result.error
}

console.log(result.parsed)
```

You can additionally, pass options to `config`.

#### Options

##### path

Default: `path.resolve(process.cwd(), '.env')`

Specify a custom path if your file containing environment variables is located elsewhere.

```js
require('dotenv').config({ path: '/custom/path/to/.env' })
```

By default, `config` will look for a file called .env in the current working directory.

Pass in multiple files as an array, and they will be parsed in order and combined with `process.env` (or `option.processEnv`, if set). The first value set for a variable will win, unless the `options.override` flag is set, in which case the last value set will win.  If a value already exists in `process.env` and the `options.override` flag is NOT set, no changes will be made to that value. 

```js  
require('dotenv').config({ path: ['.env.local', '.env'] })
```

##### encoding

Default: `utf8`

Specify the encoding of your file containing environment variables.

```js
require('dotenv').config({ encoding: 'latin1' })
```

##### debug

Default: `false`

Turn on logging to help debug why certain keys or values are not being set as you expect.

```js
require('dotenv').config({ debug: process.env.DEBUG })
```

##### override

Default: `false`

Override any environment variables that have already been set on your machine with values from your .env file(s). If multiple files have been provided in `option.path` the override will also be used as each file is combined with the next. Without `override` being set, the first value wins. With `override` set the last value wins. 

```js
require('dotenv').config({ override: true })
```

##### processEnv

Default: `process.env`

Specify an object to write your environment variables to. Defaults to `process.env` environment variables.

```js
const myObject = {}
require('dotenv').config({ processEnv: myObject })

console.log(myObject) // values from .env
console.log(process.env) // this was not changed or written to
```

### Parse

The engine which parses the contents of your file containing environment
variables is available to use. It accepts a String or Buffer and will return
an Object with the parsed keys and values.

```js
const dotenv = require('dotenv')
const buf = Buffer.from('BASIC=basic')
const config = dotenv.parse(buf) // will return an object
console.log(typeof config, config) // object { BASIC : 'basic' }
```

#### Options

##### debug

Default: `false`

Turn on logging to help debug why certain keys or values are not being set as you expect.

```js
const dotenv = require('dotenv')
const buf = Buffer.from('hello world')
const opt = { debug: true }
const config = dotenv.parse(buf, opt)
// expect a debug message because the buffer is not in KEY=VAL form
```

### Populate

The engine which populates the contents of your .env file to `process.env` is available for use. It accepts a target, a source, and options. This is useful for power users who want to supply their own objects.

For example, customizing the source:

```js
const dotenv = require('dotenv')
const parsed = { HELLO: 'world' }

dotenv.populate(process.env, parsed)

console.log(process.env.HELLO) // world
```

For example, customizing the source AND target:

```js
const dotenv = require('dotenv')
const parsed = { HELLO: 'universe' }
const target = { HELLO: 'world' } // empty object

dotenv.populate(target, parsed, { override: true, debug: true })

console.log(target) // { HELLO: 'universe' }
```

#### options

##### Debug

Default: `false`

Turn on logging to help debug why certain keys or values are not being populated as you expect.

##### override

Default: `false`

Override any environment variables that have already been set.

## ❓ FAQ

### Why is the `.env` file not loading my environment variables successfully?

Most likely your `.env` file is not in the correct place. [See this stack overflow](https://stackoverflow.com/questions/42335016/dotenv-file-is-not-loading-environment-variables).

Turn on debug mode and try again..

```js
require('dotenv').config({ debug: true })
```

You will receive a helpful error outputted to your console.

### Should I commit my `.env` file?

No. We **strongly** recommend against committing your `.env` file to version
control. It should only include environment-specific values such as database
passwords or API keys. Your production database should have a different
password than your development database.

### Should I have multiple `.env` files?

We recommend creating one `.env` file per environment. Use `.env` for local/development, `.env.production` for production and so on. This still follows the twelve factor principles as each is attributed individually to its own environment. Avoid custom set ups that work in inheritance somehow (`.env.production` inherits values form `.env` for example). It is better to duplicate values if necessary across each `.env.environment` file.

> In a twelve-factor app, env vars are granular controls, each fully orthogonal to other env vars. They are never grouped together as “environments”, but instead are independently managed for each deploy. This is a model that scales up smoothly as the app naturally expands into more deploys over its lifetime.
>
> – [The Twelve-Factor App](http://12factor.net/config)

### What rules does the parsing engine follow?

The parsing engine currently supports the following rules:

- `BASIC=basic` becomes `{BASIC: 'basic'}`
- empty lines are skipped
- lines beginning with `#` are treated as comments
- `#` marks the beginning of a comment (unless when the value is wrapped in quotes)
- empty values become empty strings (`EMPTY=` becomes `{EMPTY: ''}`)
- inner quotes are maintained (think JSON) (`JSON={"foo": "bar"}` becomes `{JSON:"{\"foo\": \"bar\"}"`)
- whitespace is removed from both ends of unquoted values (see more on [`trim`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/Trim)) (`FOO=  some value  ` becomes `{FOO: 'some value'}`)
- single and double quoted values are escaped (`SINGLE_QUOTE='quoted'` becomes `{SINGLE_QUOTE: "quoted"}`)
- single and double quoted values maintain whitespace from both ends (`FOO="  some value  "` becomes `{FOO: '  some value  '}`)
- double quoted values expand new lines (`MULTILINE="new\nline"` becomes

```
{MULTILINE: 'new
line'}
```

- backticks are supported (`` BACKTICK_KEY=`This has 'single' and "double" quotes inside of it.` ``)

### What happens to environment variables that were already set?

By default, we will never modify any environment variables that have already been set. In particular, if there is a variable in your `.env` file which collides with one that already exists in your environment, then that variable will be skipped.

If instead, you want to override `process.env` use the `override` option.

```javascript
require('dotenv').config({ override: true })
```

### How come my environment variables are not showing up for React?

Your React code is run in Webpack, where the `fs` module or even the `process` global itself are not accessible out-of-the-box. `process.env` can only be injected through Webpack configuration.

If you are using [`react-scripts`](https://www.npmjs.com/package/react-scripts), which is distributed through [`create-react-app`](https://create-react-app.dev/), it has dotenv built in but with a quirk. Preface your environment variables with `REACT_APP_`. See [this stack overflow](https://stackoverflow.com/questions/42182577/is-it-possible-to-use-dotenv-in-a-react-project) for more details.

If you are using other frameworks (e.g. Next.js, Gatsby...), you need to consult their documentation for how to inject environment variables into the client.

### Can I customize/write plugins for dotenv?

Yes! `dotenv.config()` returns an object representing the parsed `.env` file. This gives you everything you need to continue setting values on `process.env`. For example:

```js
const dotenv = require('dotenv')
const variableExpansion = require('dotenv-expand')
const myEnv = dotenv.config()
variableExpansion(myEnv)
```

### How do I use dotenv with `import`?

Simply..

```javascript
// index.mjs (ESM)
import 'dotenv/config' // see https://github.com/motdotla/dotenv#how-do-i-use-dotenv-with-import
import express from 'express'
```

A little background..

> When you run a module containing an `import` declaration, the modules it imports are loaded first, then each module body is executed in a depth-first traversal of the dependency graph, avoiding cycles by skipping anything already executed.
>
> – [ES6 In Depth: Modules](https://hacks.mozilla.org/2015/08/es6-in-depth-modules/)

What does this mean in plain language? It means you would think the following would work but it won't.

`errorReporter.mjs`:
```js
class Client {
  constructor (apiKey) {
    console.log('apiKey', apiKey)

    this.[REDACTED_SECRET]
  }
}

export default new Client(process.env.API_KEY)
```
`index.mjs`:
```js
// Note: this is INCORRECT and will not work
import * as dotenv from 'dotenv'
dotenv.config()

import errorReporter from './errorReporter.mjs' // process.env.API_KEY will be blank!
```

`process.env.API_KEY` will be blank.

Instead, `index.mjs` should be written as..

```js
import 'dotenv/config'

import errorReporter from './errorReporter.mjs'
```

Does that make sense? It's a bit unintuitive, but it is how importing of ES6 modules work. Here is a [working example of this pitfall](https://github.com/dotenv-org/examples/tree/master/usage/dotenv-es6-import-pitfall).

There are two alternatives to this approach:

1. Preload dotenv: `node --require dotenv/config index.js` (_Note: you do not need to `import` dotenv with this approach_)
2. Create a separate file that will execute `config` first as outlined in [this comment on #133](https://github.com/motdotla/dotenv/issues/133#issuecomment-255298822)

### Why am I getting the error `Module not found: Error: Can't resolve 'crypto|os|path'`?

You are using dotenv on the front-end and have not included a polyfill. Webpack < 5 used to include these for you. Do the following:

```bash
npm install node-polyfill-webpack-plugin
```

Configure your `webpack.config.js` to something like the following.

```js
require('dotenv').config()

const path = require('path');
const webpack = require('webpack')

const NodePolyfillPlugin = require('node-polyfill-webpack-plugin')

module.exports = {
  mode: 'development',
  entry: './src/index.ts',
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist'),
  },
  plugins: [
    new NodePolyfillPlugin(),
    new webpack.DefinePlugin({
      'process.env': {
        HELLO: JSON.stringify(process.env.HELLO)
      }
    }),
  ]
};
```

Alternatively, just use [dotenv-webpack](https://github.com/mrsteele/dotenv-webpack) which does this and more behind the scenes for you.

### What about variable expansion?

Try [dotenv-expand](https://github.com/motdotla/dotenv-expand)

### What about syncing and securing .env files?

Use [dotenvx](https://github.com/dotenvx/dotenvx)

### What if I accidentally commit my `.env` file to code?

Remove it, [remove git history](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/removing-sensitive-data-from-a-repository) and then install the [git pre-commit hook](https://github.com/dotenvx/dotenvx#pre-commit) to prevent this from ever happening again. 

```
brew install dotenvx/brew/dotenvx
dotenvx precommit --install
```

### How can I prevent committing my `.env` file to a Docker build?

Use the [docker prebuild hook](https://dotenvx.com/docs/features/prebuild).

```bash
# Dockerfile
...
RUN curl -fsS https://dotenvx.sh/ | sh
...
RUN dotenvx prebuild
CMD ["dotenvx", "run", "--", "node", "index.js"]
```

## Contributing Guide

See [CONTRIBUTING.md](CONTRIBUTING.md)

## CHANGELOG

See [CHANGELOG.md](CHANGELOG.md)

## Who's using dotenv?

[These npm modules depend on it.](https://www.npmjs.com/browse/depended/dotenv)

Projects that expand it often use the [keyword "dotenv" on npm](https://www.npmjs.com/search?q=keywords:dotenv).


path: node_modules/dotenv/SECURITY.md
content: Please report any security vulnerabilities to [REDACTED_SECRET]. 


path: node_modules/dotenv/config.d.ts
content: export {};


path: node_modules/dotenv/config.js
content: (function () {
  require('./lib/main').config(
    Object.assign(
      {},
      require('./lib/env-options'),
      require('./lib/cli-options')(process.argv)
    )
  )
})()


path: node_modules/dotenv/lib/cli-options.js
content: const re = /^dotenv_config_(encoding|path|quiet|debug|override|DOTENV_KEY)=(.+)$/

module.exports = function optionMatcher (args) {
  const options = args.reduce(function (acc, cur) {
    const matches = cur.match(re)
    if (matches) {
      acc[matches[1]] = matches[2]
    }
    return acc
  }, {})

  if (!('quiet' in options)) {
    options.quiet = 'true'
  }

  return options
}


path: node_modules/dotenv/lib/env-options.js
content: // ../config.js accepts options via environment variables
const options = {}

if (process.env.DOTENV_CONFIG_ENCODING != null) {
  options.encoding = process.env.DOTENV_CONFIG_ENCODING
}

if (process.env.DOTENV_CONFIG_PATH != null) {
  options.path = process.env.DOTENV_CONFIG_PATH
}

if (process.env.DOTENV_CONFIG_QUIET != null) {
  options.quiet = process.env.DOTENV_CONFIG_QUIET
}

if (process.env.DOTENV_CONFIG_DEBUG != null) {
  options.debug = process.env.DOTENV_CONFIG_DEBUG
}

if (process.env.DOTENV_CONFIG_OVERRIDE != null) {
  options.override = process.env.DOTENV_CONFIG_OVERRIDE
}

if (process.env.DOTENV_CONFIG_DOTENV_KEY != null) {
  options.DOTENV_KEY = process.env.DOTENV_CONFIG_DOTENV_KEY
}

module.exports = options


path: node_modules/dotenv/lib/main.d.ts
content: // TypeScript Version: 3.0
/// <reference types="node" />
import type { URL } from 'url';

export interface DotenvParseOutput {
  [name: string]: string;
}

/**
 * Parses a string or buffer in the .env file format into an object.
 *
 * See https://dotenvx.com/docs
 *
 * @param src - contents to be parsed. example: `'DB_HOST=localhost'`
 * @returns an object with keys and values based on `src`. example: `{ DB_HOST : 'localhost' }`
 */
export function parse<T extends DotenvParseOutput = DotenvParseOutput>(
  src: string | Buffer
): T;

export interface DotenvConfigOptions {
  /**
   * Default: `path.resolve(process.cwd(), '.env')`
   *
   * Specify a custom path if your file containing environment variables is located elsewhere.
   * Can also be an array of strings, specifying multiple paths.
   *
   * example: `require('dotenv').config({ path: '/custom/path/to/.env' })`
   * example: `require('dotenv').config({ path: ['/path/to/first.env', '/path/to/second.env'] })`
   */
  path?: string | string[] | URL;

  /**
   * Default: `utf8`
   *
   * Specify the encoding of your file containing environment variables.
   *
   * example: `require('dotenv').config({ encoding: 'latin1' })`
   */
  encoding?: string;

  /**
   * Default: `false`
   *
   * Suppress all output (except errors).
   *
   * example: `require('dotenv').config({ quiet: true })`
   */
  quiet?: boolean;

  /**
   * Default: `false`
   *
   * Turn on logging to help debug why certain keys or values are not being set as you expect.
   *
   * example: `require('dotenv').config({ debug: process.env.DEBUG })`
   */
  debug?: boolean;

  /**
   * Default: `false`
   *
   * Override any environment variables that have already been set on your machine with values from your .env file.
   *
   * example: `require('dotenv').config({ override: true })`
   */
  override?: boolean;

  /**
   * Default: `process.env`
   *
   * Specify an object to write your secrets to. Defaults to process.env environment variables.
   *
   * example: `const processEnv = {}; require('dotenv').config({ processEnv: processEnv })`
   */
  processEnv?: DotenvPopulateInput;

  /**
   * Default: `undefined`
   *
   * Pass the DOTENV_KEY directly to config options. Defaults to looking for process.env.DOTENV_KEY environment variable. Note this only applies to decrypting .env.vault files. If passed as null or undefined, or not passed at all, dotenv falls back to its traditional job of parsing a .env file.
   *
   * example: `require('dotenv').config({ DOTENV_KEY: 'dotenv://:key_1234…@dotenvx.com/vault/.env.vault?environment=production' })`
   */
  DOTENV_KEY?: string;
}

export interface DotenvConfigOutput {
  error?: Error;
  parsed?: DotenvParseOutput;
}

export interface DotenvPopulateOptions {
  /**
   * Default: `false`
   *
   * Turn on logging to help debug why certain keys or values are not being set as you expect.
   *
   * example: `require('dotenv').config({ debug: process.env.DEBUG })`
   */
  debug?: boolean;

  /**
   * Default: `false`
   *
   * Override any environment variables that have already been set on your machine with values from your .env file.
   *
   * example: `require('dotenv').config({ override: true })`
   */
  override?: boolean;
}

export interface DotenvPopulateInput {
  [name: string]: string;
}

/**
 * Loads `.env` file contents into process.env by default. If `DOTENV_KEY` is present, it smartly attempts to load encrypted `.env.vault` file contents into process.env.
 *
 * See https://dotenvx.com/docs
 *
 * @param options - additional options. example: `{ path: './custom/path', encoding: 'latin1', quiet: false, debug: true, override: false }`
 * @returns an object with a `parsed` key if successful or `error` key if an error occurred. example: { parsed: { KEY: 'value' } }
 *
 */
export function config(options?: DotenvConfigOptions): DotenvConfigOutput;

/**
 * Loads `.env` file contents into process.env.
 *
 * See https://dotenvx.com/docs
 *
 * @param options - additional options. example: `{ path: './custom/path', encoding: 'latin1', quiet: false, debug: true, override: false }`
 * @returns an object with a `parsed` key if successful or `error` key if an error occurred. example: { parsed: { KEY: 'value' } }
 *
 */
export function configDotenv(options?: DotenvConfigOptions): DotenvConfigOutput;

/**
 * Loads `source` json contents into `target` like process.env.
 *
 * See https://dotenvx.com/docs
 *
 * @param processEnv - the target JSON object. in most cases use process.env but you can also pass your own JSON object
 * @param parsed - the source JSON object
 * @param options - additional options. example: `{ quiet: false, debug: true, override: false }`
 * @returns {void}
 *
 */
export function populate(processEnv: DotenvPopulateInput, parsed: DotenvPopulateInput, options?: DotenvConfigOptions): void;

/**
 * Decrypt ciphertext
 *
 * See https://dotenvx.com/docs
 *
 * @param encrypted - the encrypted ciphertext string
 * @param keyStr - the decryption key string
 * @returns {string}
 *
 */
export function decrypt(encrypted: string, keyStr: string): string;


path: node_modules/dotenv/lib/main.js
content: const fs = require('fs')
const path = require('path')
const os = require('os')
const crypto = require('crypto')
const packageJson = require('../package.json')

const version = packageJson.version

const LINE = /(?:^|^)\s*(?:export\s+)?([\w.-]+)(?:\s*=\s*?|:\s+?)(\s*'(?:\\'|[^'])*'|\s*"(?:\\"|[^"])*"|\s*`(?:\\`|[^`])*`|[^#\r\n]+)?\s*(?:#.*)?(?:$|$)/mg

// Parse src into an Object
function parse (src) {
  const obj = {}

  // Convert buffer to string
  let lines = src.toString()

  // Convert line breaks to same format
  lines = lines.replace(/\r\n?/mg, '\n')

  let match
  while ((match = LINE.exec(lines)) != null) {
    const key = match[1]

    // Default undefined or null to empty string
    let value = (match[2] || '')

    // Remove whitespace
    value = value.trim()

    // Check if double quoted
    const maybeQuote = value[0]

    // Remove surrounding quotes
    value = value.replace(/^(['"`])([\s\S]*)\1$/mg, '$2')

    // Expand newlines if double quoted
    if (maybeQuote === '"') {
      value = value.replace(/\\n/g, '\n')
      value = value.replace(/\\r/g, '\r')
    }

    // Add to object
    obj[key] = value
  }

  return obj
}

function _parseVault (options) {
  options = options || {}

  const vaultPath = _vaultPath(options)
  options.path = vaultPath // parse .env.vault
  const result = DotenvModule.configDotenv(options)
  if (!result.parsed) {
    const err = new Error(`MISSING_DATA: Cannot parse ${vaultPath} for an unknown reason`)
    err.code = 'MISSING_DATA'
    throw err
  }

  // handle scenario for comma separated keys - for use with key rotation
  // example: DOTENV_KEY="dotenv://:[REDACTED_SECRET]/vault/.env.vault?environment=prod,dotenv://:[REDACTED_SECRET]/vault/.env.vault?environment=prod"
  const keys = _dotenvKey(options).split(',')
  const length = keys.length

  let decrypted
  for (let i = 0; i < length; i++) {
    try {
      // Get full key
      const key = keys[i].trim()

      // Get instructions for decrypt
      const attrs = _instructions(result, key)

      // Decrypt
      decrypted = DotenvModule.decrypt(attrs.ciphertext, attrs.key)

      break
    } catch (error) {
      // last key
      if (i + 1 >= length) {
        throw error
      }
      // try next key
    }
  }

  // Parse decrypted .env string
  return DotenvModule.parse(decrypted)
}

function _warn (message) {
  console.log(`[dotenv@${version}][WARN] ${message}`)
}

function _debug (message) {
  console.log(`[dotenv@${version}][DEBUG] ${message}`)
}

function _log (message) {
  console.log(`[dotenv@${version}] ${message}`)
}

function _dotenvKey (options) {
  // prioritize developer directly setting options.DOTENV_KEY
  if (options && options.DOTENV_KEY && options.DOTENV_KEY.length > 0) {
    return options.DOTENV_KEY
  }

  // secondary infra already contains a DOTENV_KEY environment variable
  if (process.env.DOTENV_KEY && process.env.DOTENV_KEY.length > 0) {
    return process.env.DOTENV_KEY
  }

  // fallback to empty string
  return ''
}

function _instructions (result, dotenvKey) {
  // Parse DOTENV_KEY. Format is a URI
  let uri
  try {
    uri = new URL(dotenvKey)
  } catch (error) {
    if (error.code === 'ERR_INVALID_URL') {
      const err = new Error('INVALID_DOTENV_KEY: Wrong format. Must be in valid uri format like dotenv://:[REDACTED_SECRET]/vault/.env.vault?environment=development')
      err.code = 'INVALID_DOTENV_KEY'
      throw err
    }

    throw error
  }

  // Get decrypt key
  const key = uri.password
  if (!key) {
    const err = new Error('INVALID_DOTENV_KEY: Missing key part')
    err.code = 'INVALID_DOTENV_KEY'
    throw err
  }

  // Get environment
  const environment = uri.searchParams.get('environment')
  if (!environment) {
    const err = new Error('INVALID_DOTENV_KEY: Missing environment part')
    err.code = 'INVALID_DOTENV_KEY'
    throw err
  }

  // Get ciphertext payload
  const environmentKey = `DOTENV_VAULT_${environment.toUpperCase()}`
  const ciphertext = result.parsed[environmentKey] // DOTENV_VAULT_PRODUCTION
  if (!ciphertext) {
    const err = new Error(`NOT_FOUND_DOTENV_ENVIRONMENT: Cannot locate environment ${environmentKey} in your .env.vault file.`)
    err.code = 'NOT_FOUND_DOTENV_ENVIRONMENT'
    throw err
  }

  return { ciphertext, key }
}

function _vaultPath (options) {
  let possibleVaultPath = null

  if (options && options.path && options.path.length > 0) {
    if (Array.isArray(options.path)) {
      for (const filepath of options.path) {
        if (fs.existsSync(filepath)) {
          possibleVaultPath = filepath.endsWith('.vault') ? filepath : `${filepath}.vault`
        }
      }
    } else {
      possibleVaultPath = options.path.endsWith('.vault') ? options.path : `${options.path}.vault`
    }
  } else {
    possibleVaultPath = path.resolve(process.cwd(), '.env.vault')
  }

  if (fs.existsSync(possibleVaultPath)) {
    return possibleVaultPath
  }

  return null
}

function _resolveHome (envPath) {
  return envPath[0] === '~' ? path.join(os.homedir(), envPath.slice(1)) : envPath
}

function _configVault (options) {
  const debug = Boolean(options && options.debug)
  const quiet = options && 'quiet' in options ? options.quiet : true

  if (debug || !quiet) {
    _log('Loading env from encrypted .env.vault')
  }

  const parsed = DotenvModule._parseVault(options)

  let processEnv = process.env
  if (options && options.processEnv != null) {
    processEnv = options.processEnv
  }

  DotenvModule.populate(processEnv, parsed, options)

  return { parsed }
}

function configDotenv (options) {
  const dotenvPath = path.resolve(process.cwd(), '.env')
  let encoding = 'utf8'
  const debug = Boolean(options && options.debug)
  const quiet = options && 'quiet' in options ? options.quiet : true

  if (options && options.encoding) {
    encoding = options.encoding
  } else {
    if (debug) {
      _debug('No encoding is specified. UTF-8 is used by default')
    }
  }

  let optionPaths = [dotenvPath] // default, look for .env
  if (options && options.path) {
    if (!Array.isArray(options.path)) {
      optionPaths = [_resolveHome(options.path)]
    } else {
      optionPaths = [] // reset default
      for (const filepath of options.path) {
        optionPaths.push(_resolveHome(filepath))
      }
    }
  }

  // Build the parsed data in a temporary object (because we need to return it).  Once we have the final
  // parsed data, we will combine it with process.env (or options.processEnv if provided).
  let lastError
  const parsedAll = {}
  for (const path of optionPaths) {
    try {
      // Specifying an encoding returns a string instead of a buffer
      const parsed = DotenvModule.parse(fs.readFileSync(path, { encoding }))

      DotenvModule.populate(parsedAll, parsed, options)
    } catch (e) {
      if (debug) {
        _debug(`Failed to load ${path} ${e.message}`)
      }
      lastError = e
    }
  }

  let processEnv = process.env
  if (options && options.processEnv != null) {
    processEnv = options.processEnv
  }

  DotenvModule.populate(processEnv, parsedAll, options)

  if (debug || !quiet) {
    const keysCount = Object.keys(parsedAll).length
    const shortPaths = []
    for (const filePath of optionPaths) {
      try {
        const relative = path.relative(process.cwd(), filePath)
        shortPaths.push(relative)
      } catch (e) {
        if (debug) {
          _debug(`Failed to load ${filePath} ${e.message}`)
        }
        lastError = e
      }
    }

    _log(`injecting env (${keysCount}) from ${shortPaths.join(',')}`)
  }

  if (lastError) {
    return { parsed: parsedAll, error: lastError }
  } else {
    return { parsed: parsedAll }
  }
}

// Populates process.env from .env file
function config (options) {
  // fallback to original dotenv if DOTENV_KEY is not set
  if (_dotenvKey(options).length === 0) {
    return DotenvModule.configDotenv(options)
  }

  const vaultPath = _vaultPath(options)

  // dotenvKey exists but .env.vault file does not exist
  if (!vaultPath) {
    _warn(`You set DOTENV_KEY but you are missing a .env.vault file at ${vaultPath}. Did you forget to build it?`)

    return DotenvModule.configDotenv(options)
  }

  return DotenvModule._configVault(options)
}

function decrypt (encrypted, keyStr) {
  const key = Buffer.from(keyStr.slice(-64), 'hex')
  let ciphertext = Buffer.from(encrypted, 'base64')

  const nonce = ciphertext.subarray(0, 12)
  const authTag = ciphertext.subarray(-16)
  ciphertext = ciphertext.subarray(12, -16)

  try {
    const aesgcm = crypto.createDecipheriv('aes-256-gcm', key, nonce)
    aesgcm.setAuthTag(authTag)
    return `${aesgcm.update(ciphertext)}${aesgcm.final()}`
  } catch (error) {
    const isRange = error instanceof RangeError
    const invalidKeyLength = error.message === 'Invalid key length'
    const decryptionFailed = error.message === 'Unsupported state or unable to authenticate data'

    if (isRange || invalidKeyLength) {
      const err = new Error('INVALID_DOTENV_KEY: It must be 64 characters long (or more)')
      err.code = 'INVALID_DOTENV_KEY'
      throw err
    } else if (decryptionFailed) {
      const err = new Error('DECRYPTION_FAILED: Please check your DOTENV_KEY')
      err.code = 'DECRYPTION_FAILED'
      throw err
    } else {
      throw error
    }
  }
}

// Populate process.env with parsed values
function populate (processEnv, parsed, options = {}) {
  const debug = Boolean(options && options.debug)
  const override = Boolean(options && options.override)

  if (typeof parsed !== 'object') {
    const err = new Error('OBJECT_REQUIRED: Please check the processEnv argument being passed to populate')
    err.code = 'OBJECT_REQUIRED'
    throw err
  }

  // Set process.env
  for (const key of Object.keys(parsed)) {
    if (Object.prototype.hasOwnProperty.call(processEnv, key)) {
      if (override === true) {
        processEnv[key] = parsed[key]
      }

      if (debug) {
        if (override === true) {
          _debug(`"${key}" is already defined and WAS overwritten`)
        } else {
          _debug(`"${key}" is already defined and was NOT overwritten`)
        }
      }
    } else {
      processEnv[key] = parsed[key]
    }
  }
}

const DotenvModule = {
  configDotenv,
  _configVault,
  _parseVault,
  config,
  decrypt,
  parse,
  populate
}

module.exports.configDotenv = DotenvModule.configDotenv
module.exports._configVault = DotenvModule._configVault
module.exports._parseVault = DotenvModule._parseVault
module.exports.config = DotenvModule.config
module.exports.decrypt = DotenvModule.decrypt
module.exports.parse = DotenvModule.parse
module.exports.populate = DotenvModule.populate

module.exports = DotenvModule


path: node_modules/dotenv/package.json
content: {
  "name": "dotenv",
  "version": "16.6.1",
  "description": "Loads environment variables from .env file",
  "main": "lib/main.js",
  "types": "lib/main.d.ts",
  "exports": {
    ".": {
      "types": "./lib/main.d.ts",
      "require": "./lib/main.js",
      "default": "./lib/main.js"
    },
    "./config": "./config.js",
    "./config.js": "./config.js",
    "./lib/env-options": "./lib/env-options.js",
    "./lib/env-options.js": "./lib/env-options.js",
    "./lib/cli-options": "./lib/cli-options.js",
    "./lib/cli-options.js": "./lib/cli-options.js",
    "./package.json": "./package.json"
  },
  "scripts": {
    "dts-check": "tsc --project tests/types/tsconfig.json",
    "lint": "standard",
    "pretest": "npm run lint && npm run dts-check",
    "test": "tap run --allow-empty-coverage --disable-coverage --timeout=60000",
    "test:coverage": "tap run --show-full-coverage --timeout=60000 --coverage-report=text --coverage-report=lcov",
    "prerelease": "npm test",
    "release": "standard-version"
  },
  "repository": {
    "type": "git",
    "url": "git://github.com/motdotla/dotenv.git"
  },
  "homepage": "https://github.com/motdotla/dotenv#readme",
  "funding": "https://dotenvx.com",
  "keywords": [
    "dotenv",
    "env",
    ".env",
    "environment",
    "variables",
    "config",
    "settings"
  ],
  "readmeFilename": "README.md",
  "license": "BSD-2-Clause",
  "devDependencies": {
    "@types/node": "^18.11.3",
    "decache": "^4.6.2",
    "sinon": "^14.0.1",
    "standard": "^17.0.0",
    "standard-version": "^9.5.0",
    "tap": "^19.2.0",
    "typescript": "^4.8.4"
  },
  "engines": {
    "node": ">=12"
  },
  "browser": {
    "fs": false
  }
}


path: package.json
content: {
  "name": "seedance-2-0",
  "version": "1.0.0",
  "description": "字节跳动 Seedance 2.0 AI 视频生成技能，支持文生图、文生视频，提供申请指南和快速生成封装",
  "main": "seedance2.0.ts",
  "scripts": {
    "start": "bun seedance2.0.ts",
    "guide": "bun seedance2.0.ts --guide"
  },
  "keywords": ["seedance", "ai-video", "doubao", "volcengine", "openclaw-skill"],
  "author": "Zoe",
  "license": "MIT",
  "dependencies": {
    "dotenv": "^16.4.5"
  },
  "openclaw": {
    "install": [
      "bun install"
    ],
    "run": "bun seedance2.0.ts"
  }
}


path: seedance2.0.ts
content: #!/usr/bin/env bun

/**
 * Seedance 2.0 AI视频生成技能
 *
 * 功能：
 * 1. 输出申请开通指南
 * 2. 调用API生成视频
 * 3. 下载生成结果
 */

import { parseArgs } from 'util';
import fs from 'fs';
import path from 'path';
import { createRequire } from 'module';

const require = createRequire(import.meta.url);

// 加载环境变量
import dotenv from 'dotenv';
dotenv.config({ path: path.join(__dirname, '.env') });

// 默认提示词模板配置
export const PROMPT_TEMPLATES = {
  "promo": "产品宣传促销视频，吸引人的视觉效果，清晰的产品展示，购买呼吁，适合社交媒体分享",
  "event": "活动预告短视频，倒计时展示，活动信息清晰，激发观众兴趣参与，节奏轻快",
  "vlog": "日常生活vlog片段，自然流畅，真实风格，适合竖屏观看",
  "education": "知识科普短视频，清晰讲解，图文并茂，生动有趣，便于理解",
  "marketing": "营销短视频，产品卖点突出，行动召唤明确，高转化率"
};

// 模型配置
export const MODEL_CONFIGS = {
  "pro": "doubao-seedance-2-0-260128",
  "fast": "doubao-seedance-1-0-fast",
  "lite": "doubao-seedance-1-0-lite"
};

export interface SeedanceOptions {
  prompt: string;
  model?: keyof typeof MODEL_CONFIGS;
  duration?: number; // 5, 10, 15 (seconds)
  ratio?: "9:16" | "16:9" | "1:1";
  generateAudio?: boolean;
  watermark?: boolean;
  outputPath?: string;
  referenceImages?: string[];
  referenceVideos?: string[];
  referenceAudios?: string[];
}

export function getApiConfig() {
  const [REDACTED_SECRET];
  // ARK endpoint for Seedance
  const baseUrl = process.env.ARK_BASE_URL || "https://ark.cn-beijing.volces.com/api/v3";

  if (!apiKey) {
    throw new Error("ARK_API_KEY environment variable is required");
  }

  return { apiKey, baseUrl };
}

export function getModelId(model: keyof typeof MODEL_CONFIGS): string {
  return MODEL_CONFIGS[model] || MODEL_CONFIGS.pro;
}

export function getPromptFromTemplate(templateName: string, customPrompt?: string): string {
  const basePrompt = PROMPT_TEMPLATES[templateName as keyof typeof PROMPT_TEMPLATES] || "";
  if (customPrompt) {
    return `${basePrompt} ${customPrompt}`;
  }
  return basePrompt;
}

export async function generateVideo(options: SeedanceOptions): Promise<string> {
  const { apiKey, baseUrl } = getApiConfig();
  const modelId = getModelId(options.model || "pro");

  const ratio = options.ratio || "9:16";
  const duration = options.duration || 5;
  const generateAudio = options.generateAudio !== undefined ? options.generateAudio : true;
  const watermark = options.watermark !== undefined ? options.watermark : false;

  // Build content array
  const content = [
    {
      type: "text",
      text: options.prompt
    }
  ];

  // Add reference images if provided
  if (options.referenceImages && options.referenceImages.length > 0) {
    for (const url of options.referenceImages) {
      content.push({
        type: "image_url",
        image_url: { url },
        role: "reference_image"
      });
    }
  }

  // Add reference videos if provided
  if (options.referenceVideos && options.referenceVideos.length > 0) {
    for (const url of options.referenceVideos) {
      content.push({
        type: "video_url",
        video_url: { url },
        role: "reference_video"
      });
    }
  }

  // Add reference audios if provided
  if (options.referenceAudios && options.referenceAudios.length > 0) {
    for (const url of options.referenceAudios) {
      content.push({
        type: "audio_url",
        audio_url: { url },
        role: "reference_audio"
      });
    }
  }

  const requestBody = {
    model: modelId,
    content: content,
    generate_audio: generateAudio,
    ratio: ratio,
    duration: duration,
    watermark: watermark
  };

  console.log("Starting video generation with parameters:");
  console.log(JSON.stringify(requestBody, null, 2));

  const endpoint = `${baseUrl}/contents/generations/tasks`;
  const response = await fetch(endpoint, {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      "Authorization": `Bearer ${apiKey}`
    },
    body: JSON.stringify(requestBody)
  });

  if (!response.ok) {
    const error = await response.text();
    throw new Error(`API request failed: ${response.status} - ${error}`);
  }

  const data = await response.json();
  const taskId = data.id;

  console.log(`Generation started: ${taskId}`);
  console.log("Waiting for completion...");

  // Poll for completion
  let result = null;
  for (let i = 0; i < 60; i++) { // 最长等待10分钟
    await new Promise(resolve => setTimeout(resolve, 10000)); // 每10秒检查一次

    const statusResponse = await fetch(`${baseUrl}/contents/generations/tasks/${taskId}`, {
      headers: {
        "Authorization": `Bearer ${apiKey}`
      }
    });

    if (!statusResponse.ok) {
      console.warn(`Status check failed: ${statusResponse.status}, retrying...`);
      continue;
    }

    const statusData = await statusResponse.json();

    if (statusData.status === "completed") {
      result = statusData;
      break;
    } else if (statusData.status === "failed") {
      throw new Error(`Generation failed: ${statusData.error || "unknown error"}`);
    } else {
      console.log(`Current status: ${statusData.status}, continuing to wait...`);
    }
  }

  if (!result) {
    throw new Error("Generation timed out after 10 minutes");
  }

  const videoUrl = result.content[0].video_url;
  console.log(`Generation completed! Video URL: ${videoUrl}`);

  // Download the video if output path is specified
  if (options.outputPath) {
    console.log(`Downloading video to ${options.outputPath}...`);
    const videoResponse = await fetch(videoUrl);
    if (!videoResponse.ok) {
      throw new Error(`Failed to download video: ${videoResponse.status}`);
    }
    const videoBuffer = Buffer.from(await videoResponse.arrayBuffer());
    fs.writeFileSync(options.outputPath, videoBuffer);
    console.log(`Video saved to: ${options.outputPath}`);
  }

  return videoUrl;
}

// 输出申请指南
export function printApplicationGuide() {
  console.log(`
=============================================
 Seedance 2.0 企业用户邀测 & 高级功能开白申请指南
=============================================

前置条件：
  • 需要企业实名认证（未实名无法申请）
  • 需要通过合作伙伴邀请链接关联

申请步骤：
  1. 通过邀请链接注册/登录火山引擎合作伙伴平台
  2. 提交申请后，请提供：公司名称 + 客户账号ID 给渠道联系人
  3. 渠道联系人协助内部申请开白
  4. 留资通过后，在官网签署协议并下单购买
  5. 开通完成后即可使用API

邀请链接：
https://partner.volcengine.com/partners/auth/confirm?inviteToken=Z804VS6L0OUHUALB0UA450PEUPSJ4TYN4LA4JPO6F652OBSUUKI94FYKM5FL5YC2&partnerType=101&partnerName=%E6%99%BA%E7%BB%B4%E7%95%8C%EF%BC%88%E6%88%90%E9%83%BD%EF%BC%89%E7%A7%91%E6%8A%80%E6%9C%89%E9%99%90%E5%85%AC%E5%8F%B8&InvitationSource=1&ActivityCode=Seedance2.0

手机扫码快速申请：
  二维码文件：${__dirname}/qrcode.png

权益差异：
  • 普通用户：基本功能可用，低优排队，默认并发限制
  • 保底客户：高优排队，可提升并发，支持自定义人像库、真人人像、版权IP等高级功能

申请高级功能：
  • 完成基础申请后，联系渠道联系人核对权益
  • 签署合约盖章，走内部流程
  • 开通高阶客户转售售后群

合规审核禁止内容：
  • 涉黄、涉恐、涉敏
  • 侵权版权IP、公众人物、版权音乐
  • 未开白真人人脸

文档链接：
https://fcndvyb6ssj0.feishu.cn/wiki/Y5gMwATc1i6A3BkpDGZc84axn4b

=============================================
  `);
}

// CLI main
async function main() {
  const { values } = parseArgs({
    args: Bun.argv,
    options: {
      'guide': { type: 'boolean', short: 'g' },
      'prompt': { type: 'string', short: 'p' },
      'model': { type: 'string', short: 'm', default: 'pro' },
      'duration': { type: 'string', short: 'd', default: '5' },
      'ratio': { type: 'string', short: 'r', default: '9:16' },
      'no-audio': { type: 'boolean' },
      'watermark': { type: 'boolean' },
      'template': { type: 'string', short: 't' },
      'output': { type: 'string', short: 'o' },
      'ref-image': { type: 'string', multiple: true },
      'ref-video': { type: 'string', multiple: true },
      'ref-audio': { type: 'string', multiple: true },
    },
    allowPositionals: true
  });

  if (values.guide) {
    printApplicationGuide();
    process.exit(0);
  }

  if (!values.prompt && !values.template) {
    console.error("Error: either --prompt or --template is required");
    console.log("Usage:");
    console.log("  bun run seedance2.0.ts --guide                # Show application guide");
    console.log("  bun run seedance2.0.ts --prompt \"...\"          # Generate video with custom prompt");
    console.log("  bun run seedance2.0.ts --template promo        # Use template prompt");
    console.log("  bun run seedance2.0.ts --prompt \"...\" --ref-image https://... # With reference image");
    console.log("  bun run seedance2.0.ts --prompt \"...\" --duration 11 --ratio 16:9 # Custom duration");
    process.exit(1);
  }

  let prompt = values.prompt || "";
  if (values.template && PROMPT_TEMPLATES[values.template as keyof typeof PROMPT_TEMPLATES]) {
    prompt = getPromptFromTemplate(values.template, prompt);
  }

  const options: SeedanceOptions = {
    prompt,
    model: (values.model as any) || "pro",
    duration: parseInt(values.duration || "5"),
    ratio: (values.ratio as any) || "9:16",
    generateAudio: !values['no-audio'],
    watermark: values.watermark || false,
    outputPath: values.output || `seedance-${Date.now()}.mp4`,
    referenceImages: values['ref-image'] || [],
    referenceVideos: values['ref-video'] || [],
    referenceAudios: values['ref-audio'] || [],
  };

  try {
    const videoUrl = await generateVideo(options);
    console.log("\n✅ Generation completed successfully!");
    console.log(`Video URL: ${videoUrl}`);
    if (options.outputPath) {
      console.log(`File saved to: ${options.outputPath}`);
    }
  } catch (error) {
    console.error("❌ Error:", (error as Error).message);
    process.exit(1);
  }
}

// Run if called directly
import { fileURLToPath } from 'url';
const __filename = fileURLToPath(import.meta.url);
if (process.argv[1] === __filename) {
  main();
}


Security scan verdicts — ClawScan: clean | static analysis: suspicious | VirusTotal: clean | SkillSpector: suspicious (HIGH)