# ninepm 中文文档

规范地址：https://npmcn.com/package/ninepm/

版本：0\.109\.0
npm 元数据更新时间：2026-11-04T07:14:38.098Z
中文译文更新时间：2026-11-04T07:59:28.269Z
软件包许可：SEE LICENSE IN LICENSE\.md

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

原始 npm 页面：https://www.npmjs.com/package/ninepm
原文对照：https://npmcn.com/package/ninepm/?lang=original
项目主页：https://9pm.ai/

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

- 包体积（解压后）：807 kB，65 个文件
- 模块格式：ES Module
- TypeScript 类型：包内自带
- Node.js 要求：\>=20\.18\.1
- 运行依赖：1 个
- 首次发布：2026-07-03T11:46:13.667Z
- 最新版本发布：2026-11-04T07:14:37.889Z
- 已发布版本数：41（近 12 个月 41 个）

## 中文简介

CLI用于将构建的应用程序部署到9pm.ai。

## 安装

```sh
npm install ninepm
```

也可以使用：`pnpm add ninepm`、`yarn add ninepm`、`bun add ninepm`

## README

# 9点。ai CLI

CLI用于将构建的应用程序部署到9pm.ai。

此包仅包含客户端部署代码。不包括晚上9点。Ai控制平面、基础设施供应代码、迁移、暂存配置、操作符令牌或冒烟测试脚本。

## 安装

```sh
npm i -g ninepm        # persistent `9pm` binary
npx ninepm <args>      # run without installing
```

## 配置

在自己的浏览器中进行身份验证。命令行将令牌存储在本地受保护的存储中：macOS Keychain， Windows DPAPI或Linux Secret Service（当可用时）。如果本机存储不可用，则可以选择使用明文文件存储 `--allow-file-credential-store` 或 `NINEPM_ALLOW_FILE_CREDENTIAL_STORE=1`。

```sh
9pm login
9pm whoami
9pm doctor
```

运行 `9pm login` 再次保留一个仍然有效的凭证，而不是另造一个； `9pm login --fresh` 替换它并撤销旧的。

对于CI，设置 `NINEPM_API_KEY` 你自己在CI的秘密仓库 `--token` 和 `NINEPM_API_KEY` 仍然覆盖存储的登录令牌。

从已登录的计算机中生成用于CI或服务器的密钥 `9pm api-key create --name <name>`;令牌打印一次。 `9pm api-key ls` 列出活动键和 `9pm api-key revoke <key-id>` 退休。每个帐户一次最多持有10个这样的密钥（登录令牌不计算在内）。将密钥存储在任意名称下，但是 `NINEPM_*` 当它生活在一个晚上9点的应用程序的自己的环境，并传递它 `--token`。

## 库存

列出你晚上9点要使用的应用程序。部署或修改前的Ai：

```sh
9pm apps
9pm apps --json
```

弹头栏是你传递给的手柄 `access`， `delete`, `files --project`。

## 版本控制

检查已安装和已发布的CLI版本：

```sh
9pm --version       # installed
9pm latest          # installed vs latest, prints update one-liner when behind
9pm doctor          # surfaces the same drift line alongside credential/account health
```

升级:

```sh
npm i -g ninepm@latest
```

## 部署

部署一个静态目录：

```sh
9pm deploy . --name my-app --slug my-app
```

在相同的段塞下再次部署将替换当前的应用程序。要在不触及它的情况下尝试更改，请在不同的段塞下部署，这会在自己的地址上创建一个单独的应用程序。在免费模式下，你的一个应用槽不能同时容纳一个单独的预览应用。部署到你现有的应用中会更新它的实时版本。练习模式演练当前应用程序的工作流程。单独测试修改后的版本需要另一个应用程序插槽：一个包含更多应用程序的计划（Hobby允许3个）。

### 一个应用的地址保持不变多久

在打印链接或QR码之前检查这一点。实时URL为 `<slug>-<suffix>.9pm.ai`，后缀来自应用的内部id，而不是slug：

