# @denny-il/devenv 中文文档

规范地址：https://npmcn.com/package/%40denny-il/devenv/

版本：0\.7\.0
npm 元数据更新时间：2026-10-31T06:59:50.453Z
中文译文更新时间：2026-11-12T10:23:05.021Z
软件包许可：MIT

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

原始 npm 页面：https://www.npmjs.com/package/%40denny-il/devenv
原文对照：https://npmcn.com/package/%40denny-il/devenv/?lang=original
源码仓库：https://github.com/denny-il/devenv

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

- 包体积（解压后）：174 kB，37 个文件
- 模块格式：ES Module
- TypeScript 类型：包内自带
- Node.js 要求：\>=22\.18\.0
- 运行依赖：0 个
- 首次发布：2026-10-10T16:38:46.823Z
- 最新版本发布：2026-10-31T06:59:50.149Z
- 近 30 天下载量：2578（2026-10-12 至 2026-11-10，npm 官方下载统计）
- 已发布版本数：8（近 12 个月 8 个）

## 中文简介

每个工作树都有一个孤立的本地开发堆栈:编译服务、主机应用程序和Tailscale上的HTTPS

## 安装

```sh
npm install @denny-il/devenv
```

也可以使用：`pnpm add @denny-il/devenv`、`yarn add @denny-il/devenv`、`bun add @denny-il/devenv`

## README

# 守护者

一个项目本地堆栈的命令: Docker 编译服务, apps 运行在主机上, 当被问及时, HTTPS 访问 a 上的每个设备 分级网.

每一次退票都有自己的堆积 所以项目运行的几棵工作树 并肩而来. 除了这台机器,什么也听不到.

Linux和macOS,节点22.18或更新. 配有编译服务的堆栈也需要 Docker Confose 2.24.4 或更新鲜.

## 安装

```sh
pnpm add -D @denny-il/devenv
```

```jsonc
// package.json
{ "scripts": { "local": "devenv" } }
```

### 更新

```sh
pnpm update @denny-il/devenv
```

此移动到最新版本中 `package.json` 允许。 在此之前 1.0 范围,例如 `^0.2.0` 仅覆盖补丁发布; `--latest` 过去了 这个.

pnpm更喜欢已经出去一天的版本,所以更新可以保持 旧版本在那之前。 要立即发布, 豁免包在 项目的 `pnpm-workspace.yaml`数字 :

```yaml
minimumReleaseAgeExclude:
  - "@denny-il/devenv"
```

## 代理技能

软件包包含在项目中使用的编码代理技术 发射装置:命令及其规则、配置以及如何移动一个 上线 从已安装的软件包中安装,然后再次安装 更新 :

```sh
npx skills add ./node_modules/@denny-il/devenv
```

## 图标

| 命令 | 它会做什么 |
| --- | --- |
| `devenv up` | 启动任何服务, 运行 `compose.init`,指定应用程序端口,并运行 `setup`。 。 。 . |
| `devenv start` | 运行一个堆起的每个应用程序,直到一站. |
| `devenv start --tailscale` | 同样的,随着应用 服务在这个机器的尾网 通过HTTPS. |
| `devenv stop` | 停止这个工作树的运行 `start`如果有的话,并等待 直到它的应用停止. |
| `devenv status` | 显示服务、应用程序 URL,以及是否 `start` 正在运行. |
| `devenv run -- <command>` | 运行带有堆栈环境的命令. |
| `devenv test [-- <args>]` | 在他们自己的新堆上进行测试,之后总是被移除. |
| `devenv down` | 停止应用程序和服务; 保留服务的名称卷. |
| `devenv reset` | 停止应用并删除此工作树的容器,卷,图像,状态. |
| `devenv list` | 显示此机上的每个堆栈 . |
| `devenv prune` | 删除已退出的堆栈及其数据. |
| `devenv setup [docker] [tailscale]` | 在此机上安装多克和分级,并设置. |
| `devenv tailnet info` | 显示这台机器的尾网名称 以及它无法服役的原因 如果有的话. |
| `devenv tailnet serve` | 服务于给定的本地端口到尾网,直到停止,没有任何项目. |

堆栈有两部分,各有生平. `up` 编写报告: 服务,它一直运行在 Docker 下直到 `down`,以及 `setup`。 。 。 . `start` ctrl-C,一个信号, 或者说 `devenv stop`。要在更改后重新启动应用程序,它们无法接收 他们自己的,跑 `devenv stop`,则 `devenv start`运行 `devenv up` 再来一次 服务变更后, `compose.init` 或者说 `setup`,例如拉动 迁移,再起后.

