ninepm

中文文档
0.109.0发布于 2026/11/04SEE LICENSE IN LICENSE.mdTypeScriptES Module

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

中文使用文档
文档目录11 节
  1. 安装
  2. 配置
  3. 库存
  4. 版本控制
  5. 部署
  6. 一个应用的地址保持不变多久
  7. 不存在的页面
  8. 访问模式
  9. 定制域
  10. 命令
  11. 安全的api密钥轮换

9点。ai CLI

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

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

安装

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。

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:

9pm apps
9pm apps --json

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

版本控制

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

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

升级:

npm i -g ninepm@latest

部署

部署一个静态目录:

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。
9pm deploy ./dist --name my-spa --spa

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

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

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

使用托管SQL数据库部署:

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

将可选的简短描述附加到部署(显示在仪表板中的版本旁边;最多200个字符):

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。

存储和共享工作文件:

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运行时应用:

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构建部署一个容器应用:

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。

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

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 报告最新的容器部署的状态、运行状况、失败原因,以及在部署失败时捕获的启动输出。它是只读的,不影响部署。

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

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:

9pm access allow email my-app [email protected]
9pm access allow domain my-app example.com
9pm access otp my-app --switch-mode
9pm access revoke email my-app [email protected]
9pm access revoke domain my-app example.com

身份提供者访问:

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

机访问:

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

回归公众:

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

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

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

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

定制域

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

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用地址回答,其中 不能从外部比较,因此行遵循平台自己的路由检查。然后:

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规则);一个仍在释放的域名被报道为这样,没有记录可以删除, 之后也没有人可以列出。

命令

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 共发布 41 个版本,首次发布于 2026/07/03;过去 12 个月发布了 41 个版本。

版本发布日期距今
0.109.0latest2026/11/04今天
0.105.02026/10/306 天前
0.101.02026/10/287 天前
0.96.02026/10/278 天前
0.92.02026/10/2312 天前
0.87.02026/10/2213 天前

关于 ninepm 的常见问题

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 和提交记录判断。