Twenty create-twenty-app 脚手架 CLI 深度解析:从一条命令到可运行的 Twenty 应用项目
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。执行一次脚手架命令后,它会做三件事:
- 创建一个新 TypeScript 项目,内置 lint、测试配置和预配置的
twentyCLI; - 通过 Docker 启动一个本地 Twenty 服务器(自动拉取最新镜像);
- 使用开发 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-app:my-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> |
oauth 或 apiKey(本地默认 apiKey,远程默认 oauth) |
cli.ts 中基于 commander 注册了这些选项,源码中可以看到若干 README 未完全展开的约束,实际使用时应特别注意:
- 位置参数(目录名)校验:目录名必须匹配
^[a-z0-9-]+$,即只允许小写字母、数字和连字符,否则直接报错退出(cli.ts#L40-L47)。 --name不允许为空字符串:传入空白--name会报--name cannot be empty(cli.ts#L49-L52)。--authentication-method只接受oauth或apiKey,其他值会报错退出(cli.ts#L54-L64)。--api-url已废弃:仍可使用但会打印弃用警告,提示改用--url(cli.ts#L22 与 cli.ts#L66-L70)。- URL 尾部斜杠会被自动去除:
serverUrl = (options.url ?? options.apiUrl)?.replace(/\/+$/, '')(cli.ts#L72)。 - 支持
-v, --version查看版本、-h, --help查看帮助。
关于“本地/远程”的判定逻辑:CreateAppCommand 以 DEV_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-app→My Twenty App);appDirectory:指定目录参数时以INIT_CWD为基准拼接;否则用kebabCase(appName)作为目录名——因此--name MyApp会生成my-app目录。
目标目录若已存在且非空,会直接抛出 Directory ... already exists and is not empty(validateDirectory)。
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:latest(pullImageInBackground,镜像名见 create-app.command.ts#L27),与项目文件复制、依赖安装并行推进,直到 ensureDockerServer 阶段才 await 拉取结果;拉取失败也不阻塞,会继续尝试使用本地缓存镜像。
4.3 模板复制与文件生成
模板复制由 copyBaseApplicationProject 完成,内部顺序为:
- 复制基础模板:从 src/constants/template 整体复制到目标目录;
- 重命名 dotfiles:
gitignore→.gitignore、github→.github、yarnrc.yml→.yarnrc.yml。源码注释说明原因是 npm 打包时会剥离点文件/点目录,因此模板内以无点文件名存放、复制后再改回(app-template.ts#L44-L60); - 镜像
AGENTS.md到CLAUDE.md,保持单一事实来源(app-template.ts#L62-L73); - 创建空的
public/目录; - 生成唯一标识符:读取 universal-identifiers.ts,把占位符
DISPLAY-NAME-GENERATED/DESCRIPTION-TO-BE-GENERATED替换为实际值,并将所有UUID-TO-BE-GENERATED逐个替换为新生成的 UUID v4(generateUniversalIdentifiers)。该文件定义了应用、默认角色、主页面前端组件、页面布局、布局 Tab、Widget、导航菜单项等 10 个*_UNIVERSAL_IDENTIFIER常量; - 更新
package.json:写入应用名,并把twenty-sdk、twenty-client-sdk的 devDependency 版本锁定为脚手架自身的版本号(updatePackageJson)——这保证生成的应用与创建它的 CLI 版本严格对齐,避免 SDK 行为漂移。
4.4 依赖安装与 Git 初始化
- 安装步骤先
corepack enable再yarn 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.json:
name为占位符TO-BE-GENERATED,engines要求 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-sdk、twenty-client-sdk(版本由脚手架写入)、twenty-ui、React 19、TypeScript 5.9; - application-config.ts:用
defineApplication声明应用的universalIdentifier、displayName、description,全部引用自 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:unit、test(集成测试使用注入的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):
- 复用已有凭据 tryExistingAuth:遍历本地 CLI 配置中所有 remote,筛选 URL 匹配且持有 token 的项,向
{serverUrl}/metadata发送{ currentWorkspace { id } }GraphQL 查询验证 token 有效性;成功则设为默认 remote 并直接复用; - OAuth 流程(远程实例或显式指定):authenticateWithOAuth 以 URL 主机名(点号转连字符)推导 remote 名,调用
authLoginOAuth打开浏览器完成 OAuth; - 开发 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 --once(syncApplication)把应用同步进 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 的三条排查项,并补充源码中的对应机制:
- 服务器起不来:先确认 Docker 正在运行(
docker info),再看yarn twenty docker:logs。源码中 Docker 未运行时会打印 “Docker is installed but not running”,此时重跑命令即可(ensureDockerServer); - 认证不生效:运行
yarn twenty remote:add重新认证——对应源码中认证失败时的黄色提示文案; - 类型未生成:确认
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.md 的 yarn twenty dev:add 命令表来扩展对象、逻辑函数与布局实体。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0623
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00