-   重新部署在同一段下会保留地址。
-   删除应用程序并在相同的标签下重新创建它会给它一个 **新** 地址，因为新应用会得到一个新id。任何用旧版本打印的东西都不能用了。
-   没有重命名：不同的地址意味着不同的应用程序。
-   你自己的自定义域名，添加到仪表板的域名页面，给应用程序一个你自己的地址。并非每个计划都包含自定义域。

### 不存在的页面

静态站点或 `--entry` Worker应用会以两种方式中的一种来响应没有文件的路径。每次部署都会打印 `Missing pages:` 线。

-   `--no-spa` （新应用的默认值）：路径返回状态404，并带有部署自己的状态 `404.html` 当它有一个的时候。 `/` 仍然是 `index.html`，无扩展链路工作： `/menu` 服务 `menu.html`，或重定向到 `/menu/` 当只有 `menu/index.html` 存在, `/menu/` 服务 `menu/index.html`． 对于多页面网站来说，删除或输入错误的页面应该显示“未找到”，而不是显示主页。
-   `--spa`：所有没有文件的路径 `index.html`因此，在浏览器中进行路由的单页应用程序会通过深层链接或刷新加载。这包括点路径，例如 `/users/jane.smith` 和丢失的文件，如 `/missing.json`，这将获得应用程序的外壳，而不是404。

```sh
9pm deploy ./dist --name my-spa --spa
```

应用程序会记住这个选择：没有任何一个标志的部署会保留它，而发布失败的部署会保留之前的选择。在此选择存在之前创建的应用程序继续服务 `index.html` 对于每个不匹配的路径，直到部署传递其中一个标志。一个worker应用自己的 `Response`，包括404，总是原样返回。这些标志不适用于 `--bundle` 或者容器应用程序。

部署一个已构建的框架输出目录：

```sh
npm run build
9pm deploy ./dist --check
9pm deploy ./dist --name my-app --slug my-app
```

使用托管SQL数据库部署：

```sh
9pm deploy ./dist --name my-app --slug my-app --with-db
```

将可选的简短描述附加到部署（显示在仪表板中的版本旁边；最多200个字符）：

```sh
9pm deploy ./dist --name my-app --slug my-app --description "Fix login redirect"
9pm deploy ./dist --name my-app --slug my-app --owner acme   # into an organisation you are an admin of
```

CLI在上传和完成后打印公共应用的URL。

存储和共享工作文件：

```sh
9pm files put ./report.pdf
9pm files share <file-id> --expires 24h
9pm files put ./notes.md --project my-app --path notes/release.md
9pm files share <file-id> --project my-app --public
```

个人文件和项目文件都计入帐户文件存储限制。股票链接到期，上限为7天。

分享链接如下 **默认情况下仅为所有者**：该链接仅为您打开，已登录。添加 `--public` 当收件人没有帐户时，该链接不需要登录，因此任何获得URL的人都可以下载该文件，直到它过期为止。不要使用 `--public` 用于包含个人数据、凭据或数据库导出的任何内容。

部署一个一流的Worker运行时应用：

```sh
9pm deploy ./examples/worker-app --name worker-app --slug worker-app --runtime worker --entry src/index.js --assets public --with-db
```

这个 `--runtime worker` entry必须是一个绑定的兼容fetch的JavaScript模块，带有默认的导出。与 `--with-db`，应用程序接收到 `env.DB` 并且应该使用与sqlite兼容的预处理语句。

选择哪些文件是公开的 `--assets <dir>`：只有该目录下的文件被服务，从应用程序的根目录(`public/index.html` 答案在 `/`)，并且不会上传deploy目录中的其他内容。使用 `--no-assets` 当条目本身服务于每个响应时。应用程序会记住这个选择，所以以后的部署不需要重复国旗；传递另一个标志或另一个目录来更改它-没有办法返回到发布所有内容。一个从来没有选择过服务的worker应用 **部署目录中的每个文件（条目除外）** 公开地说，服务器助手和剩菜之类的 `index.js.orig` 包括;这样的应用程序的每次部署都会打印一个警告，并命名这些文件 `9pm deploy --check` 列出部署将公开的每个文件。它的摘要统计了扫描的文件，除了选择上传的文件（条目和公共文件）； `--check` 它本身不会上传任何内容。

