# @adep/cli 中文文档

规范地址：https://npmcn.com/package/%40adep/cli/

版本：0\.4\.11
npm 元数据更新时间：2026-11-02T19:42:02.772Z
中文译文更新时间：2026-11-07T00:22:40.708Z
软件包许可：MIT

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

原始 npm 页面：https://www.npmjs.com/package/%40adep/cli
原文对照：https://npmcn.com/package/%40adep/cli/?lang=original
项目主页：https://adep.top/
源码仓库：https://gitcode.com/yunqiang_wu/ai-yunke

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

- 包体积（解压后）：2.2 MB，53 个文件
- 模块格式：ES Module
- TypeScript 类型：未声明
- 运行依赖：9 个
- 首次发布：2026-09-03T01:08:52.747Z
- 最新版本发布：2026-11-02T19:41:54.381Z
- 近 30 天下载量：2114（2026-10-05 至 2026-11-03，npm 官方下载统计）
- 已发布版本数：39（近 12 个月 39 个）

## 中文简介

`adep` 命令行工具包位：登录 / 初始化 / 本地调试 / 部署 / 数据库维护 / 云存储 / 静态托管 / 微前端组件（widget），实现见任务单 CLI-001 ~ CLI-003 与 FE-002；子路径 `@adep/cli/vite` 提供云函数 vite 插件（CLI-014）

## 安装

```sh
npm install @adep/cli
```

也可以使用：`pnpm add @adep/cli`、`yarn add @adep/cli`、`bun add @adep/cli`

## README

# adep — AgentDeploy CLI

> 面向终端开发者的 AgentDeploy 命令行工具：**登录 / 初始化 / 本地调试 / 部署 / 数据库维护 / 云存储 / 静态托管 / 全栈工程（functions/ + web/ 前端）** 一站式闭环。

`adep` 让你在一个项目目录里完成从**脚手架 → 本地调试 → 部署上线 → 数据与资源运维**的完整流程。它复用平台运行时内核（`@adep/runtime`），本地与线上的执行语义一致，离线、不装 Docker 也能开发。

  