`devenv restart` 于 0.7. 0 中被删除,但失败时有信件命名它 替换。 在此之前, `start` 也开始服务并运行 `setup`。 。 。 .

## 装一台机器

`devenv setup` 检查这台机器上的堆栈需要什么并安装什么 失踪. `devenv setup docker` 财务报告和审定财务报表 `devenv setup tailscale` 做两个之一. 它在Linux上安装了自有安装器的Docker和Tailscale 马科斯的土生土长 安装者要密码 .

在 Linux 上,它也同时开始两种, 标记到 Tailscale, 让用户运行 多克和在Tailscale服务。 只有一个人能做的是打印: macOS 打开两个应用程序并签名, 并在任何启用 HTTPS 的机器上 尾网证书.

再运行到检查每行; 它不会改变任何已经存在的 已经就位.

## 一个项目提供什么

一个项目适应发射装置,而不是相反.

-   **编写文件( 可选) .** 基本文件和每个模式的叠加。 服务出版 它们在 Docker 指定的回路端口上的端口 (单位:千美元)`ports: [{ target: 5432, host_ip: 127.0.0.1 }]`永远不要在固定的. 准备状态是 `healthcheck`服务一旦开通,就准备好. 启动器命名了“ 编译” 项目, 只开始服务 在剖面图之外.
-   **应用软件.** 每一个都从环境中夺去其港口 监听 `127.0.0.1`: dev 服务器,或构建然后构建的命令 服务建筑。 每个应用程序自行选取;一叠可以混合两种.
-   **环境.** 从堆栈到变量的函数 命令获取, 在根上方 `.env`一棵没有 `.env` 得到主检查.

## 只有主机的应用程序

没有容器依赖性的项目省略 `compose` (或设定) `compose: { files: [] }` (没有上下文) 普通命令从不探测或启动 Docker 这些堆栈,包括 `status`, (中文(简体) ), `down`, (中文(简体) ), `reset` 财务报告和审定财务报表 `test`。 。 。 .

```ts
import { defineConfig } from "@denny-il/devenv";

export default defineConfig({
  name: "app",
  apps: {
    server: {
      command: "pnpm server dev",
      ports: { http: {}, worker: { internal: true } },
      env: (ports) => ({
        HOST: "127.0.0.1",
        PORT: ports.http,
        WORKER_PORT: ports.worker,
      }),
    },
    web: {
      command: "pnpm web dev",
      env: (ports) => ({ HOST: "127.0.0.1", PORT: ports.http }),
    },
  },
  env: ({ root, port, url }) => ({
    APP_CONFIG: `${root}/config.ts`,
    API_ORIGIN: `http://127.0.0.1:${port("server.http")}`,
    WEB_URL: url("web"),
  }),
});
```

`up` 运行设置和指定并记住端口,所以 `run` 可以使用 环境; `start` 像往常一样运行应用程序 `start --tailscale` 服务于 公共应用端口 并保持内部的隐私. `status` 报告这些 URL 是否为 `start` 正在运行,不是每个应用程序都回答. `down` 暂停 a 运行 `start`标记堆栈停止并保持其港口; `reset` 暂停 a 运行 `start` 并去去州. 主机文件中的 App 数据留给 管理项目.

`test` 运行 `test.setup` 财务报告和审定财务报表 `test.command` 带有新应用程序端口和 a 单独上下文,不启动应用程序. `list` 呼叫准备 只有主机堆栈 `ready`,而只有东道主的孤儿可以在没有多克的情况下被挤出. `list` 需求 仅用于装有容器的Dev堆栈; `prune` 需求 它的堆栈,其测试可能 离开了多克资源.

在转换已存在的 Compose 堆栈之前, 运行 `reset` 删除其 资源。 旧的状态文件仍为状态; 删除 `compose` 从 配置不会绕过他们的清理,和 `reset` 能取名清净. 如果状态无法读取,则其模式未知: `reset` 尝试 由名清净. 当 Docker 不可用时, 它会重新发送本地状态并警告 指定项目可能仍有容器或体积需要取出.

仅包含一个配置 `compose.test` 文件保存 `start`, (中文(简体) ), `up`, (中文(简体) ), `status`, (中文(简体) ), `list` 财务报告和审定财务报表 `down` 独立于多克. `test`, (中文(简体) ), `reset` 和孤苦 需要多克来管理它的测试堆栈. 删除测试文件不 块主机应用程序:保存的清理元数据保存到 `reset`被抛弃了 测试资源仍然可以稍后删除。 编译变量被刷新 ; 当 Dev 编译服务可以创建时冻结 数量.

## 配置

`devenv.config.ts` (或 `.js`在项目根中,从 它下面的任何目录 :

```ts
import { defineConfig } from "@denny-il/devenv";