从本地Docker构建部署一个容器应用：

```sh
9pm deploy . --check --runtime container --port 8080
9pm deploy . --name container-app --slug container-app --runtime container --port 8080 --health-path /health --region auto
```

容器在本地部署需要Docker。CLI构建一个 `linux/amd64` 映像，导出它，根据每个应用程序限制和帐户保留映像配额检查映像大小，通过短时间会话上传，并最终完成队列部署。容器必须监听 `0.0.0.0:$PORT` -经常阅读 `PORT` Env变量，而不是硬编码所选择的 `--port`，因为在某些情况下，平台会保留所选择的移植，并向应用提供不同的移植；集 `--health-path` 当应用程序有一个廉价的就绪端点时。

容器cpu有 **共享** 默认情况下：每个人都可以在一段时间内远高于其基线，然后一旦爆发限额被限制到核心的一小部分。这适合web应用程序。持续的CPU工作——视频或音频编码、转码、ML推理——需要专用的内核：add `--cpu-kind performance`． 每个高性能CPU至少有2gb的内存，价格明显更高，并且只在包含它的计划中可用；没有它的计划拒绝有它的部署 `plan_container_performance_cpus_unavailable`。

使用 `--with-db` 当容器需要托管SQL时。应用程序接收到 `NINEPM_SQL_URL` 和 `NINEPM_DB_BINDINGS`;发送 `POST` 请求 `NINEPM_SQL_URL` 与 `{ "binding": "DB", "sql": "SELECT 1", "params": [] }`． 一些位置也设置了 `NINEPM_SQL_TOKEN` -当它存在时，发送 `Authorization: Bearer <that token>` 对每一个请求，或桥拒绝他们所有与 `401 {"error":"unauthorized"}`． 在每次调用时从环境中读取URL和令牌，而不是硬编码：URL在不同位置之间是不同的，并且令牌在每次部署时都要重新发布。对于本地开发，使用应用程序在存储库层后面的普通本地数据库适配器，并保持部署的SQL与SQLite兼容。

区域是提供者中立的： `auto`， `us-east`， `us-west`， `europe`， `asia`， `south-america`， `middle-east`， `oceania`， `africa`。

当一个容器应用程序无法启动或者你想在事后调查它时，检索它最近的日志：

```sh
9pm logs my-app                # recent container logs + the failure reason, if any
9pm logs my-app --lines 50     # last N lines
9pm logs my-app --json         # machine-readable
```

`9pm logs` 报告最新的容器部署的状态、运行状况、失败原因，以及在部署失败时捕获的启动输出。它是只读的，不影响部署。

删除一个应用、它的托管数据库、托管容器应用和保留的映像：

```sh
9pm delete my-app --confirm my-app
```

应用程序的地址也随之改变：在相同的标签下再次创建应用程序会给它一个新的地址，因此打印的链接和QR码不起作用。 `9pm delete` 在删除任何内容之前打印此警告。

`9pm delete` 还打印 `Its address stops serving the app within about a minute.` 当删除的方式被测量时：一个静态或Worker应用程序，或一个容器应用程序（包括一个卷，始终打开或自定义CPU/内存），没有自定义域。不是每个容器应用都符合条件，所以要按行而不是按应用类型。当该行缺失时（带有自定义域的应用程序，某些容器应用程序或报告错误的清理步骤），无法测量地址保持服务的时间，因此请自己检查地址。

## 访问模式

应用程序默认是公开的。

更改应用程序的访问模式需要 `--switch-mode`． 如果没有它，命令不会改变任何东西，只会打印修改后的结果（谁失去了访问权限，应用程序的自定义域发生了什么）以及重新运行的命令。服务令牌模式锁定每个人，并删除应用程序的自定义域；让它重新设置它们并发布新的DNS记录。在已经处于服务令牌模式的应用上创建另一个服务令牌不需要标记。

一次性密码与电子邮件/域名allowlist：

