news 2026/9/8 20:23:14

使用 create-twenty-app 脚手架创建 Twenty 应用:从项目生成、OAuth 认证到首次同步的完整指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
使用 create-twenty-app 脚手架创建 Twenty 应用:从项目生成、OAuth 认证到首次同步的完整指南

使用 create-twenty-app 脚手架创建 Twenty 应用:从项目生成、OAuth 认证到首次同步的完整指南

【免费下载链接】twentyThe open alternative to Salesforce, designed for AI.项目地址: https://gitcode.com/GitHub_Trending/tw/twenty

导读

Twenty 应用不是独立运行的服务,而是一个"寄生"于运行中 Twenty 实例的扩展包:它的对象(objects)、视图(views)、前端组件(front components)、逻辑函数(logic functions)等实体,都需要同步到一个真实的 Twenty 实例中才能被注册、渲染和执行。本指南以 packages/twenty-codex-plugin/skills/create-app/SKILL.md 为核心,结合create-twenty-app脚手架的源码实现,系统讲解如何从零开始生成一个 Twenty 应用项目。读完你将掌握:脚手架工具的全部命令参数、两种连接实例的方式(远程 OAuth 与本地 Docker)、脚手架内部执行步骤与产物结构,以及创建完成后的正确后续动作与故障排查方法。

何时使用 create-app Skill

create-app是 Twenty Codex 插件(packages/twenty-codex-plugin)中的核心 Skill 之一。当用户想要"从零开始"新建一个 Twenty 应用时,应启用该 Skill。SKILL.md 中给出了如下典型触发语句:

  • "I want to build a Twenty app"
  • "scaffold a new Twenty app"
  • "start a new Twenty plugin / extension / integration"
  • "create a CRM extension for Twenty"
  • "set up a Twenty app project"
  • "bootstrap a Twenty app called X"

值得注意的是,create-app只负责"从无到有"的项目生成。Skill 文档明确划定了边界:如果应用已经存在,则不应使用本 Skill,而应切换到其他 Skill —— 使用 develop-app SKILL 添加功能,使用 manage-app SKILL 处理同步、部署与排障,使用 publish-app SKILL 做发布前的准备,使用use-twenty-mcp查询工作区数据。这一分工意味着脚手架是"一次性"操作,且方向不可逆——因此 SKILL 建议在动手前把应用目的、要扩展的标准对象、是否需要自定义对象、是否需要 UI、是否需要工作流或安装后数据填充等内容与用户确认清楚,避免之后反复重建。

前置概念:为什么必须有一个运行中的 Twenty 实例

在开始脚手架之前,需要先向用户解释一个核心事实:Twenty 应用不是独立应用,而是扩展某个运行中 Twenty 实例的包。在开发期间,应用的实体(对象、视图、前端组件、逻辑函数)会被同步到某个 Twenty 实例,在那里完成注册、渲染和执行。如果没有一个已连接的实例,就没有可同步的目标、没有可测试的工作区,也就无法验证应用是否真正可用。

关于 Twenty 应用的工作原理,packages/twenty-codex-plugin/references/concepts/how-apps-work.md 给出了更完整的背景:Twenty 应用是拥有自己package.json、依赖和源码树的 npm 包,运行时不作为独立服务,而是被构建、发布并"安装"进运行中的 Twenty 实例,由实例把实体加载进 schema、在 UI 中渲染前端组件。

应用通常依赖两个 SDK 包:

包名用途典型导入入口
twenty-sdk定义应用实体、访问前端组件运行时 API实体定义走twenty-sdk/definedefineApplicationdefineObjectdefineFielddefineViewdefinePageLayoutdefineFrontComponentdefineNavigationMenuItemdefineLogicFunctiondefineRole等);运行时 API 走twenty-sdk/front-componentnavigateenqueueSnackbaropenSidePanelPageuseSelectedRecordIdsgetApplicationVariable等)
twenty-client-sdk从前端组件访问工作区数据对象查询走twenty-client-sdk/coreCoreApiClient),元数据查询走twenty-client-sdk/metadata

UI 层使用twenty-ui包(从 npm 安装twenty-ui@1.0.0-alpha.1),按子路径导入twenty-ui/inputtwenty-ui/data-displaytwenty-ui/icon等组件。

