首页
/ Twenty create-twenty-app 脚手架 CLI 深度解析:从一条命令到可运行的 Twenty 应用项目

Twenty create-twenty-app 脚手架 CLI 深度解析:从一条命令到可运行的 Twenty 应用项目

2026-09-05 12:40:33作者:幸俭卉

create-twenty-app 是 Twenty CRM 官方提供的应用开发脚手架 CLI,一条 npx 命令即可完成 Twenty 应用项目的创建、依赖安装、本地 Twenty 服务器(Docker)启动与开发者认证。本文以仓库中的 packages/create-twenty-app/README.md 为主体骨架,结合 CLI 入口核心命令实现项目模板 的源码,完整还原这个脚手架的每个参数、每条流水线步骤与认证策略,读完你可以独立搭建 Twenty 应用开发环境并理解脚手架背后的每一步实现。

一、create-twenty-app 是什么

根据 README 的定位,这是 “The official scaffolding CLI for building apps on top of Twenty CRM”——构建 Twenty 应用的官方脚手架,生成的项目基于 twenty-sdk 并自带预配置的 twenty CLI。执行一次脚手架命令后,它会做三件事:

  1. 创建一个新 TypeScript 项目,内置 lint、测试配置和预配置的 twenty CLI;
  2. 通过 Docker 启动一个本地 Twenty 服务器(自动拉取最新镜像);
  3. 使用开发 API Key 完成认证。

package.json 可以看到,该包当前版本为 2.38.0,运行环境要求 Node.js ^24.5.0 与 Yarn ^4.0.2,MIT 协议。构建产物是一个单文件 CLI(bin: dist/cli.cjs),因此可以直接通过 npx create-twenty-app@latest 运行,无需预先安装。

二、快速上手:三条命令跑通本地开发环境

README 给出的 Quick start 是最小可用路径:

npx create-twenty-app@latest my-twenty-app
cd my-twenty-app
yarn twenty dev

各步骤的实际含义(结合源码与 模板 SETUP.md):

  • npx create-twenty-app@latest my-twenty-appmy-twenty-app 是位置参数(目标目录名)。命令会依次完成脚手架复制、yarn install、Git 初始化、Docker 服务器启动、认证和一次应用同步(yarn twenty dev --once);
  • cd my-twenty-app:进入生成项目;
  • yarn twenty dev:启动开发模式并持续同步代码到 Twenty 实例。该命令还会自动生成类型化客户端(typed client),这是 README Troubleshooting 一节明确提到的行为。

前置条件(模板 SETUP.md):

  • Node.js(版本见 .nvmrc);
  • Yarn 4;
  • Docker(用于运行本地 Twenty 服务器)。

默认开发凭据:本地 Twenty 服务器启动后访问 http://localhost:2020,以 tim@apple.dev / tim@apple.dev 登录。

三、CLI 参数全集与输入校验规则

README 的 Options 表 列出的参数如下(完整继承,未删减):