```sh
9pm access allow email my-app dev@example.com
9pm access allow domain my-app example.com
9pm access otp my-app --switch-mode
9pm access revoke email my-app dev@example.com
9pm access revoke domain my-app example.com
```

身份提供者访问：

```sh
9pm access idp my-app --provider google --switch-mode
```

机访问:

```sh
9pm access service create my-app --name backend --switch-mode
```

回归公众：

```sh
9pm access public my-app --switch-mode
```

为服务器端allowlist管理创建一个应用范围的运行时令牌：

```sh
9pm access token create my-app --name production-app-server
```

使用 `9pm_app_...` 仅来自服务器端代码的运行时令牌。他们可以列出、添加和删除一个应用程序的电子邮件/域名授权。他们不能部署、创建数据库、创建API密钥或管理另一个应用程序。 返回的服务令牌秘密 `access service create` 也是服务器端的秘密。

## 定制域

将您拥有的域连接到应用程序：

```sh
9pm domains add my-app www.example.com
```

这将打印要在DNS提供商处发布的DNS记录，其中包含与您的域名相关的名称 域(`www`， `_acme-challenge.www`)以及DNS现在显示的内容。当一个TXT值 缺失，将其添加为自己的TXT记录；该名称上的其他TXT值可以保留。的根源 你的领域(`@`)不能包含CNAME，因此根域显示为 `ALIAS / ANAME` 记录当 您的DNS主机不是CLI识别的主机（否则是被识别的主机自己的名称）：将其添加为 别名或名称（或您的提供者扁平化的CNAME）。正确的ALIAS用地址回答，其中 不能从外部比较，因此行遵循平台自己的路由检查。然后:

```sh
9pm domains wait my-app www.example.com
```

`wait` 出口 `0` 一旦域激活， `10` 如果在你有事要做的时候超时了(a) 记录丢失或无法检查，或者CAA记录阻止了证书，即使每个 找到记录)， `11` 如果它超时了，所有的记录都被检查过了，没有任何东西留给你 （站台还在完工，再等一次）， `20` 如果域失败或过期，则 `1` 在一个 使用、登录或API错误。自0.74.0起，CAA块退出 `10`;旧版本退出 `11`． 因为0.77.0是一个裸域，它的DNS主机不能指向根 域名的主机名（GoDaddy, Route 53， IONOS, Wix） `wait` 立即停止 `10`:其 `next` 是 `use_www` 与 `www` 要添加的主机名，因为根目录下没有记录可以完成它。 `9pm domains status <app> <hostname> --json` 打印 `{hostname, app, state, reason, next, routing, tls, provider, providerId, nameservers, zone, records, advisories, error, expiresAt, checkedAt}`,在那里 `provider` 是 DNS主机（域名服务器指向的地方，不一定是购买域名的地方）； `reason` 说为什么 （`reason.providerMessage` 当它报告任何时，带有提供者自己的话 `source` 说明它们是否是证书颁发机构的)， `next` 说下一步该谁行动，该怎么做 `state` 是 `live`， `ready_to_switch`， `waiting_for_dns`， `dns_unverified` （路由是活动的，但无法检查记录）， `issuing_certificate`， `points_elsewhere`， `failed` 或 `expired`． 每条记录的 `ok` 是 `null` 当支票不能兑现时 说，它。 `check` 说为什么(`not_checked`,或 `apex_addresses`）. 找到其值的记录 在名称处键入两次域(`_acme-challenge.www.example.com.example.com`) `check: "doubled"` 和 `doubledAt`：只输入显示的短名称。从0.79.0开始，针对服务器 发送它们的：由DNS主机的通配符记录(`*.example.com`),而 比它自己的一个还要多 `check: "wildcard"` 和 `wildcard`，该行说要在那里添加一条记录 名称（通配符可以保留；TXT值总是在已经存在的值旁边添加）； `resolvers` 列出每个公共解析器在两个被请求时的回答，以及一个显示 期望值和另一个不一样，记录是 `check: "resolvers_disagree"` 与 `ok: null`： 这两个缓存都不能证明哪个答案是当前的，因此请在DNS主机上确认记录并再次检查。 不匹配的记录生效 `ttlSeconds`，该答案可以缓存多长时间。在 `9pm domains check` 输出（0.95.0或更高版本）；服务器只直接读取一个主机 域名重新检查，所以 `list`， `status` 和 `wait` 永远不要携带它)，它的DNS主机是 GoDaddy, Namecheap，谷歌云DNS或NS1可以携带 `authoritative`：当被直接询问时，主机自己的域名服务器是如何回答的 （`outcome: "answered"` 与 `nameserver`， `current` 和 `matches`,或 `outcome: "unverified"` 当 那次读取失败了)。然后该行显示“您的DNS主机发布…”或“您的DNS主机：无法发布…” 直接验证”;读取失败并不意味着记录丢失。这只能解释为什么会这样： `ok`， `check` 无论如何，州政府都要维持公共解决方案的裁决。其他东道主则没有这样的待遇 字段。一个根 在路由待定时回答地址要求您确认ALIAS或ANAME目标； 因为停车页也有地址。对于找到的每条记录，文本命名为 平台的下一个自动检查从 `next.nextCheckAt`。 `advisories` 列出提示 主机名可能是一个错别字，例如域名不在DNS中；两种方式都可以添加域。 自0.78.0以来，每个记录也携带 `typeAtProvider`， `nameAtProvider` （`""` 意思是离开东道主 字段为空)和 `valueAtProvider`：被认可的DNS主机编辑需要的记录。 `typeAtProvider` 是 `null` 对于主机不能保存的根记录（GoDaddy, Route 53， IONOS, Wix）； 然后文本输出建议连接 `www` 代替。 `list`， `status` 和 `wait` 只有读; `add`， `check`， `restart`， `remove` 和 `move` 需要配置应用程序的权限。

