# @appforge-ci/cli 中文文档

规范地址：https://npmcn.com/package/%40appforge-ci/cli/

版本：0\.3\.29
npm 元数据更新时间：2026-10-24T09:14:19.539Z
中文译文更新时间：2026-11-06T22:49:52.497Z
软件包许可：MIT

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

原始 npm 页面：https://www.npmjs.com/package/%40appforge-ci/cli
原文对照：https://npmcn.com/package/%40appforge-ci/cli/?lang=original

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

- 包体积（解压后）：459 kB，107 个文件
- 模块格式：ES Module
- TypeScript 类型：未声明
- 运行依赖：4 个
- 首次发布：2026-09-23T07:59:54.961Z
- 最新版本发布：2026-10-24T09:14:19.362Z
- 近 30 天下载量：2206（2026-10-07 至 2026-11-05，npm 官方下载统计）
- 已发布版本数：36（近 12 个月 36 个）

## 中文简介

`appforge` ——客户端的CLI:在用户端注册/登录,管理应用程序,触发/监视构建,购买构建-token上架,启动浏览器设备测试会话. 没有舰队命令——这是单独的工具, `appforge-admin` (单位:千美元)`packages/admin-cli`),为平板

## 安装

```sh
npm install @appforge-ci/cli
```

也可以使用：`pnpm add @appforge-ci/cli`、`yarn add @appforge-ci/cli`、`bun add @appforge-ci/cli`

## README

# @appforge-ci/cli (英语)

`appforge` - 客户的CLI:注册/登录,管理应用程序, 触发/ 监视构建, 购买已建入的顶上, 启动内浏览器 设备测试会话。 没有舰队命令——这是单独的工具, `appforge-admin` (单位:千美元)`packages/admin-cli`),仅供平台运营商使用.

## 安装

**在已经复制的机器上:**

```bash
pnpm install                        # once, from the repo root
pnpm --filter @appforge-ci/cli build
cd packages/cli && npm link         # symlinks `appforge` onto PATH
```

**从 npm (不需要克隆) :**

```bash
npm install -g @appforge-ci/cli          # or run once: npx @appforge-ci/cli login --web --api-url https://api.appforge.skoor.ee
appforge login --web --api-url https://api.appforge.skoor.ee
```

出版人: `.github/workflows/publish.yml` 每个版本标签,连同 `@appforge-ci/core`。沥青球包含编译 `dist/` 仅:没有测试,没有测试助手,没有来源.

## 使用量