第一步:选择目标 Twenty 实例(两种模式)

SKILL 默认要求先询问用户是否已有 Twenty 实例 URL;如果没有,则退化为本地 Docker 方案。两种方案的本质区别在于"连接方式":

模式一:已有的 Twenty 实例(默认推荐)

用户提供运行中 Twenty 服务器的 URL(自托管或云,例如https://app.twenty.com)。脚手架通过在该实例上执行OAuth完成认证——它会打开浏览器走 OAuth 流程,随后把凭据作为remote存储到本地配置文件~/.twenty/config.json。该模式适合开发者已经拥有带数据的工作区、希望直接在其上进行开发的情况。

模式二:本地 Docker 实例(兜底方案)

仅在用户没有可用的 Twenty 实例时使用。脚手架通过 Docker 启动一个一次性的本地 Twenty 服务(默认地址http://localhost:2020),用本地服务器的开发 API key 完成认证,并自动创建一个名为local的 remote。该方案要求本机已安装并运行 Docker Desktop。

使用原则:若用户未提供 URL,先询问是否已有实例 URL;只有用户明确表示没有时,才回退到 Docker。不要替用户默认选择。

脚手架命令行参数详解

目录命名规则

脚手架对目录名有严格校验。在 cli.ts 中,目录名必须匹配正则^[a-z0-9-]+$——只能包含小写字母、数字与连字符。如果需要,应把用户输入的名称转换为小写并将空格替换为连字符(源码中通过lodash.kebabcase完成目录归一化,参见 create-app.command.ts)。若校验失败,CLI 会打印错误并以非零码退出。

完整参数表

create-twenty-app的可执行入口位于 packages/create-twenty-app/src/cli.ts,基于commander解析参数。全部 create-time 选项如下:

长选项短选项含义默认值 / 备注
<app-directory>(位置参数)项目目录名必须匹配^[a-z0-9-]+$;省略时以应用名 kebab-case 化生成
--name <name>-n应用名(写入package.jsonname缺省取位置参数目录名,再缺省为my-twenty-app;不可为空字符串
--display-name <displayName>-d展示名缺省由应用名转换而来(见 convert-to-label.ts)
--description <description>应用描述可省略
--url <url>Twenty 服务器 URL缺省为http://localhost:2020;末尾斜杠会被去掉
--api-url <apiUrl>已废弃,请改用--url传入会打印黄色警告
--authentication-method <method>oauthapiKey默认"本地用 apiKey、远程用 oauth"(详见下文)

基础命令形如:

# 已有 Twenty 实例(默认),走 OAuth 认证 npx create-twenty-app@latest <app-name> --url <twenty-instance-url> # 没有实例,本地 Docker 兜底(省略 --url) npx create-twenty-app@latest <app-name>

需要携带应用元数据时,把所有信息一次性传入:

npx create-twenty-app@latest <app-directory> \ --name "<package-name>" \ --display-name "<display-name>" \ --description "<description>"

认证方式自动推导逻辑

认证方式并不完全由参数决定。在 create-app.command.ts 中可以看到如下规则:

  • skipLocalInstance = serverUrl !== DEV_API_URL,即只要显式传入了非本地默认地址的--url,就视为"连接远程实例";
  • 远程实例下,即使显式传--authentication-method apiKey也会被忽略并自动切换到 OAuth(并打印警告"API key authentication is only supported on a local Docker instance");
  • 本地实例下默认走apiKey(使用开发专用 API key),也可显式指定oauth

换言之:apiKey 认证只存在于本地 Docker 开发环境,任何远程/生产实例一律强制 OAuth。同时 CLI 在 cli.ts 会校验--authentication-method只能是oauthapiKey二者之一。

脚手架内部执行全流程(源码级拆解)

CreateAppCommand.execute()把整个流程组织为若干带编号的步骤(步骤总数由 computeTotalSteps 动态计算:基础 4 步 + 本地场景多 1 步服务器启动 + 认证 1 步 + 同步 1 步)。每一步内部都会打印进度并自动完成。结合 SKILL.md 与源码,完整流水线如下:

  1. 校验与创建项目目录validateDirectory()检查目标目录不存在或为空;fs.ensureDir()建目录。
  2. 拷贝基础模板copyBaseApplicationProject()(app-template.ts)把仓库内置模板packages/create-twenty-app/src/constants/template复制到目标目录,并把 npm 发布时会剥离的点文件(gitignore.gitignoregithub.githubyarnrc.yml.yarnrc.yml)改名还原,同时把AGENTS.md镜像为CLAUDE.md
  3. 注入随机唯一标识符:读取src/constants/universal-identifiers.ts,把其中的DISPLAY-NAME-TO-BE-GENERATEDDESCRIPTION-TO-BE-GENERATED占位符替换为用户提供的展示名与描述,把UUID-TO-BE-GENERATED逐一替换为uuid.v4()生成的稳定 UUID。
  4. 更新package.json:写入应用名,并把twenty-sdktwenty-client-sdk的 devDependency 版本锁定为create-twenty-app自身版本(仓库中当前为 2.39.0,见 package.json)。
  5. 安装依赖:启用 corepack、执行依赖安装。
  6. 初始化 GittryGitInit()尝试创建 Git 仓库与首次提交;失败或已在仓库内时优雅跳过。
  7. (仅本地模式)启动 Twenty 服务ensureDockerServer()先在后台docker pull twentycrm/twenty-app-dev:latest,再调用serverStart()拉起一次性容器;Docker 未运行或拉取失败时给出提示并继续(尽量用已有镜像)。
  8. 认证:优先级为"复用已有凭据"→ 按推导出的认证方式执行。源码中:
    • tryExistingAuth()会扫描~/.twenty/config.json中所有 remote,若存在 URL 匹配且 token 有效(能通过/metadatacurrentWorkspace查询)的 remote,直接复用并将其设为默认;
    • OAuth 路径authenticateWithOAuth()按服务器 hostname 派生 remote 名(点号转连字符),打开浏览器完成授权;
    • 本地 apiKey 路径authenticateWithDevKey()使用开发 API key 认证为tim@apple.dev,remote 名为local
  9. 初始同步(安装应用):执行yarn twenty dev --once(一次性同步命令)。SKILL.md 特别强调:脚手架已经执行过首次同步,因此创建完成后不要为了验证而额外运行yarn twenty applyyarn testyarn lint
  10. 打开生成的欢迎页openMainPage()尽力解析工作区前端 URL 与占位页布局 ID 后在浏览器中打开(best-effort,失败不影响创建结果)。

若任一关键环节失败,脚手架会打印可手动补救的提示,例如Run yarn twenty dev --once manually.Run yarn twenty remote:add --url <your-instance-url> manually.。成功结束时,logSuccess()会输出后续步骤指引:cd进入项目 → 若未认证成功则yarn twenty remote:add --url <your-instance-url>yarn twenty dev开始开发 → 打开实例地址。

脚手架产物的目录结构

模板目录见 packages/create-twenty-app/src/constants/template。脚手架完成后,一个典型应用项目结构如下:

my-app/ package.json # 应用元数据、版本、依赖(已注入 twenty-sdk / twenty-client-sdk) .github/workflows/ # CI / CD / Publish 自动化 src/ application-config.ts # defineApplication() —— 应用入口与身份声明 default-role.ts # 默认角色定义 constants/ universal-identifiers.ts # 全部实体的稳定 UUID(脚手架生成,严禁在首次同步后修改) front-components/ main-page.tsx # 占位主页面前端组件 page-layouts/ main-page.page-layout.ts # 占位页布局 navigation-menu-items/ main-page.navigation-menu-item.ts # 占位导航菜单项 public/ # 静态资源(logo、截图、图片) AGENTS.md / CLAUDE.md # AI 协作约定(互为镜像) SETUP.md / CHANGELOG.md / README.md

其中 application-config.ts 调用defineApplication(),引用src/constants/universal-identifiers.ts中生成的APPLICATION_UNIVERSAL_IDENTIFIERAPP_DISPLAY_NAMEAPP_DESCRIPTIONUniversal identifier(通用唯一标识符)是 Twenty 应用的关键设计:每个实体都有稳定的 UUID,它能在重命名、版本升级与重新同步中保持不变;一旦首次同步后就不应再改动,否则会破坏实例上已注册的实体与数据的对应关系。

创建完成后:哪些该做,哪些不该做

脚手架完成意味着应用已创建、已同步、已安装,任务即告结束。SKILL.md 给出了清晰的收尾纪律:

  • 不要在创建后运行任何多余的验证命令(yarn twenty applyyarn testyarn lint等)来"证明"脚手架成功——首次同步已由脚手架完成;仅当用户明确要求时才执行测试,且此时应切换到develop-app/manage-app的指导,使用TWENTY_API_URL=http://localhost:2021对隔离的测试实例运行完整测试套件。
  • 向用户报告"应用创建成功、已可开始开发",然后停止,等待用户的下一步指令。

此外要留意占位页面问题:脚手架会自动生成一个占位页面(src/front-components/main-page.tsx)及其配套的页面布局和导航菜单项。在后续使用develop-app开发时,除非应用确实需要 UI,否则在首次部署前应把这三个文件全部删除,并且不要在占位页面之上继续堆叠额外页面。这是避免把占位内容误部署到真实工作区的关键约定。

Docker 兜底失败的排查

仅当用户选择了本地 Docker 路径且失败原因是"缺少 Docker 或 Docker 未运行"时,才进入本节排查流程。

  • 首选恢复方案:向用户索取一个已有的 Twenty 实例 URL,重新带--url <twenty-instance-url>运行脚手架——该路径完全跳过 Docker;
  • 若用户仍坚持本地路径且 Docker 未安装,引导其安装 Docker Desktop;
  • 若 Docker 已安装但未启动,ensureDockerServer 会打印提示并要求用户先启动 Docker 再重新运行命令;
  • 运行前若检测到 Docker 完全缺失,docker-install.ts 会按平台输出对应的安装指引,并再次建议改用已有实例 URL 的方式。

后续开发路径

只有用户明确提出时才进入后续环节。SKILL.md 规划了清晰的衔接关系:

  • 添加功能(对象、字段、逻辑函数、角色、视图、导航、页面布局、Skills、Agents、前端组件注册)→ 切换到 develop-app SKILL,其配套参考包括 app-structure.md、data-model.md、front-components.md 等;
  • 设计/打磨前端组件 UI→ 参考 front-component-ui.md;
  • 同步实体变更到实例→ 后续对应用实体做任何改动后,使用yarn twenty apply一键构建、部署并安装到当前 active remote(完整同步工作流见 manage-app SKILL 及 cli-and-sync.md);
  • 打包分享yarn twenty app:publish发布到 npm(公开市场)或yarn twenty app:publish --private --remote <name>私有发布;每次发布要求package.json中 semver 版本严格递增,详见 publish-app SKILL 与 prepare-for-app-store.md。

从全局视角看,how-apps-work.md 把应用开发提炼为create → develop → sync → validate → repeat的生命周期循环:create-twenty-app覆盖其中的Create环节;yarn twenty apply承担Sync(本地yarn twenty dev为开发态同步,yarn twenty dev:typecheck负责类型检查);浏览器打开工作区验证渲染与逻辑函数执行则对应Validate。理解这条循环,就能明白为什么脚手架、同步与 Skill 边界会被设计成当前形态——所有命令最终都指向同一个目标:让应用的实体与代码始终与某个运行中的 Twenty 实例保持一致。

【免费下载链接】twentyThe open alternative to Salesforce, designed for AI.项目地址: https://gitcode.com/GitHub_Trending/tw/twenty

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/8 20:20:53

Scikit-learn特征选择实战:从过滤式到嵌入式,避开数据泄漏陷阱

做机器学习项目&#xff0c;数据拿到手我第一件事不是急着调模型&#xff0c;而是先把特征列表摊开看一眼。这个习惯是踩过不少坑攒下来的——几百个特征跑完一版基线&#xff0c;效果不行&#xff0c;你根本分不清是模型的问题、样本的问题&#xff0c;还是特征里混了一堆垃圾…

作者头像 李华
网站建设 2026/9/8 20:18:00

如何快速打造轻量 Windows 11 镜像:tiny11builder 完整实战指南

如何快速打造轻量 Windows 11 镜像&#xff1a;tiny11builder 完整实战指南 【免费下载链接】tiny11builder Scripts to build a trimmed-down Windows 11 image. 项目地址: https://gitcode.com/GitHub_Trending/ti/tiny11builder 一台用了好几年的旧笔记本&#xff0c…

作者头像 李华