从0.89.0开始，针对发送它们的服务器，有两种状态涵盖在主机之间移动域。 `ready_to_switch`：路由和证书处于活动状态，因此平台可以为该域服务； 但是它的路由记录仍然会指向另一个主机，访问者仍然会到达那个主机。文本 命名记录和要将其更改为的值， `next` 是 `replace_record`, `wait` 保持 等待，直到 `live`。 `points_elsewhere`域名是活的，它的DNS现在指向另一个 因此提供程序停止了对它的路由。 `next` 是 `remove`：删除这里的域名一旦访问者 到达新的主机。如果这是一个错误，把记录改回来，然后跑 `9pm domains check`。 `wait` 立即停止 `10` 在这个状态下。提供程序将从其配置中删除该域 移动7天。这不会影响您的域名注册。

从0.101.0开始，针对发送它的服务器， `waiting_for_reconnection` (“DNS指向晚上9点； 等待重新连接”)是返回的方式：路由记录再次指向这里，但是提供者 移动后主机名仍然断开连接。您的DNS中没有任何内容需要更改；文本 打印 `check` 首先,然后 `wait`，它在此状态下保持轮询（超时） `11`）， 然后 `restart` 作为保持断开连接的域的回退，不是必需的步骤。一个 之前的服务器调用相同的域 `failed` 与 `reason.code` `moved_needs_restart`； 这个CLI将其读取为 `waiting_for_reconnection` 当找到记录时。当唱片可以 未被确认，国家就留下 `failed` 与 `moved_needs_restart` 和 `next.action` `recheck`。 这不会显示您是否想要回域：如果您想重新连接它，请确保 在这里记录点并重新检查；如果您故意将其移动到另一个主机，请将其删除一次 访客到达了新的主人。 `wait` 同时也保持轮询（超时） 与 `10`）. 被阻止或删除的主机名永远不会得到。任何一个州的路由记录都包含 `elsewhere`即它所指向的宿主。平台报告 只有强有力的证据才能证明这一点：两个公开的解析者都同意这个名字自己的记录， 通过它的整个CNAME链，到您的区域和平台之外的主机。根回答 使用地址、通配符的答案、不同意的解析器或无法运行leave的检查 在它所拥有的状态下的领域(`live`,或 `failed` 首先，提供者停止了路由)。一个年长的 CLI按原样打印这些状态名。