```bash
appforge signup --email you@example.com --org "My Org"   # or: appforge login --email you@example.com
appforge logout                             # remove the login from THIS machine (the file and leftover copies) AND revoke its token on the server — see "Logging out"
appforge login --email you@example.com --totp-code 123456   # if 2FA is enabled (--recovery-code also works)
appforge login --email you@example.com --email-code         # no password: emails you a 6-digit code, then asks for it
appforge login --web                        # sign in (or sign up) in your browser, like `aws sso login`: no password typed here; prints the claude mcp add command at the end
appforge apps create --name demo --platform flutter --repo-url https://github.com/you/app.git
appforge apps list
appforge apps update <appId> [--name] [--repo-url] [--default-branch]   # fix a stale field without recreating the app
appforge apps webhook-secret <appId>        # the secret GitHub's webhook "Secret" field needs
appforge apps delete <appId>                # permanently delete an app and its builds/OTA history
appforge apps secrets set <appId> --name KEYSTORE_PASSWORD   # --value omitted -> prompted, echo off (never in shell history); injected as $KEYSTORE_PASSWORD on every build for this app
appforge apps secrets list <appId>          # names only, never values
appforge apps secrets unset <appId> --name KEYSTORE_PASSWORD
appforge fleet-secrets set DEVICE_STREAM_PUBLIC_KEY "$(base64 < device-stream-public.der | tr -d '\n')"   # a PUBLIC key; control-plane secrets are refused
appforge fleet-secrets list                  # names only, never values
appforge fleet-secrets unset DEVICE_STREAM_PUBLIC_KEY_PREVIOUS
appforge orgs rename --name "New Org Name"  # fix a typo'd/stale org name (e.g. a placeholder from signup)
appforge orgs set-build-webhook --url https://example.com/hook  # POST build id/status/appId/costTokens/artifacts on every build's completion
appforge orgs set-build-webhook --clear     # turn build-status notifications back off
appforge build trigger --app-id <appId>
appforge build trigger --app-id <appId> --remote-access   # run in a VM you can log in to (docs/remote-access-user.md)
appforge builds ssh <buildId>          # shell in that VM while the build runs and for 10 minutes after; ssh options go after --
appforge builds vnc <buildId>          # screen sharing into it (opens macOS Screen Sharing on a local port)
appforge builds remote-access <buildId>  # is the VM ready, and who opened sessions
appforge builds simulator <buildId>    # a succeeded build's iOS Simulator app (*.app.zip) on a Mac VM, shown by macOS Screen Sharing (100 tokens; docs/remote-access-user.md)
appforge apps test-in-simulator <appId>   # the same for the app's newest succeeded build that has a *.app.zip
appforge build list --app-id <appId>
appforge build logs <buildId> --follow
appforge build artifact <buildId>
appforge build cancel <buildId>
appforge build explain <buildId>       # AI explanation for a failed build (needs ANTHROPIC_API_KEY on the deployment)
appforge build analyze-smoke-test <buildId>  # re-run AI analysis of the build's smoke-test screenshots
appforge build test <buildId>          # where to test a succeeded build in the browser (the dashboard page: Android device test, or iOS Simulator)
appforge init                          # draft an appforge.yaml from what's actually in the current repo
appforge billing balance
appforge billing packs
appforge billing topup --pack starter          # via LHV Paytech, see docs/payments-lhv.md
appforge billing ledger                        # every balance change (top-ups, charges, refunds), newest first
appforge billing usage                         # billing mode + this period's accrued usage, on postpaid
appforge billing setup-card                    # save a card — required before switching to postpaid
appforge billing mode <prepaid|postpaid-monthly>
appforge billing invoices                      # monthly invoices (postpaid billing only)
appforge ota channels --app <appId>         # list channels and each one's active release
appforge ota releases --app <appId> [--channel production]
appforge ota promote <buildId> --app <appId> [--channel production] [--rollout 25] [--mandatory]
appforge ota set-rollout <releaseId> --app <appId> --rollout 50   # progress an existing release's rollout in place
appforge ota app-key --app <appId>          # generate/rotate the manifest key a shipped app embeds
appforge ota activate <releaseId> --app <appId> --channel production  # jump directly to a specific release
appforge ota activate --app <appId> --channel production --clear      # deactivate the channel instead
appforge ota rollback --app <appId> --channel production               # step back exactly one release
appforge tokens list [--limit n] [--offset n]  # the org's API tokens, newest first, 50 a page — id, label, created/last-used (never the token value)
appforge tokens revoke <tokenId>            # permanently revoke one — 'appforge login' again mints a fresh one
appforge vpn status [--json]                # the org's site-to-site VPN tunnel (any member)
appforge vpn create --name hq --endpoint vpn.example.com:51820 --gateway-key <base64> --lan 10.20.0.0/16 [--dns 10.20.0.2 --domain corp.example.com] [--tunnel-cidr 169.254.200.0/30]
appforge vpn peer-config                    # re-show the [Peer] block for your gateway (prints a secret; admin, audited)
appforge vpn rotate-keys [--yes]            # new AppForge keys; tunnel returns to pending (a disabled tunnel stays disabled) until you update your gateway
appforge vpn disable [--yes] | enable       # disable cancels + refunds queued VPN builds
appforge vpn delete [--yes]
appforge vpn events [--json]                # newest first
appforge vpn test [--json]                 # start a build-free handshake test of the gateway (owner/admin; nothing charged; once per 5 minutes)
appforge vpn test --status [--json]        # the latest test's verdict (any member); exits 0 only on handshake_ok
appforge apps update <appId> --vpn          # opt an app in (--no-vpn to opt out; org owner/admin)
```

### 正在注销

`login`编号 :`signup` 存储长寿 `afk_` API 令牌输入 `~/.appforge/config.json`。在一个为租户建造的Mac上,文件可以读取 由每个标准级的构建,它作为同一个用户运行,所以保持登录在自己的机器上并运行 `appforge logout` {\\fn黑体\\fs22\\bord1\\shad0\\3ahbe\\4ah00\\fscx67\\fscy66\\2chffffff\\3ch808080}只要你一回来 用共享或构建 Mac 完成 :