export default defineConfig({
  // Names the Compose projects: `shop-local-<worktree>`, `shop-test-<worktree>-<run>`.
  name: "shop",

  compose: {
    files: [".infra/compose.yml"],
    dev: [".infra/compose.local.yml"],
    test: [".infra/compose.test.yml"],
    // Services that do a job and exit. Each runs once the others are ready.
    init: ["create-bucket"],
    // Variables for the Compose files. A stack keeps the values its volumes
    // were created with until `reset`.
    env: {
      POSTGRES_USER: process.env.POSTGRES_USER || "shop",
      POSTGRES_PASSWORD: process.env.POSTGRES_PASSWORD || "shop",
    },
  },

  // Started by `start` in this order, without waiting for one another.
  apps: {
    api: {
      command: "pnpm --filter api dev",
      // `internal` ports are reserved, but neither listed nor served.
      ports: { proxy: {}, worker: { internal: true } },
      env: (ports) => ({
        API_HOST: "127.0.0.1",
        API_PORT: ports.proxy,
        WORKER_PORT: ports.worker,
      }),
    },
    // Without `ports`, an app has one port named `http`.
    web: {
      command: "pnpm --filter web dev",
      env: (ports) => ({ HOST: "127.0.0.1", PORT: ports.http }),
      // Optional: `start` reports the stack ready once this answers.
      ready: { path: "/" },
    },
  },

  env: ({ service, vars, url, project }) => ({
    DATABASE_URL: `postgresql://${vars.POSTGRES_USER}:${vars.POSTGRES_PASSWORD}@127.0.0.1:${service("postgres").port(5432)}/shop`,
    API_URL: `${url("api.proxy")}/api`,
    WEB_URL: url("web"),
    // Browsers share cookies across ports: a name per worktree keeps their
    // sessions apart.
    COOKIE_PREFIX: project,
  }),

  // Run by `up` once the services are up.
  setup: ["pnpm database migrate", "pnpm database seed"],

  test: {
    setup: ["pnpm database migrate"],
    // Arguments after `devenv test --` are added; a function decides itself.
    command: "vitest --run",
    env: { DATABASE_TESTS: "true" },
    // Compose variables of the test stack alone, over `compose.env`.
    compose: { env: { POSTGRES_PASSWORD: "test" } },
  },

  // Printed under the URLs by `start` and `status`.
  info: () => ({ "Sign-in": "admin@shop.local / admin" }),
});
```

命令是 shell 的行,或者是程序及其参数的列表.

函数将堆栈作为上下文 :

| 成员 | 这是什么 |
| --- | --- |
| `service(name).port(target)` | 环回端口多克发布服务端口开启. |
| `port(ref)` | 应用程序端口 : `'api.proxy'`,或 `'web'` 一个端口的应用程序. |
| `url(ref)` | 端口的源头. |
| `vars` | 堆栈使用时的 Confose 变量 . |
| `project` | 堆栈"作曲"项目名称. |
| `root` | 项目根. |
| `tailnet` | 这机器的尾网名称,下方 `start --tailscale`。 。 。 . |

## 堆栈的表现

-   **开口.** Docker 指定服务端口; 启动器选择免费 应用程序的端口,并在下次运行时使用相同的端口 免费, 所以 URL 打开其他地方继续工作 .
-   **州会.** 每个堆栈的端口和作曲变量都保存在 `~/.local/state/devenv/stacks/<project>.json` (单位:千美元) `$XDG_STATE_HOME` 何时 ),而不是在离职时。 所以证书没有工作空间, 并仍然可以找到一个堆栈 在其退货之后.
-   **准备.** 应用开始顺序不相等. 一个应用 `ready` 一旦它的端口接受连接, 计数就绪, 或,带有 `path`,通过HTTP回答,状态低于400. `start` 一旦每个这样的应用程序都准备好了就打印 URL, 在此之前只打印 它在等着呢 一个应用没有 `ready` 报告为开始,其中 还没回答呢 在它之前退出的应用程序 已准备好,或尚未准备好 `timeout` (300秒,除非 ),启动失败并停止堆栈.
-   **停下来.** 每个应用程序的流程组都得到一个SIGINT,无论停止什么 `start`,以及 `start` 结尾 `Stopped (<signal>): <apps>`。 。 。 . `devenv stop` 停止工作树的运行 `start` 从任何地方,和 `devenv start` 再次运行应用程序 各种服务一直持续。 十个 数秒后,一个应用程序的流程组中仍然运行的是 kill, 即使应用程序的命令本身已经退出: 服务器 也就是停止建设 它开始得到整个10秒。 任何应用程序 停止停止堆叠.
-   **考证.** 每次运行都有自己的编曲项目,在运行时删除 结束,Ctrl-C上也有,为它所建的图像. 被杀死的一跑 直接清理 下一个,或 `reset`,连同任何 `compose.init` 工作它运行.
-   **`.env` 在工作树上.** `.env` 不被检查,所以一个工作树 开始没有。 直到它拥有它自己的, 主要的退票已经加载, 一条线说。 一个空的 `.env` 在工作树上关闭它.

## 分级

`devenv start --tailscale` 为每个非应用程序端口服务 `internal` 作为 `https://<machine>.<tailnet>.ts.net:<port>`的应用程序 URL 运行,在这个机器上也.