`9pm domains remove` 只打印API表示域使用的记录，每条只删除一次 它的值是不变的：一个名称现在持有不同的值(域指向新的地方，或者 另一个服务的证书检查使用 `_acme-challenge`)不是我们的，所以离开它吧。针对服务器 它不发送这样的列表，它根本不打印删除通知。当移除还在完成时 上游（API回答） `202` 与 `releasing: true`)，它是这样说的，没有指定要删除的记录，并且 打印 `9pm domains list` 命令：一旦域名不再列出，该域名已停止服务 从晚上9点。这样的域显示为 `removing` 在 `list` 和 `status` （`"removing": true` 在 `--json`）， 和 `wait` 当它退出时 `20`． 因为0.80.0。

从0.86.0开始，从 `remove` 或 `9pm delete`)还说，搬迁后， 访问者可能会看到TLS或路由错误，而域名的DNS仍然指向晚上9点。它没有命名 记录并添加自己的删除建议：可以删除的只是打印的清理列表 在它上面，只有当它的值仍然匹配时，才会显示每条记录。一个仍在完成的移除没有这样的线条， 因为它被告知要保留它的记录。没有发送清理列表的服务器仍然获得它。

从0.87.0开始，该行后面跟着舞台排练（#2182）为a演示的顺序 移动到另一个主机：将DNS指向新主机，等待DNS TTL通过，然后删除域 从晚上9点。当缓存更新时，一些访问者可能仍然会到达晚上9点，或者短暂地看到新的错误 一旦DNS指向别处，9pm显示域指向别处(在0.89.0之前，或 针对较旧的服务器，如失败)，这是预期的。它连接了 custom-domain guide的“将域名移出9点”部分放在站点的控制平面旁边吧 和舞台指导谈过了 `--api-url https://api-staging.9pm.ai`）. 迁移到你自己的Cloudflare DNS区域没有预演，所以没有打印订单；指南上说要先联系客服。

0.84.0以来, `9pm domains removed [--owner <organisation>]` 列出可以删除的DNS记录 在背景中完成移除后 `remove` 这个回答 `releasing`的定义域 一个被删除的应用，后来被平台完成了。这是相同的列表 `remove` 完成后打印 本身，在相同的规则下（仅在仍然显示值的情况下删除记录），以及 在未完成的删除或删除后打印提示 `9pm delete` 指着它，用 `--owner` 和 `--api-url` 保存。删除完成后的30天内会被列出，只针对拥有的账户 一旦主机名再次添加到任何地方，服务器就不会再检查 在运行该命令时为其提供的证书提供程序，并且如果没有它无法检查的域命名 其记录，用命令再问一遍。服务器每页检查10个域；这个 该命令最多可读取20页，如果还有更多，则会显示。 `--hostname <hostname>` 问一个 域。 `--json` 打印API的答案及其页面合并(`next` 每一页是否为空 是读)。对于没有路由的服务器，它说它无法列出任何路由，不打印任何记录并退出 `1`。

0.83.0以来, `9pm domains cleanup <app> <hostname>` 列出了安装TXT记录9pm发布的 活动域和不再需要的域，如较早的 `_acme-challenge` 值或 `_cf-custom-hostname` 拥有权纪录(`--json` 输出API的答案)。每一项只能删除 虽然它仍然具有显示的价值；该名称下的另一个值不是我们的。检查列表 在运行命令时，针对证书提供程序：提供程序仍然要求的值 不在其中，非活动的域不会列出任何内容，并且如果无法读取提供程序，或 域在被检查时更改，命令失败并且不列出任何内容；再运行一次。只有API发出的值是候选值，而不是从public中读取的任何值 DNS。 `9pm domains status` 在活动域上打印命令。 `9pm domains remove` 列出这些值 使用域的其余记录，因为一旦删除了域，就不需要它们了。 后 `9pm domains restart`，它表示不再计数的值的措辞方式相同。对一个 没有路由的服务器， `cleanup` 表示无法列出任何选项并退出 `1`． 之前替换的值。 服务器保存它们不能被列出。