-   它删除 `config.json` 和任何 `config.json.*` 复制到旁边( 被杀死的保存的临时文件, a) `.bak`印出它所消除的, 留下所有的东西 `~/.appforge` 独自一人(VPN州也住在那里), A 类 `config.json` 即同义链接是未链接的,而不是跟随的:它指向的文件的输出名称,它保留.
-   这个 **也取消服务器上的令牌** (单位:千美元)`DELETE /auth/token`,第952期: 信使马上停止工作,所以已经有人复制了 读作已死。 文件首先被读取,然后在任何网络呼叫之前被取出,所以即使API无法访问,Mac也是干净的;每 已保存副本的令牌被撤销, 每一个都使用它旁边保存的 API URL 。 如果撤销失败( 离线, 超过路径的 API) `logout` 仍然删除登录, 退出 0, 说它不能撤销, 并打印手动后续: 从信任的机器, `appforge tokens list` (标志是标记) `cli:<email>`以所创造的时间配他 `appforge tokens revoke <tokenId>`,以及 `appforge login` 仅仅在那里。 用手删除文件不会撤销任何内容。 信使从来印出. 若为 `logout` 运行于 长生的CI标志是保存的登录,该标志是被撤销的:为输油管用薄荷新的.
-   `login` 财务报告和审定财务报表 `signup` 当构建时, 当您登录的账户运行时, 打印一个警告( 代理服务器的配置或 LaunchAgent plist 位于您的 家里,或靴子时间的代理 运行像你一样; 一个笔记本电脑没有代理 得到什么, 也没有另一个账户 在Mac的代理 运行 作为别人. `appforge-agent doctor` 失败( e)`cli-credentials-off-build-mac`),而登录则存储在有代理的Mac上. 没有什么是拒绝的.
-   `appforge tokens list` 首先显示最新50个符号。 在Mac上留下的旧登录符是最早的,所以如果不在 列表中,继续 `--offset 50`, (中文(简体) ), `--offset 100`,(或 `--limit 200`) 之前 `tokens revoke`。 。 。 .

见 `docs/security.md`,"一个CLI登录 从不停留在建设Mac上". 标志性自取(问题为#952)由单位和路由测试覆盖;尚未与所部署的控制平面(UNVERIFIED)对接,直到记录到日期运行.

### 现场对现场VPN

您描述您自己的WireGuard网关; AppForge的Mac拨号用于 构建选择的应用程序. `vpn create` 打印 a `[Peer]` 块来粘贴 输入您的网关; 旋转密钥或更改后再次更新网关 局域网/隧道范围。 它包含一个秘密(预共享密钥)——处理它 就像密码,只有 `create`, (中文(简体) ), `peer-config` 财务报告和审定财务报表 `rotate-keys` 打印出来. 所有更改都需要 Ong 拥有者/ admin; 任何成员都能读取 `status`编号 :`events`。 。 。 . `vpn test` 检查您的网关是否接受握手而不建立任何东西: 将隧道的密钥释放给一台制造机器进行测试(见 `docs/vpn.md`"试验地道", 财务报告和审定财务报表 `vpn test --status` 打印判决和判决运行时. 限制:忽略代理服务器设置的工具(raw sockets, UDP, ICMP, `xcodebuild`,模拟器)不使用地道;SSH git远程 (单位:千美元)`ssh://user@host/path` 或者说 `user@host:path`)去通过它,当你针 您的服务器主机密钥( e)`vpn ssh-hosts set`)并安装应用程序的部署 键`apps deploy-key show`在赤裸裸的时候 `ssh` 在构建脚本中不是 已路由; 您的网关必须在其端口接受进入的 UDP; 状态 变成 `ready` 在第一次成功VPN建设之后(`vpn test` 检查 单独握手; 建筑是端对端检查; 建筑来自隧道的 AppForge-side 30 地址,所以允许列出它或伪装.

`--api-url` (默认) `http://localhost:8787`,或设置 `APPFORGE_API_URL`(中文(简体) ) 只需要传下去 `login`编号 :`signup` - 在那之后,它保存给 `~/.appforge/config.json` 并重新使用。 见根 `README.md`快点 启动完整的本地- dev 流量 `docs/self-hosting.md` 指针 这是在真正的部署.

`login` 如果账户有 2FA 代码, 则以交互方式提示 已启用,但没有 `--totp-code` 也没有 `--recovery-code` 被通过——见: `docs/security.md`'"2FA (TOTP)"注释.

`login --email-code` 使用一次性的密码,而不是密码(已核实的电子邮件地址和 平台管理员; 代码在即时打出,从未以旗子的方式通过,10分钟后失效. 双因素的工作方式与 密码登录。 见 `docs/security.md`"电子邮件一次性码签入".

## 常见问题

### @appforge-ci/cli 是什么？

appforge ——客户端的CLI:在用户端注册/登录,管理应用程序,触发/监视构建,购买构建-token上架,启动浏览器设备测试会话\. 没有舰队命令——这是单独的工具, appforge-admin \(单位:千美元\)packages/admin-cli\),为平板

### 如何安装 @appforge-ci/cli？

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

### @appforge-ci/cli 支持 TypeScript 吗？

该包的 package\.json 没有声明类型入口。需要类型提示时，可以在 npm 上查找社区维护的 @types/appforge-ci\_\_cli 是否存在。

### @appforge-ci/cli 支持 ESM 还是 CommonJS？

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

### @appforge-ci/cli 可以商用吗？

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

### @appforge-ci/cli 的下载量有多少？

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

### @appforge-ci/cli 还在维护吗？

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