**[安装](https://npmcn.com/package/%40adep/cli/#readme-%E5%AE%89%E8%A3%85)** · **[快速开始](https://npmcn.com/package/%40adep/cli/#readme-%E5%BF%AB%E9%80%9F%E5%BC%80%E5%A7%8B)** · **[子命令](https://npmcn.com/package/%40adep/cli/#readme-%E5%AD%90%E5%91%BD%E4%BB%A4)** · **[配置](https://npmcn.com/package/%40adep/cli/#readme-%E9%85%8D%E7%BD%AE)** · **[FAQ](https://npmcn.com/package/%40adep/cli/#readme-faq)**

* * *

## 目录

1.  [安装](https://npmcn.com/package/%40adep/cli/#readme-%E5%AE%89%E8%A3%85)
    
2.  [快速开始](https://npmcn.com/package/%40adep/cli/#readme-%E5%BF%AB%E9%80%9F%E5%BC%80%E5%A7%8B)
    
3.  [子命令](https://npmcn.com/package/%40adep/cli/#readme-%E5%AD%90%E5%91%BD%E4%BB%A4)
    
    -   [`adep init`](https://npmcn.com/package/%40adep/cli/#readme-adep-init)
        
    -   [`adep dev`](https://npmcn.com/package/%40adep/cli/#readme-adep-dev)
        
    -   [`adep serve`](https://npmcn.com/package/%40adep/cli/#readme-adep-serve)
        
    -   [`adep publish`](https://npmcn.com/package/%40adep/cli/#readme-adep-publish)
        
    -   [`adep deploy`](https://npmcn.com/package/%40adep/cli/#readme-adep-deploy-deprecated)
        
    -   [`adep projects`](https://npmcn.com/package/%40adep/cli/#readme-adep-projects)
        
    -   [`adep functions`](https://npmcn.com/package/%40adep/cli/#readme-adep-functions-deprecated)
        
    -   [`adep mcp`](https://npmcn.com/package/%40adep/cli/#readme-adep-mcp)
        
    -   [`adep doctor`](https://npmcn.com/package/%40adep/cli/#readme-adep-doctor)
        
    -   [`adep db`](https://npmcn.com/package/%40adep/cli/#readme-adep-db)
        
    -   [`adep storage`](https://npmcn.com/package/%40adep/cli/#readme-adep-storage)
        
    -   [`adep hosting`](https://npmcn.com/package/%40adep/cli/#readme-adep-hosting-deprecated)
        
    -   [`adep export`](https://npmcn.com/package/%40adep/cli/#readme-adep-export)
        
    -   [`adep app`](https://npmcn.com/package/%40adep/cli/#readme-adep-app)
        
4.  [配置](https://npmcn.com/package/%40adep/cli/#readme-%E9%85%8D%E7%BD%AE)
    
    -   [环境变量](https://npmcn.com/package/%40adep/cli/#readme-%E7%8E%AF%E5%A2%83%E5%8F%98%E9%87%8F)
        
    -   [`adep.config.ts`](https://npmcn.com/package/%40adep/cli/#readme-adepconfigts)
        
5.  [常用示例](https://npmcn.com/package/%40adep/cli/#readme-%E5%B8%B8%E7%94%A8%E7%A4%BA%E4%BE%8B)
    
6.  [FAQ](https://npmcn.com/package/%40adep/cli/#readme-faq)
    
7.  [相关](https://npmcn.com/package/%40adep/cli/#readme-%E7%9B%B8%E5%85%B3)
    

* * *

## 安装

```bash
# 通过 npm 全局安装
npm install -g @adep/cli
# 或使用 bun
bun add -g @adep/cli
# 发布前本地调试：从仓库根目录
bun run packages/cli/src/index.ts --help
```

> **要求**：Node ≥ 22.19，或 Bun ≥ 1.3（Bun 可免编译直接运行 TS，推荐用于本地开发）。 安装后运行 `adep --help` 查看全部可用命令。

* * *

## 快速开始

```bash
# 1. 登录平台（打开浏览器用网页授权；凭据按 server 分槽保存于 ~/.adep/credentials.d/，权限 0600）
adep login
# 无浏览器环境（SSH / 无桌面）：只打印验证码与链接，手工在浏览器里完成授权
adep login --no-browser
# 或不走浏览器，直接用邮箱密码登录（脚本 / 老平台）
adep login -s https://platform.example.com -e you@example.com -p '***'

# 2. 初始化一个函数项目
adep init my-app --template function

# 3. 进入项目，本地调试（监听 functions/，支持热重载）
cd my-app
adep dev
# → http://127.0.0.1:8787/hello

# 4. 部署上线（全栈：函数 + 前端）
adep publish
```

三步即可把本地 `functions/hello.ts` 与 `web/` 前端发到线上并得到公网访问地址。 只发布函数：`adep publish --only functions`；只发布前端：`adep publish --only frontend`。

* * *

## 子命令

所有子命令都支持全局 `--json` 标志，以机器可读的 JSON 信封输出（适合 Agent / 脚本调用）：

```bash
adep --json whoami
# → {"ok":true,"command":"whoami","data":{"email":"...","server":"..."}}
```

失败时返回退出码 1 + `{"ok":false,"command":"...","error":{"code":"...","message":"..."}}`。

### `adep login` / `whoami` / `logout`

`adep login` 缺省走**浏览器网页授权**（RFC 8628 设备授权流）：CLI 向平台要一个设备码并把 `<平台>/device?user_code=XXXX` 打开，你在网页上确认「批准」后 CLI 自动换回会话并落盘凭据。

```bash
adep login                       # 打开浏览器；终端会同时打印验证码与链接
adep login --no-browser          # 不开浏览器：手工访问打印出来的链接（SSH / 无桌面）
adep login -s <url>              # 指定平台（缺省 ADEP_SERVER，再缺省 https://adep.top）
adep login -e <邮箱> -p <密码>   # 邮箱密码直登，不发起浏览器流程（CI / 老平台）
adep whoami                      # 查看当前身份（读凭据并向平台确认会话仍有效）
adep logout                      # 通知平台注销并清除本地凭据
```

-   判定「打不开浏览器」的三种情况：`--no-browser`、`ADEP_NO_BROWSER=1`、stdout 不是 TTY（CI）。 三种都**不会**尝试打开浏览器，但都会打印验证码与链接——命令仍可完成登录。
-   `--json` 模式下交互提示（验证码 / 链接）写 **stderr**，stdout 恒为恰好一个 JSON 对象。
-   失败语义：用户拒绝 → `LOGIN_DENIED`；验证码过期 → `DEVICE_CODE_EXPIRED`； 平台没有设备授权端点（老版本）→ `LOGIN_UNSUPPORTED`（提示改用 `-e/-p`）。失败**不写凭据**。
-   凭据形态：浏览器登录落 `authType: "bearer"`（发 `Authorization: Bearer`）， 密码直登落 `authType: "cookie"`；旧凭据缺该字段按 cookie 兼容。
-   凭据按 server **分槽**保存（`~/.adep/credentials.d/<host>.json` + `current` 指针， 权限 0600）：SaaS 与本地自建位等多环境先后登录**互不覆盖**——登录哪个环境， 后续命令就连哪个环境的凭据，谁也不会被静默替换；旧版单文件 `~/.adep/credentials` 在首次读写时自动迁入对应槽并删除。同 server 重复登录只覆盖自己的槽（输出会注明 替换了哪个邮箱的凭据）。

### `adep init`

初始化项目（脚手架）。**默认 `fullstack` 模板**：生成与 Web IDE 项目**同一结构**的全栈骨架 （`functions/` 云函数 + `web/` 标准 Vite 前端工程 + `database/schema.sql`）：

| 模板 | 说明 |
| --- | --- |
| `fullstack` | 全栈骨架：`functions/` + `web/`（Vite + Vue 3）+ `database/schema.sql`（默认） |
| `function` | 仅云函数：单个示例函数 `functions/hello.ts` |
| `empty` | 仅项目骨架（`adep.config.ts` + 类型提示入口，不生成示例产物） |

```bash
adep init my-app                      # 默认 fullstack 模板（与 Web IDE 项目同构）
adep init my-app -t function          # 仅云函数
adep init my-app -t empty             # 空模板
adep init --list                      # 从平台 GET /api/v1/templates 列出可用模板
adep init --list -s https://platform.example.com
adep templates publish -t fullstack  # 上传平台托管模板包（需登录；模板目录须含 template.json）
```

模板来源（CLI-023）：`adep init` 优先下载**平台托管模板包**（`GET /api/v1/templates/:code/package`， 缓存到 `~/.adep/templates/<code>-<version>.json`）；平台无包 / 下载失败 / 离线时自动回退本地内置模板。 模板包为 JSON 文件映射，与本地内置模板共用同一套 `{{var}}` 渲染管线。

产物结构（`fullstack` 模板，CLI-014：vite 工程根在项目根目录）：

```
my-app/
├── package.json         # 应用定义：@adep/cli + 前端依赖同根声明 + scripts（dev/build/site:deploy/serve/deploy/doctor）+ engines
├── vite.config.ts       # vite 配置：vue 插件 + adep() 云函数插件；build.outDir = site/
├── index.html           # vite 入口（引用 /web/src/main.ts）
├── adep.config.ts       # 项目配置：name / template / functionsDir / functions_prefix（默认 /api）
├── tsconfig.json        # 云函数 TypeScript 编辑器配置（strict + noEmit）
├── adep.d.ts            # 云函数上下文环境类型声明（ctx: AdepContext 补全）
├── functions/
│   ├── hello.ts         # 示例函数（deploy 后经 /api/hello 触发）
│   └── README.md
├── web/src/             # 前端源码（Vue 3；与 Web IDE 的 web/ 工程共用同一份 src/）
│   ├── main.ts
│   └── App.vue
├── site/                # vite build 构建产物（站点托管目录，adep hosting deploy site 上传；已 gitignore）
├── database/
│   └── schema.sql       # 数据库结构（占位；表由平台控制台 / adep db 管理）
├── README.md
└── .gitignore           # 已忽略 node_modules/ data/ .adep/ site/
```

**根 package.json**：与导出的离线部署包（`adep export` / 平台自托管导出）的应用定义同构—— 声明 `@adep/cli` 版本依赖（值来自 CLI 自身发布版本，不硬编码）与常用 scripts： `pnpm dev`（= `vite`，全栈开发：前端 HMR + 云函数代理）/ `pnpm build`（= `vite build` → `site/`）/ `pnpm site:deploy`（= `adep hosting deploy site --spa`）/ `pnpm serve` / `pnpm deploy` / `pnpm doctor`。

**全栈开发（vite + 云函数代理）**：`pnpm dev` 启动 vite 后，`@adep/cli/vite` 插件在 vite 进程内 启动 `adep dev`（模拟运行时，函数热重载 / .env.local / cloud.\* 全可用），并把 `/{functions_prefix}/*` 请求代理到云函数——默认前缀 `/api`（与线上函数路由对齐）， 前端 `fetch('/api/hello')` 即调用 `functions/hello.ts`。

**functions\_prefix（云函数路由前缀）**：`adep.config.ts` 的 `functions_prefix`（**默认 `/api`**）：

-   `adep dev` 访问路径 `/{prefix}/{fnName}`（如 `/api/hello`）；vite 插件按同一前缀代理。
-   `adep serve` 为 `/api/{prefix}/{fnName}`（前缀拼接在 `/api/` 之后）。
-   留空（旧项目）：`adep dev` 为 `/{fnName}`，`adep serve` 为 `/api/{fnName}`； vite 插件在配置为空时强制 `/api` 并同步覆盖 dev 路由，保证代理与路由一致。
-   **边界**：只影响本地 HTTP 入口路由；函数互调 `ctx.cloud.invoke('name')` 与线上部署路径 按函数名，不随前缀变化（与线上同构）。

**前端源码（web/src/）**：与 Web IDE 内 `web/` 工程的 `src/` 完全同构（同一份模板真相源）； vite 工程根在项目根目录（`vite.config.ts` / `index.html` / 根 `package.json`），构建产物输出到 `site/`（站点托管目录），`pnpm site:deploy` 上传部署。

**类型提示**：`adep init` 产出的项目自带 `tsconfig.json` 与 `adep.d.ts`，用 VSCode 打开即可在 `functions/` 下获得 `AdepContext` / `ctx.cloud.*` 补全，无需本机安装 `@adep/types`。 函数签名写 `export default async (ctx: AdepContext) => {...}` 即可。

> 目录已存在时会拒绝覆盖（fail loud），不会静默改写你的代码。

### `adep dev`

本地调试：监听 `functions/`（以及 `.env.local` / `adep.config.ts`）变化并热重载，默认监听 `http://127.0.0.1:8787/<fnName>`，冷启动 ≤ 1.5s，文件变更到可被调用 ≤ 300ms。

```bash
adep dev                      # 默认端口 8787
adep dev -p 3000              # 指定端口
adep dev --db sim             # 回到纯模拟数据面（.adep/sim/db.json）
adep dev --db sqlite --db-file var/dev.sqlite    # 自定义库文件
adep dev --schema database/schema.sql            # 启动时灌 schema（与 serve 同一套语义）
```

-   **模拟运行时**：默认使用进程内模拟运行时（`@adep/runtime` + 本地模拟器），**不连云端、不装 Docker、断网也能开发**——只替换传输与持久化，不改写函数语义。
    
-   **数据库面与 `adep serve` 同源**：缺省 `--db sqlite`（真实 SQLite 库文件 `.adep/data/project.sqlite`，schema.sql 全量生效、视图 / 唯一索引可用；运行时不支持或打开失败时自动降级 `sim` 并告警），`--db sim` 回到内置模拟引擎。三个旗标（`--db` / `--db-file` / `--schema`）与 `adep serve` **共用同一份实现**，两条命令在同一目录、同一环境下必然给出同一个数据面。
    
-   **能力注入**：自动装配 `cloud.db` / `cloud.storage` / `cloud.realtime`，语义与线上一致。
    
-   **环境变量**：读取 `.env.local` / `.env` 的键值，注入执行沙箱（`process.env[KEY]`）。
    
-   **能力边界**：启动时打印一行边界清单（如下），提示本地与线上的差异：
    
    -   定时/事件触发器只登记，本地以手工 HTTP 调用替代；
        
    -   realtime 为单进程内存广播，线上多实例语义不同；
        
    -   本地不执行计量 / 配额门禁，不计费。
        

```bash
[adep] dev server listening on http://127.0.0.1:8787（Ctrl-C 退出）
[adep] curl 示例：curl http://127.0.0.1:8787/hello
...
```

### `adep serve`

开发态服务器：把函数（`/api/{fn}`）、`/healthz`、静态托管与组件预览合并到一个进程里常驻，**默认只绑回环地址，是本地开发服务器而非生产服务器**。自托管部署包内用它指向包内 `web/` 站点。

```bash
adep serve                       # 默认 127.0.0.1:8787（PORT / HOST 环境变量可覆盖）
adep serve -p 9000               # 指定端口
adep serve --static web          # 指定静态托管目录（缺省 public/）
adep serve --db sqlite           # 真实 SQLite 库文件（缺省 .adep/data/project.sqlite）
adep serve --db sqlite --db-file var/local.sqlite   # 指定库文件
```

-   缺省值优先级为「命令行旗标 > 环境变量（`PORT` / `HOST` / `ADEP_SERVE_STATIC_DIR` / `ADEP_SERVE_DB` / `ADEP_SERVE_DB_FILE`）> 内置缺省」，容器编排注入的 `PORT` / `HOST` 不会被命令行缺省盖掉。
    
-   绑定非回环地址时给出对外暴露警告（它不带生产级加固）。
    
-   数据库两档模式（`--db`）：
    
    -   `sqlite`（缺省）：**真实 SQLite 库文件**，驱动按运行时分派（Bun → `bun:sqlite`，Node ≥ 22.5 → `node:sqlite`）。`--schema` 的每条语句都真实执行，**失败即停**（视图 / 唯一索引 / 触发器等 sim 做不到的能力全可用）。运行时不支持（Bun / Node < 22.5）或打开库文件失败时**自动降级 `sim` 并告警**，不拒绝启动；
    -   `sim`：内置模拟引擎，库是 JSON 文件 `.adep/sim/db.json`。`--schema` 只支持 DDL 子集，其余语句跳过并告警。
    -   模式名写错（旗标或环境变量）一律拒绝启动，不静默换库；启动横幅与根路径 `/` 会回显 `db.mode` / `db.file` / `db.driver`。

### `adep publish`

全栈发布顶层命令（CLI-010）：函数部署 + 前端构建托管一把梭。

```bash
adep publish                          # 缺省全栈：函数 deploy + 前端平台侧构建托管
adep publish --only functions         # 只发布云函数
adep publish --only frontend          # 只发布前端（vite 工程平台侧构建；纯静态站直通托管通道）
adep publish --only frontend --env dev   # 前端发到**开发站点**（site-dev/ + dev- 子域 + 独立版本序列）
adep publish -p my-app                # 显式指定目标 slug
```

-   **函数部分**：扫描本地 `functions/` 计算内容哈希 → 调平台 `/api/v1/deploy/diff` 拿差异清单 → 仅上传变更函数 → 发布 → 输出访问域名（与 `adep deploy` 同一管线）。
    
-   **前端部分（vite 工程）**：先整组同步本地 `web/` 草稿，再调平台 `POST /api/v1/projects/:id/frontend/publish`（服务端真实构建），读 `/frontend/versions` 取当前版本与 `siteUrl`。未登录由 `createClient` 统一抛 `NOT_LOGGED_IN`。
    
-   **前端部分（纯静态站直通）**：本地 `web/` 无 `scripts.build` 且无待编译源码（与平台 `isStaticSite` 同语义）时，不经草稿与平台构建，直接 multipart 上传 `site/` 打开托管—— 草稿通道的 ≤100 文件 / ≤512KB / 仅文本上限是「源码草稿」预算，vendored 依赖与 webp/woff2 二进制资产装不下也不该走它。缺 `web/index.html` 在上传前 fail loud （`FRONTEND_NO_PAGE`）；SPA 回退保留平台当前值（`adep hosting config --spa` 可改）。
    
-   成功输出每个函数的名字 / 版本 / 访问地址，末尾汇总函数部署数 + 前端构建状态 + 站点 URL：
    

```bash
hello  v1  https://my-app.platform.example.com/api/hello
✓ 1 functions deployed in 3.2s
✓ frontend built v2 · https://my-app.platform.example.com
```

-   `--json` 输出统一信封 `{ ok, command, data: { scope, functions?, frontend? } }`。
    
-   **`--env dev` 只影响前端**：产物写 `site-dev/`、版本走独立序列（dev v1.. / prod v1..）、地址是 `dev-<子域>`，与线上站点完全隔离。**函数部署不受影响**——网关恒读生产库，不存在「部署一个读开发库的 函数」，输出里会显式说明。纯静态站（无 `scripts.build`、无待编译源码）传 `--env dev` 直接 fail loud （`STATIC_DEV_UNSUPPORTED`）：该通道直传 `site/`，会覆盖线上站点。
    

> 兼容别名：`adep deploy` / `adep functions deploy` / `adep hosting deploy` 保留原行为， 仅在 stderr 打印 deprecation 提示指向本命令（见下文）。

### `adep deploy`（deprecated）

> **已废弃**：推荐使用 `adep publish`（全栈）或 `adep publish --only functions`（仅函数）。 本命令保留向后兼容，运行时在 stderr 打印迁移提示。

增量部署：扫描本地 `functions/` 计算内容哈希 → 调平台 `/api/v1/deploy/diff` 拿差异清单 → 仅上传变更函数 → 发布 → 输出访问域名。

```bash
adep deploy                      # 项目 slug 取 adep.config.ts 的 name
adep deploy -p my-app            # 显式指定目标 slug
adep deploy --worker -p <id|slug>   # 按 **wrangler 项目**部署（CF-063，见下）
```

-   **`--worker` 是另一条链**：当前目录当作 wrangler 项目根，读 `wrangler.jsonc` 直传构建产物——它不是 「部署 adep 函数」，输入 / 产物 / 成败判据都不同（因此 `-p` 必填，缺省即 `WORKER_PROJECT_REQUIRED`）。 失败始终非零退出（`WORKER_DEPLOY_FAILED`）：CI 里「部署失败但退出码 0」是最坏的一种静默。
    
-   本地 `functions/<name>.ts` 对应平台函数 `<name>`（入口文件固定为 `index.ts`）。 目录形态 `functions/<name>/index.ts` **等价**：目录内其余文件是该函数的私有文件，随草稿整组上传 （默认模板生成扁平形态；两种形态不可同名并存 —— 并存时命令非零退出并列出冲突路径）。
    
-   **幂等**：内容与已发布版本一致时输出 `no changes`，不产生新版本。
    
-   成功输出每个函数的名字 / 版本 / 访问地址，末尾给一行汇总：
    

```bash
hello  v1  https://my-app.platform.example.com/hello
✓ 1 functions deployed in 3.2s
```

> 汇总只在**真的产生新版本**时写 `deployed`；全部复用时写 `✓ no changes · N functions up to date in Ts`，不把幂等说成重新发布。

### `adep projects`

项目子命令组：创建 / 列出 / 查看 / 删除。子域地址由平台回显（`projectBaseUrl`），CLI 不自行拼域名。

```bash
adep projects create notes-app              # → ✓ Project created · https://notes-app.adep.top
adep projects create notes-app -n 笔记应用  # 展示名与 slug 分开
adep projects list                          # slug \t name \t url
adep projects info notes-app                # id \t slug \t name \t url
adep projects delete notes-app --yes        # → ✓ Project deleted · notes-app
```

-   `--name` 缺省取 slug：一行命令即可建项目。
    
-   目标 slug 已占用 → 平台返回 `PROJECT_SLUG_TAKEN`，CLI 原样透传并退出码 1。
    
-   **`projects delete` 必须显式 `--yes`**：删除是**级联且不可撤销**的（云函数与草稿、前端代码、 环境变量、触发器、Git 绑定、自定义域名、MCP 工具一并清空，市场共享下架，子域名立即下线）。 缺 `--yes` 直接拒绝（`CONFIRM_REQUIRED`，退出码 1）且**不发任何请求**——不做 TTY 交互提问， 因为确定性输出（含 `--json`）比一个可能被 CI 管道吞掉的提问更可靠。删除后 slug **不回收**。
    
-   未登录 / 会话失效 → 打印错误后附带 `提示：先执行 adep login`。
    

### `adep functions`（deprecated）

> **`functions deploy` 已废弃**：推荐使用 `adep publish --only functions`（或 `adep publish --only functions -- <dir>` 等价语义）。 `functions list` / `functions logs` 保留不变。

云函数子命令组：部署（可指定目录）/ 列出 / 查日志。

```bash
adep functions deploy ./handlers            # 覆盖 adep.config.ts 的 functionsDir（deprecated）
adep functions deploy                       # 等价于 adep deploy（deprecated）
adep functions list -p my-app               # name \t 访问地址
adep functions logs hello -p my-app --tail 50
```

-   `deploy` 与 `adep deploy` 共用同一执行体，输出逐字一致（两个入口各写一遍迟早只有一处有汇总行）。
    
-   日志缓冲在平台进程内（环形），**未执行过的函数为空**——命令会如实说明而非报错。
    

### `adep mcp`

MCP Tool 子命令组：把云函数发布为项目 MCP Tool / 取消发布 / 列出。发布后外部 Agent 即可通过项目 `/mcp` 端点调用你的后端能力（只消费平台既有的 `POST|DELETE /api/v1/functions/:id/mcp-publish` 与 `tools/list`，CLI 不重实现发布逻辑）。

```bash
adep mcp publish --function stock                    # → ✓ MCP tool published · stock
adep mcp publish --function stock --name get-stock   # 以别名注册（tools/list 里出现 get-stock）
adep mcp publish --function query-database --description "查询库存"  # 覆盖面向 Agent 的描述
adep mcp unpublish --function stock                  # 取消发布（别名发布过则加 --name get-stock）
adep mcp list                                        # 打印端点地址 + 已发布 tool（name \t description）
```

-   `--function` 是**函数名**，`--name` 是可选的**注册 Tool 名**（缺省取函数名）；目标项目缺省取 `adep.config.ts` 的 `name`，也可用 `-p <slug>` 指定。
    
-   服务端错误原样透出：函数入参无法映射为 JSON Schema 时返回 `MCP_SCHEMA_UNSERIALIZABLE` 并以退出码 1 结束（CLI 不改写、不兜底，原因由服务端指出）。
    
-   `mcp list` 读的是**项目** **`/mcp`** **端点的** **`tools/list`**（与外部 Agent 同一条路径）：项目 MCP 鉴权模式为 `public` 时可直接读取；为 `api-key` 时未带 Key 会返回 `MCP_UNAUTHORIZED`。
    
-   `unpublish` 默认按函数名移除；若曾以别名发布，需加 `--name <tool>` 指向该别名。取消一个不存在的工具会如实说明、不报成功也不报错。
    

### `adep doctor`

环境自检：凭据状态、平台可达性、离线可用范围与本地模拟运行时的能力边界。

```bash
adep doctor
adep doctor --json    # { server, credentials, network, serverHealth, offlineCommands, boundaries }
```

-   已登录时体检的是**凭据里记录的那个平台**（`login --server` 可指到任意环境），未登录才回退 `ADEP_SERVER` 缺省。
    
-   平台可达性 = 对 `GET /api/v1/health` 的一次真实探测；拿到任何 HTTP 应答都算可达。
    
-   凭据文件权限宽于 `0600` 会给告警；命令本身**不因体检结论失败**（它是诊断，不是门）。
    

### `adep db`

项目数据库维护子命令组：启动 / 状态 / 停止 / SQL 执行 / 快照 / 时间点回滚。项目参数缺省取 `adep.config.ts` 的 `name`（也可用 `-p` 显式指定）。

```bash
adep db start                          # 启动项目数据库（已存在则重新激活，不重建数据）
adep db status                         # 查询状态与用量（体积 / 表数 / 行数）
adep db stop                           # 停止数据库（连接关闭并标记；文件保留）

# 列当前环境的表与行数；--table 看单表结构（字段 / 索引 / 建表 DDL）
adep db tables
adep db tables --table users

# 执行单条 SQL；写 / 破坏性语句需 --confirm-table 二次确认目标表名
adep db exec --sql "SELECT * FROM users"
adep db exec --sql "DELETE FROM users WHERE id = 1" --confirm-table users

# 快照（付费档位）：列出 / 创建 / 还原
adep db snapshot list
adep db snapshot create
adep db snapshot restore <snapshotId>

# 时间点回滚（团队版，基于变更流重放）
adep db rollback --to 2026-01-01T00:00:00.000Z
```

`db exec` 人读模式下返回对齐文本表（结果行截断时会提示），`--json` 输出结构化结果。

-   **环境（`--env`）**：`exec` / `migrate` / `tables` 按全局 `--env dev|prod` 选库，优先级 `--env` > `ADEP_ENV` > `adep.config.ts` 的 `db_environment` > `prod`；每条命令都打印生效环境**及来源**。 服务端一直支持 `?environment=`，CLI 之前不传 ⇒ `exec` 恒打生产库，开发者在 dev 建的表用 CLI 一查 就「不存在」——同一类事故的 CLI 版。
-   `start` / `status` / `stop` 与快照类**不分环境**：它们管理的是「项目数据库」这一资源本身。

### `adep storage`

云存储 / 文件存储子命令组：上传 / 下载 / 列表 / 删除。

```bash
adep storage upload ./avatar.png --path avatars/a.png            # 缺省 private（签名访问）
adep storage upload ./banner.png --path site/banner.png --visibility public   # public 直连
adep storage download avatars/a.png [-o 本地输出路径]              # 自动解析签名 / 直连 URL 落盘
adep storage ls [--prefix site/]                                  # 按前缀列出（附访问 URL）
adep storage rm avatars/a.png
```

-   **上传**：multipart，单文件 ≤ 50MB；`path` 为桶内相对路径，`visibility` 决定 public 直连或 private 签名。
    
-   **下载**：先列表解析出服务端生成的 URL（public 直连 / private 15 分钟签名），再取回内容——private 文件无需 CLI 自行签发签名。
    
-   所有命令都支持 `-p <slug>` 指定项目。
    
-   四个子命令都跟随全局 `--env`：dev 走 `.env-dev/` 键空间（dev 传的文件在 prod `ls` 里看不到，反之亦然），输出会标明当前环境。上传走 multipart 的 `environment` 字段，其余走 `?environment=`。
    

### `adep hosting`（deprecated）

> **`hosting deploy` 已废弃**：推荐使用 `adep publish --only frontend`——vite 工程平台侧构建 `web/` 草稿；纯静态站（无构建脚本、无待编译源码）同样直通本上传链路，文件数 / 总量 / 二进制不受草稿通道约束。仅当上传**非 `web/` 目录**（如本地 `vite build` 的 `dist/` 产物）时 仍需本命令，仅 stderr 提示迁移。 `hosting info` / `pull` / `config` 保留（运维类操作不并入 publish）。

静态托管子命令组：查看 / 部署 / 拉取 / 配置。站点文件即项目桶 `site/` 前缀下的 public 文件。

```bash
adep hosting info                        # 查看托管配置、站点地址与文件树
adep hosting deploy ./dist               # 增量上传目录到 site/ 并打开托管（deprecated）
adep hosting deploy ./dist --spa         # 同时启用 SPA 回退（deprecated）
adep hosting deploy ./dist --build "npm run build"   # 部署前先跑构建命令（非零退出即中止）
adep hosting pull [-o ./site]            # 拉取站点公开文件到本地（跳过 private 托管配置）
adep hosting config --enabled true --spa true    # 更新托管开关 / SPA 回退（幂等）
```

-   **deploy**：先与线上 `site/` 文件表做**增量比对**（逐文件 sha256，CLI-038）——只上传变更文件， 输出「N 变更 / M 复用」与「部署内容构建于 <本地最新文件 mtime>」；**与线上完全一致（空 diff）时 输出醒目警示**——大概率是改了源码忘了先构建（旧实现全量盲传，曾把旧包原样重传上线且零提示）。 `--build <cmd>` 在项目根目录先执行构建命令，构建失败即中止部署。把本地目录上传为 `site/<rel>`（public）→ 打开托管开关 → 输出站点地址。
    
-   **pull**：只拉公开站点文件，private 侧载的托管配置（`site/.hosting.json`）不会进站点目录。
    

### `adep export`

导出自托管部署包：触发平台长任务 → 轮询进度 → 下载 zip → 按 manifest 逐项自检，产出一个「解压即可运行」的可部署包（含应用定义、`adep.config.ts`、Docker 产物与静态站点）。

```bash
adep export                          # 目标项目取 adep.config.ts 的 name
adep export -p my-app --with-data    # 显式指定项目并包含数据库行数据（缺省仅 schema）
adep export --out ./dist-export      # 指定输出目录（缺省 ./exports）
```

-   `--with-data` 附带行数据，`--with-source` 附带函数源码（平台缺省已含，显式给出不改变默认）。
    
-   `--json` 输出单个结果信封；导出失败（长任务未产出 / 自检不过）以退出码 1 + `EXPORT_FAILED` 结束，不静默给半截产物。
    

### `adep app`

应用壳工程（PRD §2.11 路径 A：在线运行时——**页面随包本地加载、云函数服务端执行**，改函数逻辑不需要重新发版）。 两种壳：`--platform desktop`（缺省，Electron）与 `--platform mobile`（Capacitor 移动壳，见下）。

```bash
adep app init -p my-app -n "我的应用"        # 生成 Electron 壳工程（缺省 ./my-app-app）
cd my-app-app && npm install                 # 壳工程依赖（electron + electron-builder）
adep app open                                # 启动开发预览（等价壳工程内 npm start，构建前先跑一眼）

adep app build                               # 拉取已发布页面产物 → 注入 app/site/ → 出安装包
adep app build --platform win32              # 交叉指定目标平台（缺省当前平台）
adep app build --target dir                  # 只出未压缩目录（macOS 即 .app），本地快速验证
adep app build --prepare-only                # 只拉产物 + 注入 + 出构建报告，不调 electron-builder
```

-   `app build` 只把项目**已发布**的前端产物（`adep publish --only frontend` 的产物）打进壳： 经平台导出链路拉包 → 校验 manifest 与逐项 sha256 → 只取 `site/**` 注入 `app/site/` （注入前清空旧产物，上一次构建留下的陈旧文件不会躺在安装包里）；
    
-   **缺省产物形态**（APP-037 契约门锁住，漂移当场红）：
    
    | 平台 | 缺省格式 | 签名状态 | 说明 |
    | --- | --- | --- | --- |
    | macOS（`darwin`） | `.dmg` | unsigned | 签名 / 公证由开发者本地完成 |
    | Windows（`win32`） | nsis 安装器（`*-Setup.exe`）+ zip 便携包（`*-win.zip`） | unsigned | 安装器**不是单文件绿色 exe**；zip 便携包（APP-043）解压后直接运行里面的 `<productName>.exe`，两者同次产出 |
    | Linux（`linux`） | `.AppImage` + `.deb` | unsigned | deb 需要宿主机有 `dpkg-deb`——缺失时 electron-builder 会静默跳过，构建报告与终端会显式列出 `APP_BUILD_TARGET_SKIPPED` 及原因（rpm 不进缺省模板，见计划 R2 拍板 P3） |
    | Android（`android`） | unsigned `.apk` | unsigned | `gradlew assembleRelease`，签名由开发者自担 |
    | iOS（`ios`） | unsigned `.xcarchive` / `.ipa` | unsigned | xcodebuild 或 xtool（`--toolchain xtool` 产 `.ipa`） |
    
-   **函数源码不入包**：在线运行时下函数在服务端执行，构建报告里的函数清单只标 `runtime: "online"`（安装包内不含任何 `functions/` 文件）；
    
-   产物版本回写 `adep.app.json` 的 `build` 段（`bundleVersion` = manifest 项目版本 + `site/` 内容指纹， 内容不变则版本不变），同一份版本也写进 `dist/build-report.json`（`appName` / `bundleVersion` / `functions` / `topAssets` 四字段 + 平台、产物路径等）；
    
-   平台**不出具任何签名**：签名与公证由开发者本地完成；
    
-   fail loud（都以退出码 1 结束且不产出安装包）：项目从未发布前端（提示先跑 `publish --only frontend`）、壳工程依赖未安装（提示先 `npm install`）、导出包损坏或内容物校验和不匹配。 其中「依赖未安装」的判定**有意排在导出之前**——导出是分钟级长任务，依赖没装不必白跑。
    
-   `app open`（APP-035）只服务桌面壳：直接调壳工程内安装的 `node_modules/.bin/electron .` （与模板缺省 start script `electron .` 等价，不经 npm 以规避 Windows 下 npm.cmd 的 shell 差异； 若你改过 start script，open 不感知，直接跑 `npm start` 即可）。**移动壳没有开发预览路径** （capacitor 壳下一步是 `npx cap add ios / android` + Xcode / Android Studio，xtool 壳是 `xtool dev`）， 对它们执行 open 当场报 `APP_OPEN_UNSUPPORTED` 并点名下一步。与 `app doctor` 同口径的开发期 便利命令：不需要登录、不需要网络、不设门（判定门在 `app build`）。
    

#### 移动壳（Capacitor，APP-009）

```bash
adep app init -p my-app -n "我的应用" --platform mobile   # Capacitor 骨架 + plugins/adep-bridge 原生桥
cd my-app-app && npm install
npx cap add ios && npx cap add android                   # 原生工程由 Capacitor 生成

adep app build --platform android --prepare-only         # 只注入 + 出报告，先验证注入面
adep app build --platform android                        # gradlew assembleRelease → unsigned APK
adep app build --platform ios                            # xcodebuild archive（CODE_SIGNING_ALLOWED=NO）
```

-   骨架含 `plugins/adep-bridge` **原生桥**（iOS Swift / Android Kotlin）与 host-side 门控镜像 `bridge/gate.mjs`：权限门控做在**原生侧**，未在 `adep.permissions.json` 声明的权限一律 `PERMISSION_DENIED` + 设备侧审计日志；`ownerKey` 只存 Keychain / Keystore。
-   构建往 `app/site/` 落四件：`adep.permissions.json`（权限清单）、`adep-bridge.js`（页面桥）、 `adep.app.json`（壳配置）、以及往 `index.html` 幂等注入的一行 `<script src="/adep-bridge.js">`。 **缺 `index.html` 即构建失败**（`APP_SITE_MISSING`）：它是 WebView 恒加载的入口页，缺了装机就是 白屏——所以不产出「报告成功、装机白屏」的包。页面加载后由桥装配 `window.__ADEP_APP__`， 失败时按原因分三种字段（`configError` / `offlineError` / `timeoutError`），都带可读原因， 不会只剩一个 `MISSING`。
-   iOS 侧原生桥是**双形态并存**（APP-015）：`Package.swift`（SPM）与 `ios/AdepBridge.podspec` （CocoaPods）各管一条消费路径。自 Capacitor 8 起 `cap add ios` 默认建 SPM 工程，缺 SPM 清单的 插件会被**静默跳过**（运行时才报 "plugin is not implemented"），所以两者都别删；包名 / product 名 （`AdepBridge`）、目录布局（清单在 npm 包根、源码平铺 `ios/Sources`）与 iOS 下限（14.0）两形态必须一致。
-   移动平台**必须显式指定** `--platform ios|android`；产物是 **unsigned** 的 `.xcarchive` / APK。
-   ⚠️ **`.xcarchive` ≠ 安装包**（APP-040）：它是 Xcode 的归档格式，不能直接装真机；导出 `.ipa` 还需要在 Xcode 里完成 Distribute App（或 `xcodebuild -exportArchive`），而导出要**用户自备** `ExportOptions.plist` 与描述文件——平台不出具签名（PRD §2.11.7），这一步不做自动化 （见 `docs/mobile-shell-signing.md` §3）。构建期会对 `.xcarchive` 做产物级结构核对： 缺 `Products/Applications/*.app` 报 `APP_ARCHIVE_INCOMPLETE`；归档内出现 `_CodeSignature` / `embedded.mobileprovision` 报 `APP_ARCHIVE_SIGNED`（与「平台不出具签名」 口径冲突，属实现回归）。
-   签名 / 公证 / 上架由开发者自担，逐步指引见仓库 `docs/mobile-shell-signing.md`。

#### 离线运行时（`--offline`，APP-008 / APP-022）

```bash
adep app build --offline                     # 桌面壳：注入 app/offline/
adep app build --offline --toolchain xtool   # iOS xtool 壳：注入 app/site/offline/
```

把设备端运行时（`@adep/app-runtime`）装入壳工程的离线根——桌面 `app/offline/`，xtool `app/site/offline/`（页面经 `capacitor://` 只能读 `appLocation` 之内的文件）：白名单云函数与 数据库基线表全部**随包本地执行**，不需要平台在线。白名单函数含**不可移植**写法时构建失败、 退出码非 0，错误含违规类型与文件名行号。

`--offline` 在**桌面壳**下不接受 `--platform`（离线包与平台无关）；iOS 走 `--offline --toolchain xtool`（恒 `--platform ios`）。

⚠️ **xtool 离线构建要求先跑在线构建**：离线路径只追加 `site/offline/` 子树与壳注入面 （页面桥 / `adep.app.json` / 权限清单），**不产生页面本体**——页面只能来自平台导出。 缺 `app/site/index.html` 时当场报 `APP_SITE_MISSING`，不会产出「报告成功、装机白屏」的包。

```bash
adep app build --platform ios --toolchain xtool   # 1) 拉页面产物 + 注入页面桥 / 壳配置
adep app build --offline --toolchain xtool        # 2) 追加离线树
```

#### 壳工程体检（`adep app doctor`，APP-031）

```bash
adep app doctor                      # 体检当前目录（壳工程根）
adep app doctor --dir ./my-app-app   # 指定壳工程
adep app doctor --json               # 机器可读（脚本 / CI 归档）
```

**只读、不需要登录、不需要网络**：体检的是「盘上已经有的东西」。它与 `app build` 的分工是场景不同—— build 要先登录、先发布、跑一整轮导出才知道注入面齐不齐；doctor 一条离线命令就回答同一个问题， 适合排查「上次构建留下的壳工程为什么装机白屏」。十项结论各带固定 `id` 与原因码（与构建侧同码）：

| id | 查什么 | 不通过时 |
| --- | --- | --- |
| `config` | `adep.app.json` 在且过 schema | `APP_CONFIG_NOT_FOUND` / `APP_CONFIG_INVALID`（读不到就当场收口，不再往下猜） |
| `form` | 由 `template` 推导构建形态（desktop→electron；mobile→capacitor + 盘上原生工程；xtool→xtool/ios） | 还没 `npx cap add` / 未知模板 ⇒ 提示 |
| `deps` | 打包器前置（复用构建侧判定，不写盘） | `APP_SHELL_DEPS_MISSING` / `APP_XTOOL_MISSING` / `APP_XCODE_SDK_MISSING` |
| `siteEntry` | `app/site/index.html` | `APP_SITE_MISSING` / `APP_SITE_UNREADABLE` |
| `bridgeTag` | 入口页引用了 `/adep-bridge.js`（桌面壳改查 `preload.cjs`） | 桥压根不执行 ⇒ `__ADEP_APP__` 永不出现 |
| `siteAssets` | `app/site/` 三件套齐（桌面壳不走注入，跳过） | 点名缺哪一个 |
| `configDrift` | 站点内壳配置与壳根一致（比页面消费的 6 个字段；`build` 段不比） | 构建后改了配置没重建 ⇒ 页面还在打旧平台地址 |
| `buildBinding` | 壳根有 `build` 段 | 未构建过 ⇒ 提示（新 init 的正常中间态） |
| `offline` | 离线树必需文件 + 函数清单里每个函数的源码 | 点名缺件 / 缺哪个函数源码（设备上会 FN\_NOT\_FOUND） |
| `identity` | 桌面壳首启是否签发了 `ownerKey`、落在哪种存储（读 `data/identity/status.json`，**非机密**） | 未自举 ⇒ 提示；落在 0600 文件 ⇒ 明说「非系统凭据」；签发失败 ⇒ 原因码原样透出（APP-033） |

**它不是门**：有 `fail` 项也以退出码 0 结束（与 `adep doctor` 同口径）；判定门在 `adep app build`。

#### 离线库同步（`adep app sync`，APP-032）

```bash
adep app sync --owner-key adep_ok_…        # 一次往返：先上行 outbox，再拉下行增量
adep app sync --owner-key adep_ok_… --push # 只上行（排障时不必来回跑整轮）
adep app sync --owner-key adep_ok_… --pull # 只下行
ADEP_OWNER_KEY=adep_ok_… adep app sync     # 也可以走环境变量
```

把桌面壳的**设备本地库**（`data/offline.sqlite`，由离线运行时首次启动时创建）与云端项目库按 单主语义对齐：上行读本地变更流 → `outbox` → `POST /app-sync/upstream`（整批原子，服务端确认后才推进 `acked_seq`）；下行 `GET /app-sync/changes?since=<游标>` → 应用进本地库（**直写驱动，不追加变更流**， 否则刚拉下来的行会被下一次上行当成新写推回去）。

-   **身份不是可选项**：`--owner-key` / `ADEP_OWNER_KEY` 必填。ownerKey 由服务端签发 （`POST /api/v1/projects/<slug>/app-installations`，移动壳由原生侧首启自举写入 Keychain / Keystore， 桌面壳由主进程首启自举写入系统凭据库或 0600 文件，见 APP-033）， CLI **不复用平台会话**冒充设备身份；缺失即 `IDENTITY_MISSING` 且不发任何 `/app-sync` 请求。 桌面 app 自己启动后会自动同步；本命令用于**开发期 / 排障**（比如看某次上行到底卡在哪一批）。
-   同步目标取壳配置的 `platformUrl` / `projectSlug`（不是 `ADEP_SERVER`）：同步的一定是**这个壳**连的项目。
-   只支持**桌面壳**：移动壳的库在设备沙箱里，本机 CLI 摸不到（`APP_SYNC_UNSUPPORTED_SHELL`）。
-   本地库不存在 ⇒ `APP_SYNC_DB_MISSING`（先跑一次离线运行时，库才会被建出来）。
-   服务端拒绝时命令退出码非 0，**码与 `failedSeq` 原样透出**，本地位点不动（可原样重试）。

* * *

## 配置

### 环境变量

| 变量 | 说明 | 缺省 |
| --- | --- | --- |
| `ADEP_SERVER` | 平台地址（CLI 请求的默认 server） | `https://adep.top` |
| `ADEP_HOME` | 凭据目录（测试隔离用） | `~/.adep` |
| `ADEP_NO_BROWSER` | `1` = `adep login` 不打开浏览器 | 未设置（TTY 下自动打开） |
| `ADEP_ENV` | 数据面默认环境（`dev` / `prod`） | 未设置（再读 `db_environment`，最后 `prod`） |
| `ADEP_OWNER_KEY` | `adep app sync` 的设备身份（服务端签发的 ownerKey） | 未设置（`--owner-key` 优先；两者都空即 `IDENTITY_MISSING`） |

```bash
export ADEP_SERVER=https://platform.example.com
export ADEP_HOME=~/.adep
export ADEP_ENV=dev          # 等价于每条命令都带 --env dev（db exec / migrate / tables、storage、publish 前端）
```

> 也可通过 `-s` / `-e` / `-p` 等子命令参数覆盖。全局旗标 `--env <dev|prod>` 优先级最高： `--env` > `ADEP_ENV` > `adep.config.ts` 的 `db_environment` > `prod`。

### 开发期环境变量（`.env` / `.env.local`）

项目根的 `.env` / `.env.local` 与进程环境变量是**两条不同的通道**，混着预期是本地开发 最常见的排查黑洞（esign 实测：`ADEP_AUTH_ISSUER` 写进 `.env` 后用 `bun run` 起 serve—— 函数数据面一切正常、应用却显示未登录，白耗一轮排查）：

| 通道 | 谁在读 | 变量 | 生效条件 |
| --- | --- | --- | --- |
| **函数 env**（注入函数运行时） | `adep dev` / `adep serve` 自己读 `.env` + `.env.local` 文件 | 业务变量、`ADEP_SECRET_*`、`FUNCTIONS_FETCH_*` | 写进文件即可，**不依赖 shell 进程** |
| **进程级**（CLI 命令自身的行为开关） | 只认 `process.env`，**不读 `.env` 文件** | `PORT` / `HOST` / `ADEP_SERVE_STATIC_DIR` / `ADEP_SERVE_DB` / `ADEP_SERVE_DB_FILE` / `ADEP_SERVER` 等 | `export` / `env VAR=... adep serve` / Docker `env_file` |
| **混合**（登录即服务） | `process.env` 优先；缺失时回退 `adep dev` / `adep serve` 读到的 `.env` + `.env.local` | `ADEP_AUTH_ISSUER` | `export`（优先级最高）或直接写 `.env` |

函数 env 的合并优先级（`adep dev` / `adep serve` 同一份实现）：`adep.config.ts` 的 `environment` 为基座 → `.env` 覆盖 → `.env.local` 最优先。

⚠️ **`bun run <script>`（以及 `npm run`）直跑自定义脚本时，`.env` 不会自动生效**—— `bun run` 的子进程不自动加载 `.env`（node 更不会）。但 `adep dev` / `adep serve` 自己会读文件， 所以「进程级变量全部失效」只对纯 shell 开关成立：

-   函数 env 不受影响（CLI 自己读文件，数据面已自愈）；
-   `ADEP_AUTH_ISSUER` 有文件回退（CLI-044）：写进 `.env` 后 `bun run serve` / `adep serve` 也能 启用「登录即服务」，不再出现「平台授权成功、应用显示未登录」；`process.env` 仍优先；
-   其余进程级开关（`PORT` / `HOST` / `ADEP_SERVE_*`）仍只认 `process.env`，要显式 `export` 或 `env VAR=... adep serve`。

拿不准一个变量属于哪条通道，看它在哪个环节被消费：函数代码里读的走文件通道， `adep serve` / `adep dev` 命令行为开关走进程通道（`ADEP_AUTH_ISSUER` 是唯一的文件回退例外）。

### `adep.config.ts`

`adep init` 生成的项目配置文件，CLI 的 `dev` / `serve` / `deploy` 按此识别项目（CLI 直接 import 后读 `default` 的字段，无需任何辅助包）：

```ts
// adep 项目配置：CLI（dev / serve / deploy）与云函数 vite 插件按 default export 读取。
export default {
  name: 'my-app', // 项目名（deploy 的默认 slug）
  template: 'fullstack', // 模板：empty | function | fullstack
  functionsDir: 'functions', // 云函数目录
  functions_prefix: '/api', // 云函数路由前缀（默认 /api，与线上 /api/{fn} 对齐）
  db_environment: 'dev', // 数据面默认环境（dev | prod，2026-10-18）
}
```

-   `functionsDir`：云函数目录（`dev` / `serve` / `deploy` 读取，缺省 `functions/`）。
-   `functions_prefix`：**影响本地路由与 vite 插件代理前缀**（见上方 `adep init` 产物结构说明）—— 默认 `/api`：`adep dev` 访问 `/{prefix}/{fnName}`、`adep serve` 访问 `/api/{prefix}/{fnName}`、 vite 插件按 `/{prefix}/*` 代理；函数互调与线上部署路径不随前缀变化。
-   `db_environment`：不带 `--env` 也不设 `ADEP_ENV` 时数据面命令的默认环境。⚠️ **不能复用** `environment`——那个键是「注入函数运行时的变量表」（`Record<string, string>`），同名会让解析拿到 对象、判成非法值。

* * *

## 常用示例

```bash
# 登录后查看当前身份
adep whoami

# 登出并清除本地凭据
adep logout

# 列出平台可用的脚手架模板
adep init --list

# 数据库运维：启动 → 看状态 → 跑 SQL → 打快照
adep db start
adep db status
adep db exec --sql "SELECT count(*) FROM users"
adep db snapshot create

# 云存储：上传 / 下载 / 删除
adep storage upload ./logo.png --path assets/logo.png --visibility public
adep storage download assets/logo.png -o ./logo.png

# 静态托管：本地构建产物一键上线，随时拉回
adep hosting deploy ./dist        # deprecated：推荐 adep publish --only frontend
adep hosting pull -o ./site

# 以 JSON 输出（Agent / CI 可用）
adep --json publish -p my-app
```

* * *

## FAQ

**Q：`adep login`** **失败提示** **`NOT_LOGGED_IN`** **/** **`SERVER_UNREACHABLE`？** 先确认 `ADEP_SERVER`（或 `-s`）指向可访问的平台地址，再重新 `adep login`。凭据保存在 `~/.adep/credentials`（权限 `0600`）。

**Q：`adep dev`** **需要 Docker / 云连接吗？** 不需要。默认使用进程内模拟运行时（`@adep/runtime`），断网也能开发——只替换传输与持久化，不改变函数语义。

**Q：本地开发与线上行为会不一致吗？** 模拟器刻意保持执行语义一致：`cloud.db` / `cloud.storage` / `cloud.realtime` 能力装配复用线上逻辑。差异点仅限传输层与持久化层，且 `adep dev` 启动时会打印边界清单（触发器不自动执行、无跨实例广播、不在本地计量计费）。

**Q：`adep deploy`** **显示** **`no changes`？** 这是幂等设计：本地函数内容与已发布版本一致时复用当前版本，不产生新版本。想强制更新需修改函数内容。

**Q：项目名的命名规则？** `init` 项目名：小写字母开头，仅含小写字母 / 数字 / 连字符（≤ 63 字符）。

**Q：`adep db exec`** **的** **`--confirm-table`** **是做什么的？** 写 / 破坏性语句（DELETE / DROP / ALTER…）服务端要求二次确认目标表名，`--confirm-table users` 即输入目标表名以放行；只读查询无需该参数。

**Q：变量写进 `.env` 了，`adep serve` 却没生效？** 先分通道：函数 env（业务变量 / `ADEP_SECRET_*`）走 `.env` / `.env.local` 文件，`adep dev` / `adep serve` 自己读、必生效；进程级开关（`PORT` / `HOST` / `ADEP_SERVE_*` 等）只认 `process.env`，要显式 `export` 或 `env VAR=... adep serve`。`ADEP_AUTH_ISSUER` 是混合通道（CLI-044）：`process.env` 优先，缺失时回退 `.env` / `.env.local`，所以写进 `.env` 也能启用登录即服务。`bun run <script>` / `npm run` 直跑时 `.env` 不会自动加载（详见「配置 → 开发期环境变量」）。

**Q：`adep storage`** **/** **`adep hosting`** **需要在平台项目目录里跑吗？** 不需要。它们通过 `-p <slug>` 指定目标项目，缺省才读取 `adep.config.ts` 的 `name`——在任何目录下都能对指定项目做资源运维。

**Q：private 文件如何下载？** `adep storage download` 会自动调用平台列表接口拿到服务端生成的 15 分钟签名 URL 再取回内容，无需 CLI 自行签发签名；公网访问同样走该 URL。

**Q：`--json`** **输出长什么样？** 每个命令输出一个 JSON 对象：成功 `{"ok":true,"command":"...","data":{...}}`，预期内失败 `{"ok":false,"command":"...","error":{"code":"...","message":"..."}}` 且退出码为 1。

* * *

## 相关

-   `@adep/runtime` —— 平台运行时内核（执行器 + 本地模拟运行时 + 能力装配），`adep dev` 复用其保证本地/线上语义一致。

## 常见问题

### @adep/cli 是什么？

adep 命令行工具包位：登录 / 初始化 / 本地调试 / 部署 / 数据库维护 / 云存储 / 静态托管 / 微前端组件（widget），实现见任务单 CLI-001 ~ CLI-003 与 FE-002；子路径 @adep/cli/vite 提供云函数 vite 插件（CLI-014）

### 如何安装 @adep/cli？

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

### @adep/cli 支持 TypeScript 吗？

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

### @adep/cli 支持 ESM 还是 CommonJS？

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

### @adep/cli 可以商用吗？

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

### @adep/cli 的下载量有多少？

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

### @adep/cli 还在维护吗？

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