`9pm domains move <hostname> --to <app>` 将域名移动到同一帐户的另一个应用程序。它使 它的证书和DNS记录已经发布，所以没有再次验证。没有一个 源代码应用程序的CLI查找它的帐户；说出来(`9pm domains move <app> <hostname> --to <app>`)跳过它。每次拒绝都会打印出处理方法：找不到域名或应用程序； 目的地是在它的自定义域上限，一个域名的删除仍在完成，该域名 在服务令牌应用程序下断开连接或从未提供(删除它并将其添加到 其他应用程序)，或者目的地在另一个帐户。 `remove --json` 和 `move --json` 打印 API的答案来了。因为0.80.0。

每一个 `9pm deploy` 列表下列出应用程序的自定义域 `Deployed` 线: `Also serving at https://<domain>` 对于一个活着的人来说，对于任何其他的人来说，它的状态和 `9pm domains status` 命令运行。如果无法在几秒钟内读取域，则部署将在一秒钟内读取 行相反;部署本身永远不会受到它的阻碍。 `9pm delete` 命名自定义域 它删除了，并且从0.80.0开始，API表示每个人使用的记录(在相同的 value-unchanged规则);一个仍在释放的域名被报道为这样，没有记录可以删除， 之后也没有人可以列出。

## 命令

```sh
9pm --version
9pm deploy [directory] --name <name> [--slug <slug>] [--spa | --no-spa] [--with-db]
9pm deploy [directory] --check [--runtime worker --entry <path> (--assets <dir> | --no-assets)]
9pm deploy [directory] --runtime container --port 8080 [--health-path /health] [--region auto] [--with-db]
9pm signup
9pm login [--fresh]
9pm logout [--api-url <url>] [--local]
9pm doctor [--json]
9pm whoami
9pm apps [--json]
9pm latest [--json]
9pm files list [--project <site>]
9pm files put <local-path> [--path <remote-path>] [--project <site>]
9pm files get <file-id> [--output <path>] [--project <site>]
9pm files share <file-id> [--expires 24h] [--public] [--project <site>]
9pm files delete <file-id> [--project <site>]
9pm deploy [directory] --runtime worker --entry <path> (--assets <dir> | --no-assets) [--spa | --no-spa] [--with-db]
9pm delete <site> --confirm <slug>
9pm domains list [<app>] [--owner <organisation>] [--json]
9pm domains add <app> <hostname> [--json]
9pm domains status <app> <hostname> [--json]
9pm domains check <app> <hostname> [--json]
9pm domains wait <app> <hostname> [--timeout 30m] [--interval 20s] [--json]
9pm domains restart <app> <hostname>          # after a certificate failed, or as a fallback for a moved domain that stays disconnected; record values may change
9pm domains remove <app> <hostname> --confirm <hostname> [--json]
9pm domains move [<app>] <hostname> --to <app> [--json]
9pm domains removed [--hostname <hostname>] [--owner <organisation>] [--json]   # records to delete after a removal that finished in the background
9pm access show <site>
9pm access public <site> [--switch-mode]
9pm access otp <site> [--switch-mode]
9pm access idp <site> [--provider google|github|entra] [--switch-mode]
9pm access allow email <site> <email>
9pm access allow domain <site> <domain>
9pm access revoke email <site> <email>
9pm access revoke domain <site> <domain>
9pm access service create <site> [--name <name>] [--duration 8760h] [--switch-mode]
9pm access service revoke <site> <service-token-id>
9pm access token create <site> [--name <name>]
9pm access token revoke <site> <token-id>
```

选项:

