Cell API
    Preparing search index...

    Module @celljs/cli - v4.1.0

    @celljs/cli

    Cell 4 的命令行工具 cell:读取 cell.config.ts,按 preset 构建应用,运行和部署构建产物。设计见仓库的 docs/design/architecture.md,从 3.x 迁移见 docs/migration-4.md。

    需要 Node.js ^20.19.0 || >=22.12.0。在项目里安装:

    npm install -D @celljs/cli
    npx cell build
    命令 作用
    cell init [template] [dir] 从模板创建项目(backend、fullstack),自带 AGENTS.md、cell 技能和 .mcp.json;不带参数时列出模板
    cell dev 开发:前后端同一个端口,前端 HMR,后端改文件自动重载,配置变化自动重启
    cell build 构建到 .cell/output:server/index.mjs(依赖内联的单个文件)、public/(前端)、manifest.json
    cell info 描述项目:preset 及其来源、mode、目标、组件、DI 模块、hooks、产物状态。只读,不构建、不执行 hooks
    cell check 一次完成配置、TypeScript 类型、装饰器设置、后端 DI 绑定和模块注册的检查,有错误时退出码 1
    cell preview 按 manifest.json 运行构建产物,不重新构建
    cell deploy 用 preset 构建,再交给 preset 的部署器发布;--dry-run 只给出计划
    cell config get <key> 某个配置项合并后的值,--why 列出设置它的文件和环境变量
    cell docs <query> 检索已安装组件和模块随包的文档(与项目所用版本一致)
    cell mcp stdio MCP 服务器,把 info、check、config_get、docs_search、build、deploy_plan 和模块注册的工具提供给 coding agent
    cell agent sync 按已安装的版本重写 AGENTS.md 中由 Cell 管理的部分和 .agents/skills/cell/SKILL.md
    preset 产物 运行 / 预览 部署器
    node(默认) Node.js HTTP 服务:node .cell/output/server/index.mjs cell preview 用 Node.js 运行 无,产物自行部署
    cloudflare Cloudflare Workers:server/worker.mjs + wrangler.json,前端作为静态资源 cell preview 用 wrangler dev 在本机的 workerd 中运行 cloudflare(Wrangler)
    cli Node.js 命令行程序:node .cell/output/server/index.mjs 启动应用但不起服务,由组件(如 ApplicationLifecycle)完成工作;不需要 @celljs/express-adapter,也不报缺少入口 cell preview 用 Node.js 运行,继承当前终端 无
    fc 阿里云函数计算 3.0 自定义运行时:产物加 bootstrap 启动脚本,前端由服务端从 public/ 返回 Node.js 运行 fc(函数计算 API)
    scf 腾讯云 SCF Web 函数:产物加 scf_bootstrap Node.js 运行 scf(云函数 API)
    lambda AWS Lambda + 函数 URL:产物加 server/lambda.mjs 处理器 Node.js 运行 lambda(AWS API)
    vercel Vercel Build Output API:.vercel/output,前端在 CDN,服务端是一个函数 Node.js 运行函数的 bundle,前端取自 static/ vercel(Vercel CLI)

    每个 preset 的选项写在 cell.config.ts 里与 preset 同名的字段(如 fc: { region: 'cn-shanghai' }),按 preset 的 schema 校验,未知选项报 CELL_CONFIG_INVALID;切换 preset 时其他 preset 的字段保留不报错。

    cell build --preset cloudflare          # 构建到 .cell/output
    cell preview # wrangler dev,在 workerd(Cloudflare 的运行时)中运行,默认 8787 端口
    cell deploy --preset cloudflare --dry-run # 构建并执行 wrangler deploy --dry-run,输出计划,不上传
    cell deploy --preset cloudflare # 构建并部署,输出 workers.dev 地址
    • 运行方式:Cell 后端(Express)运行在 Workers 的 node:http 服务端上(需要 nodejs_compat),由 @celljs/express-adapter 的 http 入口提供,与 node preset 相同。前端(public/)由 Cloudflare 作为静态资源直接返回,只有不匹配静态文件的请求进入 Worker。产物只支持 ESM,--format cjs 报 CELL_CONFIG_CONFLICT。
    • 启动时机:Workers 只允许在模块加载阶段生成代码(new Function,Express 的依赖会用到),只允许在处理请求时做 I/O。所以应用的模块在 Worker 启动时加载,Application.start() 和 onStart 在第一个请求时执行(ApplicationHost.beforeStart)。模块加载失败会让 Worker 启动失败,wrangler dev / wrangler deploy 直接报出。
    • Cloudflare 的配置写在项目根目录的 wrangler.jsonc 或 wrangler.json(可选,按 Cloudflare 文档的写法):name、compatibility_date、vars、KV / D1 / R2 等绑定、routes 都在这里。构建时 Cell 以它为基础生成 .cell/output/wrangler.json,并设置:main(项目里写了会被忽略并警告)、有前端时的 assets.directory、compatibility_flags 里的 nodejs_compat。没有配置文件时,name 取自 package.json 的包名(如 @acme/shop → acme-shop),compatibility_date 默认 2026-03-17,这也是允许的最早日期(node:http 服务端与 node:tty 从这天起默认可用)。wrangler.toml 不支持,请改写成 wrangler.jsonc。
    • 单页应用:有前端时默认 assets.not_found_handling: "single-page-application":浏览器导航到不存在的路径时由 Cloudflare 返回 index.html(与 Node.js 上 @celljs/serve-static 的 spa 一致),API 等其他请求仍进入 Worker;在 wrangler.jsonc 里写了 not_found_handling 就以项目为准。Worker 里没有前端文件,@celljs/serve-static 发现没有前端目录时直接放行,未知路径得到正常的 404。
    • 自定义域名:域名的 DNS 托管在 Cloudflare 时,在 wrangler.jsonc 里写 "routes": [{ "pattern": "app.example.com", "custom_domain": true }],部署时 Cloudflare 自动创建 DNS 记录和证书,deployment.url 报告这个域名。国内网络无法访问 *.workers.dev,面向国内访问时要绑定自定义域名。
    • 应用配置:vars 和 secrets(wrangler secret put)进入 process.env,所以 cell.yml 里的 ${env.X} 和 CELL_BACKEND__* 变量照常生效。
    • Wrangler:不是 Cell 的依赖。项目装了 wrangler 就用项目的,否则由 npx --yes wrangler@4 在第一次使用时安装(npm 缓存)。凭据由 Wrangler 管理:设置 CLOUDFLARE_API_TOKEN(必要时加 CLOUDFLARE_ACCOUNT_ID),或执行一次 npx wrangler login。也可以不用 cell deploy,直接执行 npx wrangler deploy --config .cell/output/wrangler.json。
    • Workers Builds(Cloudflare 的 CI,设置 WORKERS_CI=1)里自动选用 cloudflare preset:构建命令 npx cell build,部署命令 npx cell deploy --skip-build。
    • wrangler dev 会在项目根目录创建 .wrangler/,请加入 .gitignore。

    三个函数平台的做法相同:Cell 服务端原样运行,产物目录整体打成 zip 作为函数代码;部署器直接调用云 API(请求签名自己实现:阿里云 ACS3、腾讯云 TC3、AWS SigV4),不需要云 SDK 或云厂商 CLI。函数名默认取包名(@acme/shop → shop),可用 name 指定;env 写入函数的环境变量(另带 NODE_ENV=production),cell.yml 里的 ${env.X} 和 CELL_BACKEND__* 照常生效。

    preset 运行方式 选项 凭据(环境变量) 部署结果
    fc custom.debian10 运行时,bootstrap 用镜像自带的 Node.js 20(node: '18' 可选)在 9000 端口(FC_SERVER_PORT)启动服务 name、region(默认 ALIBABA_CLOUD_REGION_ID 或 cn-hangzhou)、node、memory(MB,默认 1024)、cpu(默认按内存 2 GB/核)、timeout(默认 60)、concurrency(单实例并发,默认 20)、env ALIBABA_CLOUD_ACCESS_KEY_ID、ALIBABA_CLOUD_ACCESS_KEY_SECRET(可选 ALIBABA_CLOUD_SECURITY_TOKEN) 创建或更新函数,没有时创建匿名 HTTP 触发器 http(已有的触发器不改),返回 fcapp.run 地址
    scf Web 函数(Type: HTTP),scf_bootstrap 用运行时的 Node.js 18(runtime: 'Nodejs16.13' 可选)在 9000 端口启动服务;只有 /tmp 可写 name、region(默认 TENCENTCLOUD_REGION 或 ap-guangzhou)、namespace(默认 default)、runtime、memory(默认 512)、timeout(默认 60)、env TENCENTCLOUD_SECRET_ID、TENCENTCLOUD_SECRET_KEY(可选 TENCENTCLOUD_SESSION_TOKEN) 创建或更新函数(先代码后配置,等待状态变为 Active),没有时创建公网、免鉴权的函数 URL
    lambda nodejs22.x,初始化阶段在回环端口启动服务,server/lambda.handler 把函数 URL / HTTP API(payload 2.0)事件转成请求,响应以 base64 返回,多个 Cookie 放在 cookies name、region(默认 AWS_REGION 或 us-east-1)、runtime、architecture(x86_64 / arm64)、memory(默认 1024)、timeout(默认 30)、role、env AWS_ACCESS_KEY_ID、AWS_SECRET_ACCESS_KEY(可选 AWS_SESSION_TOKEN),或 ~/.aws/credentials 的 AWS_PROFILE / default 没有 role 时创建或复用执行角色 cell-lambda-execution(只有日志权限);创建或更新函数;没有时创建 AuthType: NONE 的函数 URL 及其两项公开调用权限
    • 代码包直接随请求上传,上限:FC 100 MB、SCF 20 MB、Lambda 50 MB(zip 后),超出报 CELL_DEPLOY_PACKAGE_TOO_LARGE。体积大多来自 build.external 留在 server/node_modules 的包。
    • 没有凭据时 --dry-run 照样给出计划(动作为 deploy,并警告不知道函数是否已存在);有凭据时查询云端,动作是 create 或 update。实际部署缺凭据报 CELL_DEPLOY_CREDENTIALS_MISSING,云 API 的错误报 CELL_DEPLOY_API_ERROR / CELL_DEPLOY_UNAUTHORIZED,消息里带云厂商的错误码和请求 ID。
    • 函数计算的默认域名 fcapp.run 会让浏览器下载 HTML 页面,网页应用请绑定自定义域名;API 不受影响。
    • 镜像里的 Node.js 较旧(FC 20.10、SCF 18.15):服务端 bundle 自带 import.meta.dirname / filename 的补丁。
    cell build --preset vercel     # .vercel/output(Build Output API v3)
    cell preview # Node.js 运行函数的 bundle,前端取自 .vercel/output/static
    cell deploy --preset vercel # vercel deploy --prebuilt,不在 Vercel 上再构建
    • 前端放在 static/ 由 Vercel CDN 返回(/assets/* 带一年的 immutable 缓存头);其他请求进入函数 functions/index.func(nodejs22.x),函数里的 Cell 服务端处理 API,并用其中的 public/index.html 做单页回退。vercel build 留在 .vercel/output 的文件在构建时清除。
    • 选项:project(默认取包名)、scope(团队)、environment(production 默认 / preview)、runtime、memory、maxDuration、regions(逗号分隔)。输出目录固定 .vercel/output(--out-dir 到别处时部署报 CELL_DEPLOY_OUTPUT_MISMATCH);不接受 --single / --compile。
    • Vercel CLI 不是依赖:项目装了就用项目的,否则 npx --yes vercel@65。凭据:VERCEL_TOKEN,或执行一次 npx vercel login;项目不存在时自动创建(--create-if-missing)。
    • Vercel 的构建环境(VERCEL=1)里自动选用 vercel preset。.vercel/ 请加入 .gitignore。
    选项 说明
    --preset <name> 用哪个 preset 的入口运行后端,默认 node
    -m, --mode <mode> 额外的 mode,可重复;development 总是自动加上
    -p, --port <port> 端口,默认取 cell.server.port(考虑 CELL_BACKEND__SERVER__PORT),否则 3000;0 表示随机端口
    --host <host> 监听地址,默认取 cell.server.host,否则 127.0.0.1
    • 一个端口:Vite 提供前端页面和模块(HMR),/favicon.ico 与组件的 assets 和构建产物里的位置一致,其余请求交给后端。
    • 后端不打包,在 Vite 的 server 环境里由 module runner 加载:Cell 包和项目源码经过 Cell 插件(生成的 DI 容器与配置写到 .cell/generated/),其他依赖由 Node 直接加载。入口通过 ApplicationHost(@celljs/core)把请求处理函数交给 cell dev,不自己监听端口。
    • 后端用到的文件变化时:先停止旧应用(触发 onStop),再从新的模块重新启动,并触发 dev:reload。启动失败时请求返回 500 和 CellError(CELL_DEV_BACKEND_FAILED),保存后自动重试。
    • 项目或组件的 cell*.yml、package.json、cell.config.* 变化时:重新解析工具链并在同一端口重启,再次触发 dev:ready。配置写错时报错并等待下一次修改。
    • 源码里的 require() 和项目内的 CommonJS 文件(如生成的 prisma client)照常可用。
    • POST /_cell/mcp:运行中应用的 MCP 端点(Streamable HTTP,JSON 响应),工具有 get_errors(后端启动错误、失败的重载、5xx 请求、错误日志)、list_routes、list_bindings、get_config(${...} 已求值)、recent_requests、logs。只接受本机来源(无 Origin 或回环地址),其他来源返回 403。
    • --json:就绪时 stdout 输出一行结果(url、port、mode、targets、mcp,后端启动失败时带 backendError),之后应用和 Vite 的输出都走 stderr。收到 SIGINT / SIGTERM 时停止应用并以 0 退出。
    • React Fast Refresh 等框架插件由组件的 toolchain 模块提供(模块宿主完成后);在那之前前端修改会整页刷新,CSS 热替换。
    选项 说明
    --preset <name> 产物形态:node(默认)、cloudflare、cli、fc、scf、lambda、vercel
    -m, --mode <mode> 额外的 mode,读取 cell.<mode>.yml,可重复;production 总是自动加上
    --format <esm|cjs> 服务端产物格式,默认取 preset(node 为 esm)
    --single 前端内嵌进 server/index.mjs:一个文件运行整个应用(见下)
    --compile [bun|node|deno] 编译成一个可执行文件 .cell/output/app,默认 bun(见下)
    --compile-target <target> 交叉编译,交给 bun(如 bun-linux-x64)或 deno(如 x86_64-unknown-linux-gnu)
    --sourcemap 生成 source map
    --out-dir <dir> 输出目录,默认 .cell/output

    单文件(--single):先构建前端,再把 public/ 的全部文件(页面、脚本、favicon、组件的 assets)以 base64 写进服务端 bundle,启动时注册到 Symbol.for('@celljs/serve-static/assets'),@celljs/serve-static 从内存返回它们(Content-Type、ETag / 304、Cache-Control 与从磁盘时一致,单页应用回退到 index.html)。产物只有 server/index.mjs 和 manifest.json(single: true,没有 public),把这一个文件拷到任意目录用 node index.mjs 即可运行。项目只有后端时与不加 --single 相同(会提示);build.external 等留在 server/node_modules 的包仍要放在它旁边。也可在 cell.config.ts 写 build: { single: true }。

    可执行文件(--compile):在单文件 bundle 的基础上编译成 .cell/output/app(Windows 目标为 app.exe),拷到没有 Node.js 和 node_modules 的机器也能运行;manifest.json 记录 executable,cell preview 直接运行它。

    工具 做法 需要
    bun(默认) bun build --compile 本机装有 Bun
    deno deno compile --allow-all 本机装有 Deno
    node Node.js 单可执行应用(SEA):CommonJS bundle 生成 blob,用 npx postject 注入 node 的副本,macOS 上重新签名 产物格式自动为 cjs;第一次使用时 npx 下载 postject;不能交叉编译

    留在 bundle 外的包(build.external、组件的 optionalDependencies,通常是原生模块)无法放进可执行文件,报 CELL_COMPILE_EXTERNALS 并列出它们。cloudflare、vercel preset 的前端由平台托管,不接受 --single / --compile。

    接受与 cell build 相同的 --preset、-m、--format、--out-dir 等选项,描述同样参数下 cell build 会用到的内容;另有:

    选项 说明
    --app-config 同时输出每个目标合并后的应用配置(cell.yml);后端的 ${...} 保持原样,运行时才求值

    只读取 package.json、cell*.yml、cell.config.ts 和 manifest.json,不运行项目代码,不执行 hooks。--json 结果的主要字段:

    字段 内容
    name、version、cellVersion、configFile 项目、CLI 版本、cell.config 文件(相对根目录)
    preset name、source(flag / config / env / ci / default)、entry、format、runtime(workerd 表示 Cloudflare Workers)、deployer、available
    mode、targets、targetSources 生效的 mode;构建目标及其来由(cell.config.ts、default 或声明它的组件)
    build 生效的 format、outDir、external、sourcemap、single、compile
    components 按加载顺序;dir、configFiles 相对根目录,targets / entries / toolchain / optionalDependencies 只在组件声明时出现
    frontend、backend entry、提供入口的 entryComponent、staticModules / modules(DI 模块,按加载顺序)、config(仅 --app-config)
    hooks、modules、moduleOptions cell.config.ts 里的 hooks、modules 条目、toolchain 模块选项的键
    output dir、built,构建过时还有 manifest 里的 preset、format、targets、server、public
    frontend.envOverrides、backend.envOverrides 当前环境里的 CELL_FRONTEND__* / CELL_BACKEND__* 变量:applied(变量 → 配置路径)和 problems(找不到键或类型不符)。没有这类变量时不出现,不输出值

    warnings 会提前指出不起作用或会让 cell build 失败的设置:没有组件提供 preset 的入口、-m 指定的 mode 没有任何 cell.<mode>.yml(附拼写建议)、使用了尚未提供的 single / compile、不生效的 CELL_FRONTEND__* / CELL_BACKEND__* 变量。

    选项 说明
    --preset <name>、-m, --mode <mode> 同 cell build
    --skip <check> 跳过某项检查,可重复;未知名字报 CELL_ARGUMENT_INVALID 并列出可用的检查
    检查 内容
    config 与 cell info 的 warnings 相同:缺少入口(CELL_ENTRY_MISSING)、无效 mode(CELL_MODE_UNKNOWN)、不生效或被遮住的环境变量(CELL_ENV_OVERRIDE_IGNORED / CELL_ENV_OVERRIDE_SHADOWS)、不可用的 single / compile
    types 用项目的 TypeScript 执行 tsc --noEmit -p tsconfig.json,每条诊断带文件、行列和 TSxxxx 码;没有 tsconfig.json 或 typescript 时跳过
    decorators tsconfig 要开启 experimentalDecorators 和 emitDecoratorMetadata(CELL_TSCONFIG_DECORATORS),与构建时的装饰器语义一致
    di 用 cell dev 的方式加载后端 DI 容器(不启动应用),逐个解析绑定:CELL_DI_NO_BINDING、CELL_DI_AMBIGUOUS、CELL_DI_CIRCULAR、CELL_DI_MISSING_INJECT 为错误,带修复建议;只能在注入点或请求中创建的绑定记为 info
    模块注册的检查 toolchain 模块用 addCheck 注册,名字如 typeorm:entities

    --json 结果:passed、summary(errors / warnings / info 计数)、issues(每条带 check、level、code、message,可能有 file、line、column、hint)、checks(每项的耗时、问题数、跳过原因)。不加 --json 时按编译器格式输出 src/a.ts:3:5 error TS2322 …,info 不显示。

    npx @celljs/cli init backend my-app     # 或 fullstack:React 前端 + 后端,经 RPC 调用
    cd my-app && npm install && npx cell agent sync && npx cell dev
    选项 说明
    --name <name> 包名,默认取目录名(转成小写、去掉空格)
    --force 允许写入非空目录(同名文件被覆盖)

    从不提问;目录非空时报 CELL_INIT_NOT_EMPTY,模板不存在时报 CELL_TEMPLATE_NOT_FOUND(带拼写建议)。项目依赖 @celljs/* 的 ^<cli 版本>,测试用 bun test + createTestApp()。为 coding agent 生成:AGENTS.md(Cell 指南,与版本匹配)、.agents/skills/cell/SKILL.md、CLAUDE.md(@AGENTS.md)、.mcp.json(npx cell mcp)。

    把 @celljs/cli 自带的 Cell 指南和已安装组件、toolchain 模块(addDocs 目录)的 AGENTS.md 片段写进 AGENTS.md 的 <!-- cell:begin --> … <!-- cell:end --> 之间(其余内容保持不变;没有标记时追加到末尾),并重写 .agents/skills/cell/SKILL.md。升级 Cell 或增减组件后执行一次。

    cell config get cell.server.port --why
    # cell.server.port (backend) = 8080
    # node_modules/@celljs/web/cell.yml: 3000
    # cell.yml [backend]: 8080
    选项 说明
    -m, --mode <mode> 额外的 mode,可重复
    --target <target> backend 或 frontend,默认有后端时取 backend
    --why 列出设置该值的文件(按合并顺序:所有文件的公共部分在前,目标段 backend: / frontend: 在后,后者覆盖前者)和环境变量

    键可写 a.b.c、items[0].name。--json 结果有 value、layers(file、component、section、value)、env(设置了该键或其上下级的 CELL_<TARGET>__* 变量)、expressions(后端值含 ${...},服务端启动时求值)。键不存在时报 CELL_CONFIG_KEY_NOT_FOUND,带最接近的键。

    cell docs <query> [--limit n]:在各组件的 README.md、docs/ 和模块 addDocs() 的目录里按标题分段检索,返回最匹配的段落和 file:line。

    在 stdio 上运行 MCP 服务器(每行一条 JSON-RPC 消息),直到 stdin 关闭。工具都对应同名命令的 --json 结果:

    工具 对应命令 副作用
    info cell info 只读
    check cell check 只读
    config_get cell config get 只读
    docs_search cell docs 只读
    build cell build 写输出目录
    deploy_plan cell deploy --dry-run 写输出目录,部署器可能联网;不部署

    不提供部署工具:实际部署由人执行 cell deploy。

    之后是 toolchain 模块用 addMcpTool 注册的工具(与内置工具重名的会被忽略并警告);cell.config.*、package.json 或模块文件变化后自动重新加载。每个工具标注 readOnlyHint / openWorldHint;参数按 inputSchema 校验,失败时返回 isError 和 CellError。stdout 只有协议消息,模块和 hooks 的输出都走 stderr。

    在 agent 中配置(项目根目录下运行):

    // Claude Code / Cursor / CodeBuddy:.mcp.json 或 .cursor/mcp.json
    { "mcpServers": { "cell": { "command": "npx", "args": ["cell", "mcp"] } } }
    # Codex:~/.codex/config.toml
    [mcp_servers.cell]
    command = "npx"
    args = ["cell", "mcp"]
    

    cell dev 运行时,另外把 http://127.0.0.1:<port>/_cell/mcp 配成 HTTP 类型的 MCP 服务器即可查看运行中的应用。

    选项 说明
    -p, --port <port> 监听端口,默认取 cell.server.port(3000);等同于设置 CELL_BACKEND__SERVER__PORT。cloudflare 产物传给 wrangler dev --port,默认 8787
    --out-dir <dir> 产物目录,默认 .cell/output

    产物由哪个 preset 构建,就按它的方式运行:node、cli、fc、scf、lambda 用 Node.js 运行 server/index.mjs(标准输入输出继承当前终端),cloudflare 用 wrangler dev,vercel 用 Node.js 运行函数里的 bundle 并从 static/ 返回前端。

    选项 说明
    --preset <name> 部署到哪个平台:cloudflare、fc、scf、lambda、vercel;node、cli 没有部署器,报 CELL_DEPLOY_UNSUPPORTED(构建之前就检查)
    --dry-run 构建并计划,不上传(cloudflare:wrangler deploy --dry-run;fc / scf / lambda:打包并查询函数是否存在;vercel:列出函数和静态文件)
    --skip-build 部署 --out-dir 里已有的产物;产物的 preset 与 --preset 不一致时报 CELL_DEPLOY_OUTPUT_MISMATCH
    -m, --mode <mode>、--sourcemap、--out-dir <dir> 同 cell build

    先 plan 后 apply:计划列出要部署的资源(resources,每项有 type、name、action、details),--dry-run 到此为止。依次触发 deploy:before(闸门,hooks 里的命令失败会取消部署)、deploy:plan、deploy:done 事件。部署工具(Wrangler、Vercel CLI)的输出在 --json 时走 stderr。--json 结果:preset、deployer、dryRun、plan,实际部署时还有 deployment(url,以及 details.versionId)。

    选项 说明
    --root <dir> 项目根目录,默认当前目录
    --json stdout 只输出一行 JSON 结果,其余输出(进度、hook 命令的输出)走 stderr
    -h, --help / -v, --version 帮助 / 版本

    命令从不交互提问。退出码:成功 0,执行失败 1,用法错误(未知命令、选项、取值)2。

    {"schemaVersion":1,"command":"build","ok":true,"root":"/app","preset":"node","format":"esm","mode":["production"],"targets":["backend"],"outDir":".cell/output","entry":"@celljs/express-adapter/lib/node/http-application-entry","durationMs":480,"warnings":[]}
    

    失败时:

    {"schemaVersion":1,"command":"build","ok":false,"error":{"code":"CELL_PRESET_NOT_FOUND","message":"Unknown preset 'nod'. Available: node.","hint":"Did you mean 'node'?","docs":"https://cell.cellbang.com/errors/cell-preset-not-found"},"warnings":[]}
    

    schemaVersion 不变时,字段只增不改。

    可选。只放工具链配置;应用配置(@Value 读取的内容)写在 cell.yml。

    import { defineConfig } from '@celljs/cli';

    export default defineConfig({
    preset: 'node',
    targets: ['frontend', 'backend'],
    modules: ['!@celljs/serve-static', { source: '@x/ui', runtime: false }],
    build: { format: 'esm', external: ['sharp'], sourcemap: false, outDir: '.cell/output' },
    vite: {},
    hooks: { 'build:before': 'prisma generate' },
    });
    字段 说明
    preset 产物形态。优先级:--preset → 本字段 → CELL_PRESET → CI 环境识别 → node
    targets 构建目标。默认 backend 加上组件声明的目标(装了 @celljs/react 会经 @celljs/widget 加上 frontend);写了就完全以它为准
    modules '!包名' 去掉一个组件(连同只经由它引入的依赖);{ source, runtime: false } 去掉它的 DI 模块、保留配置;{ source, toolchain: false } 去掉它的 toolchain 模块;本地路径或包名表示额外加载的 toolchain 模块(见下文)
    build.format esm 或 cjs
    build.external 不内联的包,按依赖关系拷到 server/node_modules
    build.sourcemap、build.outDir 同命令行选项
    build.single、build.compile 单文件全栈 / 可执行文件,尚未提供(CELL_UNSUPPORTED)
    vite 合并进每个环境的 Vite 配置
    hooks 在工具链事件上执行的 shell 命令,见下文

    其他顶层字段是 toolchain 模块的选项,值必须是对象。文件支持 .ts/.mts/.cts/.js/.mjs/.cjs,同时存在多个报 CELL_CONFIG_AMBIGUOUS。命令行参数优先于配置文件。

    cell.yml 里已有的任意键都可以用环境变量覆盖,不用改文件:

    CELL_BACKEND__SERVER__PORT=8080 cell preview      # 服务端启动时应用:cell.server.port
    CELL_FRONTEND__API_BASE=/api cell build # 构建前端时应用:cell.apiBase

    __ 分隔层级,第一段先在顶层找、再到 cell 下找(CELL__… 总是指 cell),一个键只能由一个变量设置,不区分大小写并忽略 _、-;值按原值类型转换(JSON 写法的有限数、true / false、对象和数组用 JSON,原值为 null 时是 JSON 就按 JSON),整体是一个 ${...} 的值保留到求值时再定类型(如 CELL_BACKEND__SERVER__PORT='${env.PORT}'),在 ${...} 求值之前生效。只能覆盖已存在的键,找不到键或类型不符的变量不生效并给出警告:服务端在启动时打印,cell build 检查 CELL_FRONTEND__*,cell info 两种都检查。完整规则见迁移指南 5.3。

    hooks: {
    'build:before': 'prisma generate',
    'output:done': 'cp extra/* "$CELL_OUT_DIR/server/"',
    }
    • 命令经 shell 在项目根目录执行,不读标准输入。PATH 最前面是项目及上级目录的 node_modules/.bin。
    • 环境变量:CELL_EVENT、CELL_PRESET、CELL_MODE(逗号分隔)、CELL_OUT_DIR(输出目录的绝对路径)。
    • cell dev 触发 modules:done → config:resolved → dev:ready,后端重载时 dev:reload,重启时 close 后重新来一遍。
    • cell build 依次触发:modules:done → config:resolved → build:before → 构建 → output:done → close。
    • build:before 是闸门事件:命令非零退出即取消构建(CELL_BUILD_CANCELLED)。其他事件里非零退出报 CELL_HOOK_FAILED。
    • 只接受命令字符串。需要写代码或修改事件对象(build:done、deploy:plan)的扩展写成 toolchain 模块。

    需要写代码的扩展写成 toolchain 模块:默认导出一个工厂函数,拿到 cell 后注册能力(设计见 docs/design/modules.md)。

    // modules/audit.ts,在 cell.config.ts 里写 modules: ['./modules/audit'], audit: { url: '...' }
    import type { CellAPI } from '@celljs/kit';

    export default function (cell: CellAPI) {
    const { url } = cell.options('audit', { url: 'http://localhost:9000' });
    cell.addVitePlugin({ name: 'audit', transform: code => code }, { env: 'server' });
    cell.on('build:done', event => {
    event.files['audit.json'] = JSON.stringify({ url, targets: event.project.targets });
    });
    }
    • 加载顺序固定:依赖里的组件(package.json 的 cell.toolchain,按依赖顺序)→ cell.config.ts 的 modules(本地路径或包名,按书写顺序)。{ source, toolchain: false } 关掉某个组件的模块,'!包名' 连组件一起去掉。
    • 工厂只做注册,不启动进程、端口、监听或定时器:cell info 也会执行工厂。
    • cell.config.ts 里除 preset、targets、modules、build、vite、hooks 之外的顶层字段都是模块选项,必须由某个模块用 options() 或 addConfigSchema() 认领,否则报 CELL_CONFIG_UNKNOWN_OPTION(附拼写建议);addConfigSchema 接受 Standard Schema(zod、valibot 等),不合法报 CELL_CONFIG_INVALID。
    • 工厂抛错报 CELL_MODULE_ERROR(带模块名);默认导出不是函数报 CELL_MODULE_INVALID。cell dev 中通知类事件的处理函数出错只报告不中断,cell build 中任何处理函数出错都失败。
    • 每个模块注册了什么都列在 cell info --json 的 toolchainModules 里。
    API 作用
    command、mode、dev、ci、root、preset、components、logger 只读信息;preset 是命令行 / 配置 / 环境变量里写的名字,解析后的 preset 在 config:resolved 事件里
    options(key, defaults)、addConfigSchema(key, schema) 读并认领 cell.config.ts 的 key 字段(只能在工厂里同步调用)
    updateConfig({ build: { external }, vite }) 追加 external、在项目的 vite 之下合并 Vite 配置(项目优先);应用配置仍写在组件自己的 cell.yml
    addVitePlugin(plugin, { env }) 加 Vite 插件,env 为 client / server 时只作用于前端 / 后端
    addRuntimeModule(path, { target, static })、addVirtualModule(id, code)、setEntry(target, path) 追加 DI 模块、提供虚拟模块、指定入口
    addDevHandler(path, handler)、addWatchFile(path) cell dev 中在后端之前处理某个路径;文件变化时重启
    addPreset(preset)、addOutputFile(path, content) 注册 preset(参与 --preset 和 CI 识别);构建后写入输出目录的文件(build:done 的 event.files 可增删改)
    addCheck(def)、addMcpTool(def)、addDocs(dir) 供 cell check、cell mcp、cell docs 使用
    on(event, handler)、events 订阅工具链事件(组合规则见 modules.md §3.2);模块之间的事件总线
    exec(cmd, args, opts)、resolve(spec) 不经 shell 执行命令;从项目根目录解析模块

    所有失败都以 CellError { code, message, file?, line?, hint, docs } 输出,code 在 4.x 内保持稳定。

    错误码 含义
    CELL_ARGUMENT_INVALID 未知命令、选项或取值(退出码 2)
    CELL_PROJECT_NOT_FOUND、CELL_PACKAGE_JSON_INVALID 根目录没有 package.json、某个 package.json 无法读取
    CELL_CONFIG_LOAD、CELL_CONFIG_AMBIGUOUS cell.config.ts 加载或执行失败、存在多个配置文件
    CELL_CONFIG_INVALID、CELL_CONFIG_CONFLICT 配置字段错误(带字段路径和拼写建议)、选项互相冲突
    CELL_CONFIG_PARSE、CELL_CONFIG_NOT_OBJECT、CELL_CONFIG_EXPRESSION cell.yml 不是合法 YAML、顶层不是映射、${...} 表达式错误
    CELL_COMPONENT_NOT_FOUND、CELL_LOCAL_MODULE_NOT_FOUND modules 里写的组件或本地模块不存在
    CELL_MODULE_NOT_FOUND、CELL_CORE_NOT_FOUND 组件声明的 DI 模块无法解析、项目没有依赖 @celljs/core
    CELL_CORE_EL_MISSING 项目的 @celljs/core 早于 4.1.0,没有构建期求值配置所需的 @celljs/core/el 入口
    CELL_PRESET_NOT_FOUND、CELL_PRESET_DUPLICATE、CELL_PRESET_CYCLE preset 不存在、重名、extends 成环
    CELL_BUILD_FAILED 打包失败,带出错文件和位置
    CELL_BUILD_CANCELLED、CELL_HOOK_FAILED hook 或模块取消了构建、hook 命令失败
    CELL_MODULE_ERROR、CELL_MODULE_INVALID toolchain 模块的工厂或处理函数出错、默认导出不是工厂函数
    CELL_CHECK_FAILED、CELL_DI_MODULE_FAILED 某项检查自身出错、cell check 加载后端 DI 模块失败
    CELL_CONFIG_UNKNOWN_OPTION cell.config.ts 有没有模块认领的选项字段
    CELL_DEV_FAILED、CELL_DEV_BACKEND_FAILED、CELL_DEV_START_TIMEOUT cell dev 无法启动(端口等)、后端启动失败、后端入口超时未就绪
    CELL_DEV_BACKEND_NOT_RUNNING dev MCP 工具需要运行中的后端,但后端启动失败或尚未启动
    CELL_CONFIG_KEY_NOT_FOUND cell config get / get_config 的键不存在
    CELL_COMPILE_TOOL_MISSING、CELL_COMPILE_FAILED --compile 需要的 bun / deno / node 不存在、编译器报错(带输出的最后几行)
    CELL_COMPILE_EXTERNALS、CELL_COMPILE_NO_SERVER 有留在 bundle 外的包、项目没有后端可编译
    CELL_TEMPLATE_NOT_FOUND、CELL_INIT_NOT_EMPTY cell init 的模板不存在、目标目录非空
    CELL_UNSUPPORTED 使用了尚未提供的功能
    CELL_OUTPUT_NOT_FOUND、CELL_PREVIEW_NO_SERVER cell preview / cell deploy --skip-build 前没有构建、产物里没有服务端
    CELL_DEPLOY_UNSUPPORTED、CELL_DEPLOY_OUTPUT_MISMATCH、CELL_DEPLOYER_NOT_FOUND preset 没有部署器、已有产物不是该 preset 构建的、部署器不存在
    CELL_DEPLOY_PLAN_FAILED、CELL_DEPLOY_FAILED、CELL_DEPLOY_CANCELLED 计划失败(如打包失败)、部署失败(凭据问题时 hint 说明如何设置)、hook 或模块取消了部署
    CELL_DEPLOY_CREDENTIALS_MISSING、CELL_DEPLOY_UNAUTHORIZED 没有云平台凭据、凭据无效或权限不足
    CELL_DEPLOY_API_ERROR、CELL_DEPLOY_NETWORK、CELL_DEPLOY_TIMEOUT、CELL_DEPLOY_PACKAGE_TOO_LARGE 云 API 报错(带云厂商错误码和请求 ID)、连不上云 API、等待函数就绪超时、代码包超过直传上限
    CELL_CLOUDFLARE_CONFIG_INVALID、CELL_CLOUDFLARE_CONFIG_UNSUPPORTED、CELL_CLOUDFLARE_COMPATIBILITY_DATE wrangler.json(c) 不是合法 JSON 或字段类型错误、使用了 wrangler.toml、compatibility_date 早于 2026-03-17
    CELL_INTERNAL_ERROR Cell 或模块的缺陷;设置 CELL_DEBUG=1 可看到调用栈
    import { createTestApp } from '@celljs/cli';

    const app = await createTestApp({ root, mode: ['extra'] }); // mode 前面总有 test
    const res = await app.fetch('/users', { method: 'POST', headers: { 'content-type': 'application/json' }, body: '{}' });
    const { UserService } = await app.import('/src/user-service.ts'); // 后端加载的那份模块
    app.get(UserService); // DI 容器里的对象
    await app.close(); // 停止应用(onStop)

    app.get(X) 中测试从项目源码导入的类或 Symbol('X') 与应用里的不是同一个模块实例(应用在 Vite 的 module runner 里),按类名或 symbol 描述匹配;没有或重名时报 CELL_DI_NO_BINDING / CELL_DI_AMBIGUOUS。要拿到应用用的那一份(重名时、或要用模块里的其他导出),用 app.import():项目内的文件写 /src/...,包写包名。

    在测试进程里像 cell dev 一样从源码加载后端,不构建、不监听端口;请求经内存中的 req/res 对象走完整的 HTTP 处理链,fetch 返回标准 Response。启动失败抛 CellError(如 CELL_DEV_BACKEND_FAILED,带出错文件);后端没有 HTTP 入口时 fetch 报 CELL_TEST_APP_NO_HTTP。

    import { CellCli } from '@celljs/cli';

    const code = await new CellCli({ stdout, stderr, env }).run(['build', '--json']);

    也导出 defineConfig、ConfigResolver、PresetRegistry、DeployerRegistry、EventBus、HookRunner 等,用于测试和编写工具。

    CloudApi
    CloudCredentials
    CloudflarePreset
    CloudNames
    FcPreset
    JsonUtil
    LambdaPreset
    PresetOptionsSchema
    PresetOutput
    RequestSigner
    ScfPreset
    ServerlessScripts
    TextUtil
    VercelPreset
    AgentCommand
    AgentGuide
    AwsClient
    BuildCommand
    CellCli
    CheckCommand
    CloudApiError
    CloudflareDeployment
    CodePackage
    Command
    ConfigCommand
    ConfigExplainer
    ConfigFileLoader
    ConfigResolver
    ConfigValidator
    DeployCommand
    DeployerRegistry
    DevActivity
    DevCommand
    DevMcpEndpoint
    DocsCommand
    DocsIndex
    EventBus
    ExecutableCompiler
    FcClient
    FcDeployment
    HookRunner
    InfoCommand
    InitCommand
    LambdaDeployment
    McpCommand
    McpServer
    PresetRegistry
    PreviewCommand
    ProjectChecker
    ProjectInitializer
    ProjectInspector
    ProjectMcpTools
    Reporter
    ScfClient
    ScfDeployment
    Toolchain
    VercelCli
    VercelDeployment
    Wrangler
    WranglerConfig
    ZipWriter
    AgentSyncResult
    BootstrapOptions
    BuildOptions
    BuildResult
    CellCliOptions
    CellConfig
    CheckReport
    CloudIo
    CommandContext
    CompileOptions
    ComponentSummary
    ConfigFlags
    ConfigLayer
    ConfigResolverOptions
    ConfigValue
    CreateTestAppOptions
    DevErrorRecord
    DevLogRecord
    DocsHit
    DocsSection
    DocsSource
    GeneratedWranglerConfig
    GuideSnippet
    HookRunnerOptions
    InitResult
    InspectOptions
    JsonRpcResponse
    LoadedConfigFile
    McpIo
    McpServerOptions
    McpToolResult
    ModuleFilter
    OutputSummary
    PresetDetector
    PresetOutputOptions
    ProjectInfo
    ResolvedBuildOptions
    ResolvedConfig
    SignableRequest
    SourcePosition
    TargetSummary
    TemplateInfo
    ToolchainOptions
    WranglerCommand
    WranglerResult
    Writable
    CellCommand
    CellRunner
    CompileTarget
    EventHandler
    LogLevel
    ModuleEntry
    ModuleSpec
    ParseArgsOptions
    ParsedValues
    TestApp
    ValueSource
    WranglerJson
    BUILTIN_PRESETS
    cliPreset
    cloudflareDeployer
    cloudflarePreset
    DEFAULT_IO
    fcDeployer
    fcPreset
    lambdaDeployer
    lambdaPreset
    nodePreset
    scfDeployer
    scfPreset
    vercelDeployer
    vercelPreset
    createTestApp
    defineConfig
    rfc3986
    TestContainer → TestApp