每个尾网和机器一次:

-   在尾网启用 HTTPS 证书 [DNS 页面](https://login.tailscale.com/admin/dns)。 。 。 .
-   在Linux上,允许您的用户服务: `sudo tailscale set --operator=$USER`。 。 。 .

给新名字的第一个请求需要半分钟的证明 已印发。 当发射机停止时, 条目会消失; 这里从未运行过 `tailscale serve reset`,可以抹去每个项目的条目.

所有能在尾网上到达这台机器的人都到达了堆栈. 对a Vite dev 服务器 发射器集 `__VITE_ADDITIONAL_SERVER_ALLOWED_HOSTS`这样 它接受尾网名称而不改变配置.

## 机器上的每一个堆

`devenv list` 显示每个堆栈的取出和是否运行, 被拦截或成为孤儿。 一叠就成了孤儿,一旦它退出了 当一个工作树被删除时会发生 `devenv reset`:其容器和 卷会留在多克 没有任何东西可以管理它们.

`devenv prune` 列出孤儿名单,并在 " 是 " 之后,将孤儿连同他们的 数据与已建图像。 被移动或坐落在没有挂载的磁盘上的检出,外观 与被删除的相同,在达成一致之前阅读清单。 没有 除非给定,否则它不会删除任何东西 `--yes`。 。 。 .

## 沙盒下边

在沙盒中运行命令的代理需要写入 `~/.local/state/devenv`,加上用于堆栈的多克套接字。 无 第二,命令在启动任何事项并命名目录之前停止.

## 制定这套计划

```sh
pnpm check && pnpm test
```

`skills/use-devenv` 描述发射装置在项目中使用的剂 这个 用它描述的行为来改变它.

出版物由 `Publish` 工作流程,手动发送 `main`,与 npm 信任的出版。 发行的PR先会打出版本; 工作流程检查其输入匹配 `package.json`检查 和试验,建造 `dist/` (未执行),出版,然后标记 承诺并创建其 GitHub 释放。 重播完成一个发布 并且再也不会出版另一本书:

```sh
pnpm version patch --no-git-tag-version   # or minor; merged in a PR
gh workflow run publish.yml --ref main -f version=<version>
```

`.agents/skills/release` 给代理人同样的步骤, 检查什么 首先,当一个失败.

## 常见问题

### @denny-il/devenv 是什么？

每个工作树都有一个孤立的本地开发堆栈:编译服务、主机应用程序和Tailscale上的HTTPS

### 如何安装 @denny-il/devenv？

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

### @denny-il/devenv 支持 TypeScript 吗？

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

### @denny-il/devenv 支持 ESM 还是 CommonJS？

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

### @denny-il/devenv 需要什么版本的 Node\.js？

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

### @denny-il/devenv 可以商用吗？

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

### @denny-il/devenv 的下载量有多少？

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

### @denny-il/devenv 还在维护吗？

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

