@adep/cli

中文文档
0.4.11发布于 2026/11/03MITES Module近 30 天下载 2114

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

原始使用文档
文档目录26 节
  1. 目录
  2. 安装
  3. 快速开始
  4. 子命令
  5. adep login / whoami / logout
  6. adep init
  7. adep dev
  8. adep serve
  9. adep publish
  10. adep deploy (deprecated)
  11. adep projects
  12. adep functions (deprecated)
  13. adep mcp
  14. adep doctor
  15. adep db
  16. adep storage
  17. adep hosting (deprecated)
  18. adep export
  19. adep app
  20. 配置
  21. 环境变量
  22. 开发期环境变量( .env / .env.local )
  23. adep.config.ts
  24. 常用示例
  25. FAQ
  26. 相关

adep — AgentDeploy CLI

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

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



目录

  1. 安装

  2. 快速开始

  3. 子命令

  4. 配置

  5. 常用示例

  6. FAQ

  7. 相关


安装

# 通过 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 查看全部可用命令。


快速开始

# 1. 登录平台(打开浏览器用网页授权;凭据按 server 分槽保存于 ~/.adep/credentials.d/,权限 0600)
adep login
# 无浏览器环境(SSH / 无桌面):只打印验证码与链接,手工在浏览器里完成授权
adep login --no-browser
# 或不走浏览器,直接用邮箱密码登录(脚本 / 老平台)
adep login -s https://platform.example.com -e [email protected] -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 / 脚本调用):

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 自动换回会话并落盘凭据。

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 + 类型提示入口,不生成示例产物)
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。

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 为单进程内存广播,线上多实例语义不同;

    • 本地不执行计量 / 配额门禁,不计费。

[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/ 站点。

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):函数部署 + 前端构建托管一把梭。

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:

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 拿差异清单 → 仅上传变更函数 → 发布 → 输出访问域名。

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,不产生新版本。

  • 成功输出每个函数的名字 / 版本 / 访问地址,末尾给一行汇总:

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 不自行拼域名。

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 保留不变。

云函数子命令组:部署(可指定目录)/ 列出 / 查日志。

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 不重实现发布逻辑)。

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

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

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 显式指定)。

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

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

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 文件。

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 产物与静态站点)。

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 移动壳,见下)。

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).dmgunsigned签名 / 公证由开发者本地完成
    Windows(win32)nsis 安装器(*-Setup.exe)+ zip 便携包(*-win.zip)unsigned安装器不是单文件绿色 exe;zip 便携包(APP-043)解压后直接运行里面的 <productName>.exe,两者同次产出
    Linux(linux).AppImage + .debunsigneddeb 需要宿主机有 dpkg-deb——缺失时 electron-builder 会静默跳过,构建报告与终端会显式列出 APP_BUILD_TARGET_SKIPPED 及原因(rpm 不进缺省模板,见计划 R2 拍板 P3)
    Android(android)unsigned .apkunsignedgradlew assembleRelease,签名由开发者自担
    iOS(ios)unsigned .xcarchive / .ipaunsignedxcodebuild 或 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)

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)

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,不会产出「报告成功、装机白屏」的包。

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

壳工程体检(adep app doctor,APP-031)

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

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

id查什么不通过时
configadep.app.json 在且过 schemaAPP_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
siteEntryapp/site/index.htmlAPP_SITE_MISSING / APP_SITE_UNREADABLE
bridgeTag入口页引用了 /adep-bridge.js(桌面壳改查 preload.cjs)桥压根不执行 ⇒ __ADEP_APP__ 永不出现
siteAssetsapp/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)

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_BROWSER1 = adep login 不打开浏览器未设置(TTY 下自动打开)
ADEP_ENV数据面默认环境(dev / prod)未设置(再读 db_environment,最后 prod)
ADEP_OWNER_KEYadep app sync 的设备身份(服务端签发的 ownerKey)未设置(--owner-key 优先;两者都空即 IDENTITY_MISSING)
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.localADEP_AUTH_ISSUERexport(优先级最高)或直接写 .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 的字段,无需任何辅助包):

// 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>),同名会让解析拿到 对象、判成非法值。

常用示例

# 登录后查看当前身份
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 共发布 39 个版本,首次发布于 2026/09/03;过去 12 个月发布了 39 个版本。

版本发布日期距今
0.4.11latest2026/11/035 天前
0.4.102026/11/035 天前
0.4.62026/11/016 天前
0.4.52026/10/2810 天前
0.4.42026/10/1919 天前
0.4.12026/10/1326 天前

关于 @adep/cli 的常见问题

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