参数 说明
--name <name> 设置应用名称
--display-name <displayName> 设置显示名称
--description <description> 设置应用描述
--url <url> Twenty 工作区 URL(默认 http://localhost:2020
--authentication-method <method> oauthapiKey(本地默认 apiKey,远程默认 oauth

cli.ts 中基于 commander 注册了这些选项,源码中可以看到若干 README 未完全展开的约束,实际使用时应特别注意:

  • 位置参数(目录名)校验:目录名必须匹配 ^[a-z0-9-]+$,即只允许小写字母、数字和连字符,否则直接报错退出(cli.ts#L40-L47)。
  • --name 不允许为空字符串:传入空白 --name 会报 --name cannot be emptycli.ts#L49-L52)。
  • --authentication-method 只接受 oauthapiKey,其他值会报错退出(cli.ts#L54-L64)。
  • --api-url 已废弃:仍可使用但会打印弃用警告,提示改用 --urlcli.ts#L22cli.ts#L66-L70)。
  • URL 尾部斜杠会被自动去除serverUrl = (options.url ?? options.apiUrl)?.replace(/\/+$/, '')cli.ts#L72)。
  • 支持 -v, --version 查看版本、-h, --help 查看帮助。

关于“本地/远程”的判定逻辑:CreateAppCommandDEV_API_URL(即 http://localhost:2020,定义于 dev-api-key.ts)作为分界线——--url 等于该默认值时走本地 Docker 流程,否则视为远程实例并跳过本地服务器启动(skipLocalInstance)。若连接远程实例时显式指定 apiKey,CLI 会打印警告并强制切换为 OAuth,因为 API Key 认证只对本地 Docker 实例生效(create-app.command.ts#L57-L67)。

四、脚手架流水线:七个步骤的源码级拆解

npx create-twenty-app 的执行主体是 CreateAppCommand.execute。它把整个过程组织为带 [n/total] 编号的步骤输出,本地流程共 6 步,远程流程 5 步(computeTotalSteps)。

4.1 应用信息推导

getAppInfos 的取值优先级:

  • appName--name ?? 目录参数 ?? my-twenty-app
  • display name--display-name,缺省时由 convertToLabel 从应用名推导(Start Case 后首字母大写,如 my-twenty-appMy Twenty App);
  • appDirectory:指定目录参数时以 INIT_CWD 为基准拼接;否则用 kebabCase(appName) 作为目录名——因此 --name MyApp 会生成 my-app 目录。

目标目录若已存在且非空,会直接抛出 Directory ... already exists and is not emptyvalidateDirectory)。

4.2 Docker 检查与镜像后台预拉取

本地模式下先通过 docker --version 探测 Docker 是否安装(isDockerInstalled)。未安装时按平台打印 Docker 安装指引,并给出替代方案:npx create-twenty-app@latest my-twenty-app --url <your-instance-url> 连接已有实例(getDockerInstallInstructions)。

在确认 Docker 正在运行后,脚手架会在后台并行执行 docker pull twentycrm/twenty-app-dev:latestpullImageInBackground,镜像名见 create-app.command.ts#L27),与项目文件复制、依赖安装并行推进,直到 ensureDockerServer 阶段才 await 拉取结果;拉取失败也不阻塞,会继续尝试使用本地缓存镜像。

4.3 模板复制与文件生成

模板复制由 copyBaseApplicationProject 完成,内部顺序为:

  1. 复制基础模板:从 src/constants/template 整体复制到目标目录;
  2. 重命名 dotfilesgitignore.gitignoregithub.githubyarnrc.yml.yarnrc.yml。源码注释说明原因是 npm 打包时会剥离点文件/点目录,因此模板内以无点文件名存放、复制后再改回(app-template.ts#L44-L60);
  3. 镜像 AGENTS.mdCLAUDE.md,保持单一事实来源(app-template.ts#L62-L73);
  4. 创建空的 public/ 目录
  5. 生成唯一标识符:读取 universal-identifiers.ts,把占位符 DISPLAY-NAME-GENERATED/DESCRIPTION-TO-BE-GENERATED 替换为实际值,并将所有 UUID-TO-BE-GENERATED 逐个替换为新生成的 UUID v4(generateUniversalIdentifiers)。该文件定义了应用、默认角色、主页面前端组件、页面布局、布局 Tab、Widget、导航菜单项等 10 个 *_UNIVERSAL_IDENTIFIER 常量;
  6. 更新 package.json:写入应用名,并把 twenty-sdktwenty-client-sdk 的 devDependency 版本锁定为脚手架自身的版本号updatePackageJson)——这保证生成的应用与创建它的 CLI 版本严格对齐,避免 SDK 行为漂移。

4.4 依赖安装与 Git 初始化

  • 安装步骤先 corepack enableyarn install,两者失败都只告警不中断(install.ts);
  • Git 初始化是尽力而为:tryGitInit 会执行 git init、切到 main 分支、git add -A 并创建 “Initial commit from Create Twenty App” 初始提交;若当前已处于 Git/Mercurial 仓库内则跳过,失败时会清理 .git 目录并返回 false,不影响整体流程。

4.5 启动 Twenty 服务器

ensureDockerServer 再次确认 Docker 在运行后,调用 twenty-sdk/cli 导出的 serverStart 启动服务器(create-app.command.ts#L301-L307),成功则拿到服务 URL。Docker 已安装但未启动时会提示先启动 Docker 再重跑命令。

五、生成的项目里有什么

模板目录 src/constants/template 就是生成项目的完整原型,值得逐一了解:

  • package.jsonname 为占位符 TO-BE-GENERATEDengines 要求 Node ^24.5.0"npm": "please-use-yarn"packageManager 锁定 yarn@4.13.0。预置脚本:yarn twenty(执行 twenty CLI)、yarn lint(oxlint)、yarn typecheck(tsgo)、yarn test(vitest 集成)、yarn test:unit;依赖含 twenty-sdktwenty-client-sdk(版本由脚手架写入)、twenty-ui、React 19、TypeScript 5.9;
  • application-config.ts:用 defineApplication 声明应用的 universalIdentifierdisplayNamedescription,全部引用自 universal-identifiers 常量;
  • 最小可用 UI 骨架main-page.tsx 前端组件、页面布局导航菜单项默认角色,应用同步成功后即在 Twenty 界面可见;
  • 测试基建application-config.test.ts 验证标识符常量已正确生成,另有 global setup 与 schema 集成测试;
  • CI/CD 工作流.github/workflows,模板内存于 github/workflows):ci.yml 在 main 分支与 PR 上启动一个 Twenty 测试实例,然后依次 yarn install --immutable、lint、typecheck、test:unittest(集成测试使用注入的 TWENTY_API_URL/TWENTY_API_KEY);另有 cd 与 publish 工作流;
  • AGENTS.md:为 AI 编码助手提供开发指引,其中最有实操价值的是 yarn twenty dev:add 实体生成命令表——对象、字段、逻辑函数、前端组件、角色、技能、Agent、视图、导航菜单项、页面布局、Tab、命令菜单项、视图字段、连接提供者等 14 类实体各有对应子命令与生成路径,模板建议优先用这些命令创建实体以自动生成所需的 UUID 等元数据。

六、认证机制:先复用、再降级

同步前的认证是三步决策(create-app.command.ts#L134-L148):

  1. 复用已有凭据 tryExistingAuth:遍历本地 CLI 配置中所有 remote,筛选 URL 匹配且持有 token 的项,向 {serverUrl}/metadata 发送 { currentWorkspace { id } } GraphQL 查询验证 token 有效性;成功则设为默认 remote 并直接复用;
  2. OAuth 流程(远程实例或显式指定):authenticateWithOAuth 以 URL 主机名(点号转连字符)推导 remote 名,调用 authLoginOAuth 打开浏览器完成 OAuth;
  3. 开发 API Key(本地默认):authenticateWithDevKey 使用 twenty-sdk/cli 内置的 DEV_API_KEY(见 dev-api-key.ts)以 remote 名 local 登录,成功后输出 Authenticated as tim@apple.dev (development API key)

任一环节失败时 CLI 都会提示手动补救命令:yarn twenty remote:add(或带 --url <your-instance-url>)。

七、应用同步与欢迎页自动打开

认证成功后,脚手架进入“Installing application”步骤,本质是在项目目录内 spawn 一次 yarn twenty dev --oncesyncApplication)把应用同步进 Twenty 实例;同步失败会明确提示手动执行 yarn twenty dev --once

同步成功后还有一个尽力而为的收尾:openMainPage 读取刚生成的 src/constants/universal-identifiers.ts 中的 MAIN_PAGE_LAYOUT_UNIVERSAL_IDENTIFIER,通过 /metadata GraphQL 端点查询工作区前端 URL 与页面布局 ID,拼出 /{frontUrl}/page/{pageLayoutId} 后用 xdg-open(Linux)/open(macOS)/rundll32(Windows)在浏览器打开应用欢迎页。该逻辑对 URL 做了字符集与 http/https 协议白名单校验(sanitizeBrowserUrl),且任何失败都不会导致脚手架整体失败。

八、故障排查:README 清单与源码依据

继承 README Troubleshooting 的三条排查项,并补充源码中的对应机制:

  1. 服务器起不来:先确认 Docker 正在运行(docker info),再看 yarn twenty docker:logs。源码中 Docker 未运行时会打印 “Docker is installed but not running”,此时重跑命令即可(ensureDockerServer);
  2. 认证不生效:运行 yarn twenty remote:add 重新认证——对应源码中认证失败时的黄色提示文案;
  3. 类型未生成:确认 yarn twenty dev 在运行中,该命令会自动生成类型化客户端。

额外注意点:同步步骤失败不等于脚手架失败,可按提示手动执行 yarn twenty dev --once;若目标目录非空会直接中止,可先移走内容或换个目录名。

九、小结

create-twenty-app 用一个约 700 行的核心命令类,把“复制模板 → 生成 UUID → 装依赖 → Git 初始化 → Docker 起服务器 → 认证 → 一次同步 → 打开欢迎页”串成一条带进度编号的流水线,并通过“SDK 版本与脚手架版本锁定”“远程/本地认证策略分流”“全部降级路径可手动补救”三个设计,使 npx create-twenty-app@latest my-app && cd my-app && yarn twenty dev 成为 Twenty 应用开发可预期、可复制的起点。后续开发建议直接参考模板内 AGENTS.mdyarn twenty dev:add 命令表来扩展对象、逻辑函数与布局实体。

登录后查看全文
热门项目推荐
相关项目推荐