-   `--api-url <url>` 覆盖 `NINEPM_API_URL`
-   `--token <key>` 覆盖 `NINEPM_API_KEY`
-   `--allow-file-credential-store` 的明文回退存储 `login` 和 `signup` 当本地受保护存储不可用时
-   `--name <name>` 设置应用程序的显示名称
-   `--slug <slug>` 设置url安全的应用程序选项
-   `--with-db` 请求应用程序的托管存储
-   `--with-auth` 给应用程序晚上9点管理的最终用户登录（电子邮件一次性代码）和暗示 `--with-db`． 一旦启用，它就会在以后的每次应用部署中保持打开状态，不管有没有这个标志；它无法关闭
-   `--database-name <name>` 自定义请求的数据库名称
-   `--binding <name>` 自定义数据库绑定名称
-   `--environment <name>` 设置部署环境元数据
-   `--runtime <static|worker|container>` 选择静态资产托管、应用程序拥有的Worker代码或本地Docker容器部署
-   `--entry <path>` 选择Worker运行时服务器条目文件
-   `--assets <dir>` 只将工作部署的那个目录设置为公共目录（为以后的部署保留）
-   `--no-assets` 不使工作部署的文件公开（为以后的部署保留）
-   `--spa` 服务 `index.html` 对于每个没有文件的路径，对于单页应用程序（记住以后部署）
-   `--no-spa` 对于没有文件的路径返回404，其中包含部署文件 `404.html` 当礼物;新应用程序的默认值（为以后部署保留）
-   `--port <port>` 选择容器应用公开的HTTP端口
-   `--health-path <path>` 可选让晚上9点。在将容器标记为健康之前，请检查其运行状况
-   `--region <region>` 可选地选择与提供程序无关的容器放置
-   `--cpus <n>` 和 `--memory <size>` （`512m`， `2048`， `4g`)大小一个容器应用程序
-   `--cpu-kind <shared|performance>` 选择容器的CPU类： `shared` （默认）爆发并在持续负载下进行节流； `performance` 是专用核心，在计划中包括它吗
-   `--project <site>` 将文件命令扩展到应用程序
-   `--path <remote-path>` 将文件存储在特定路径
-   `--output <path>` 将下载的文件写入磁盘
-   `--expires <duration>` 设定股票挂钩的到期日，上限为7天
-   `--public` 任何人都可以下载共享链接，不需要登录（共享链接是所有者独有的）
-   `--confirm <slug>` 确认删除应用程序时，需要点击“slug”
-   `--provider <google|github|entra>` 选择已配置的标识提供程序
-   `--duration <duration>` 设置服务令牌持续时间

访问命令选项：

-   `--api-url <url>` 覆盖 `NINEPM_API_URL`
-   `--token <key>` 覆盖 `NINEPM_API_KEY`
-   `--name <name>` 命名一个应用范围的运行时令牌
-   `--expires-at <iso-date>` 可选地使应用范围的运行时令牌过期

### 安全的api密钥轮换

使用完全访问权限的个人登录。 `9pm api-key rotate <key-id>` 创建一个链接 替换并打印它的标记一次。安全地存储它并切换每个消费者， 然后运行 `9pm api-key rotation complete <rotation-id> --yes` 撤销原稿 `rotation show` 检查截止日期; `rotation cancel` 撤销替换。 所有的支持 `--json`． 7天是最大的重叠，进一步限制了 原固定期限。完全遗忘使替换失效并离开 原来的现有期限不变。

普通的 `api-key revoke` 如果替换品幸存，则发出警告。为了控制事故， `9pm api-key revoke <original-key-id> --both --rotation <rotation-id>` 撤销完全 那对，即使在完成之后。独立制作的证书和后来的轮岗 保持独立：查看在妥协过程中创建的所有密钥。不支持的服务器 明显失败，没有薄荷/撤销的退路。不要在报告或日志中放置令牌。

## 常见问题

### ninepm 是什么？

CLI用于将构建的应用程序部署到9pm\.ai。

### 如何安装 ninepm？

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

### ninepm 支持 TypeScript 吗？

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

### ninepm 支持 ESM 还是 CommonJS？

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

### ninepm 需要什么版本的 Node\.js？

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

### ninepm 可以商用吗？

ninepm 使用 SEE LICENSE IN LICENSE\.md 许可。许可条款写在包内的独立文件中，请阅读该文件确认可否商用。以上为概括，不构成法律意见，请以许可原文为准。

### ninepm 还在维护吗？

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

