diff --git a/packages/twenty-docs/developers/extend/apps/getting-started/quick-start.mdx b/packages/twenty-docs/developers/extend/apps/getting-started/quick-start.mdx index 74e15e5f6e..7550d339c8 100644 --- a/packages/twenty-docs/developers/extend/apps/getting-started/quick-start.mdx +++ b/packages/twenty-docs/developers/extend/apps/getting-started/quick-start.mdx @@ -6,7 +6,7 @@ description: Create your first Twenty app in minutes. ## Prerequisites -- **Node.js 24+** — [Download](https://nodejs.org/) +- **Node.js 24.5+** — [Download](https://nodejs.org/) - **Yarn 4** — bundled with Node via Corepack. Enable it: `corepack enable` - **Docker** — [Download](https://www.docker.com/products/docker-desktop/). Needed to run a local Twenty server. Skip if you already have Twenty running elsewhere. @@ -15,7 +15,7 @@ Building a Twenty app has three phases. The scaffolder collapses them into one h | Phase | What you do | Tool | Result | |---|---|---|---| | **1. Scaffold** | Generate the app's source code | `npx create-twenty-app` | A TypeScript project on disk | -| **2. Run a server** | Start a Twenty server to sync into | Docker + `yarn twenty server` | A running Twenty instance | +| **2. Run a server** | Start a Twenty server to sync into | Docker + `yarn twenty docker:start` | A running Twenty instance | | **3. Sync** | Live-sync your code to the server | `yarn twenty dev` | Your changes appear in the UI | --- @@ -28,7 +28,7 @@ Create a new app from the template: npx create-twenty-app@latest my-twenty-app ``` -You'll be prompted for a name and description — press **Enter** for the defaults. This generates a TypeScript project in `my-twenty-app/` with a starter `application-config.ts`, a default role, a CI workflow, and an integration test. +The scaffolder is non-interactive: the directory name becomes the app name. Pass `--display-name` and `--description` to customize the generated metadata (you can also edit it later in `src/constants/universal-identifiers.ts`). This generates a TypeScript project in `my-twenty-app/` with a starter `application-config.ts`, a default role, CI/CD workflows, and an integration test. **After this phase:** you have an app's source code on your machine. It isn't running yet — that's Phase 2. @@ -38,28 +38,14 @@ You'll be prompted for a name and description — press **Enter** for the defaul Your app needs a Twenty server to sync into. The server is a full Twenty instance — UI, GraphQL API, PostgreSQL — running locally in Docker. Your local code uploads its definitions to that server, which makes them appear in the UI. -The scaffolder offers to start one for you: +The scaffolder starts one for you: with Docker running, it pulls the `twentycrm/twenty-app-dev` image, starts it on port `2020`, and authenticates the CLI against the pre-seeded demo workspace (`tim@apple.dev`) — no sign-in required. -> **Would you like to set up a local Twenty instance?** - -- **Yes (recommended)** — pulls the `twentycrm/twenty-app-dev` Docker image and starts it on port `2020`. Make sure Docker is running first. -- **No** — choose this if you already have a Twenty server you want to connect to. You can wire it up later with `yarn twenty remote:add`. - -
- Should start local instance? -
- -Once the server is up, a browser opens for sign-in. Use the pre-seeded demo account: - -- **Email:** `tim@apple.dev` -- **Password:** `tim@apple.dev` +To connect to an existing Twenty server instead, pass `--url `. Remote servers authenticate with OAuth: a browser opens so you can sign in and click **Authorize**, which gives the CLI access to your workspace. (You can also opt into OAuth locally with `--authentication-method oauth` — sign in with `tim@apple.dev` / `tim@apple.dev`.)
Twenty login screen
-Click **Authorize** on the next screen — this gives the CLI access to your workspace. -
Twenty CLI authorization screen
@@ -117,27 +103,31 @@ Click **View installed app** to see the workspace install. The **About** tab sho ### One-shot sync for CI and scripts -Pass `--once` to run a single build + sync and exit — same pipeline, no watcher: +Use `plan` and `apply` to run the same pipeline once, without a watcher: ```bash filename="Terminal" -yarn twenty dev --once +yarn twenty plan # preview the metadata changes without applying them +yarn twenty apply # show the plan, then apply it ``` | Command | Behavior | When to use | |---------|----------|-------------| | `yarn twenty dev` | Watches and re-syncs on every change. Runs until you stop it. | Interactive local development. | -| `yarn twenty dev --once` | Single build + sync, exits `0` on success, `1` on failure. | CI, pre-commit hooks, AI agents, scripted workflows. | -| `yarn twenty dev --once --dry-run` | Builds and prints the metadata changes **without applying them**. | Inspecting what a sync would change before committing to it. | +| `yarn twenty apply` | Single build + sync, exits `0` on success, `1` on failure. Asks for confirmation on destructive changes (pass `--force` to skip). | CI, pre-commit hooks, AI agents, scripted workflows. | +| `yarn twenty plan` | Builds and prints the metadata changes **without applying them**. | Inspecting what a sync would change before committing to it. | -Both modes need an authenticated remote. See [Syncing & recovery](/developers/extend/apps/operations/sync-and-recovery#previewing-changes-dry-run) for more on `--dry-run`. +All modes need an authenticated remote. See [Syncing & recovery](/developers/extend/apps/operations/sync-and-recovery#previewing-changes-plan) for more on `plan`. + + +`yarn twenty dev --once` and `yarn twenty dev --once --dry-run` are deprecated aliases for `yarn twenty apply` and `yarn twenty plan`. + ### Dev mode options | Flag | Description | |------|-------------| -| `--once` | Build and sync once, then exit. | -| `--dry-run` | With `--once`, preview the metadata changes without applying them. Writes nothing. | -| `--debounceMs ` | Set the file-change debounce delay in milliseconds (default: `2000`). | +| `--force` | Apply destructive changes (deletes) without confirmation. | +| `--debounceMs ` | Set the file-change debounce delay in milliseconds (default: `1000`). | | `--verbose` / `--debug` | Show detailed build logs, sync requests, and error traces. | ## What you can build diff --git a/packages/twenty-docs/developers/extend/apps/operations/cli.mdx b/packages/twenty-docs/developers/extend/apps/operations/cli.mdx index cb3c3ac6a5..9045311115 100644 --- a/packages/twenty-docs/developers/extend/apps/operations/cli.mdx +++ b/packages/twenty-docs/developers/extend/apps/operations/cli.mdx @@ -4,7 +4,25 @@ description: yarn twenty commands for executing functions, streaming logs, manag icon: "terminal" --- -Beyond `dev`, `dev:build`, `dev:add`, and `dev:typecheck`, the `yarn twenty` CLI provides commands for executing functions, viewing logs, and managing app installations. +The `yarn twenty` CLI is your interface to everything app-related. Full command list: + +| Command | What it does | Documented in | +|---------|--------------|---------------| +| `dev` | Watch source files and live-sync changes | [Quick Start](/developers/extend/apps/getting-started/quick-start) | +| `plan` | Preview metadata changes without applying them | [Syncing & recovery](/developers/extend/apps/operations/sync-and-recovery#previewing-changes-plan) | +| `apply` | Apply metadata changes after showing the plan | [Syncing & recovery](/developers/extend/apps/operations/sync-and-recovery) | +| `dev:build` | Compile the app and generate the API client (`--tarball` to pack a `.tgz`) | [Publishing](/developers/extend/apps/operations/publishing) | +| `dev:typecheck` | Run TypeScript type checking | [Testing](/developers/extend/apps/operations/testing) | +| `dev:add` | Scaffold a new entity | [Scaffolding](/developers/extend/apps/getting-started/scaffolding) | +| `dev:generate-client` | Regenerate the typed API client | this page | +| `dev:function:exec` / `dev:function:logs` | Execute functions and stream their logs | this page | +| `dev:translations-extract` | Extract translatable strings into `locales/` catalogs | [Translations](/developers/extend/apps/translations/overview) | +| `dev:catalog-sync` | Trigger a marketplace catalog sync | [Publishing](/developers/extend/apps/operations/publishing#how-marketplace-discovery-works) | +| `app:publish` / `app:install` / `app:uninstall` | Release lifecycle | [Publishing](/developers/extend/apps/operations/publishing) and this page | +| `docker:*` | Manage the local Twenty server container | [Local Server](/developers/extend/apps/getting-started/local-server) | +| `remote:*` | Manage server connections | this page | + +Every command accepts `-r, --remote ` to target a specific remote instead of the default one. ## Executing functions (`yarn twenty dev:function:exec`) @@ -20,8 +38,9 @@ yarn twenty dev:function:exec -u e56d363b-0bdc-4d8a-a393-6f0d1c75bdcf # Pass a JSON payload yarn twenty dev:function:exec -n create-new-post-card -p '{"name": "Hello"}' -# Execute the post-install function +# Execute the install hooks yarn twenty dev:function:exec --postInstall +yarn twenty dev:function:exec --preInstall ``` ## Viewing function logs (`yarn twenty dev:function:logs`) @@ -100,6 +119,12 @@ yarn twenty remote:list # Set the active remote yarn twenty remote:use + +# Check that the active remote's authentication is still valid +yarn twenty remote:status + +# Remove a remote +yarn twenty remote:remove ``` Your credentials are stored in `~/.twenty/config.json`. diff --git a/packages/twenty-docs/developers/extend/apps/operations/sync-and-recovery.mdx b/packages/twenty-docs/developers/extend/apps/operations/sync-and-recovery.mdx index f5ed5c0e7b..66ece93b59 100644 --- a/packages/twenty-docs/developers/extend/apps/operations/sync-and-recovery.mdx +++ b/packages/twenty-docs/developers/extend/apps/operations/sync-and-recovery.mdx @@ -15,33 +15,44 @@ For day-to-day local iteration you almost always want `yarn twenty dev`. Deployi | You want to… | Command | Notes | | --- | --- | --- | | Iterate locally with live sync | `yarn twenty dev` | Watches your files and syncs on every change. | -| Sync once and exit (CI, scripts, hooks) | `yarn twenty dev --once` | One build + sync, then exits. | -| Preview changes **without applying them** | `yarn twenty dev --once --dry-run` | Computes and prints the diff; writes nothing. | +| Sync once and exit (CI, scripts, hooks) | `yarn twenty apply` | One build + sync, then exits. Add `--force` to skip the destructive-change confirmation. | +| Preview changes **without applying them** | `yarn twenty plan` | Computes and prints the diff; writes nothing. | | Remove the app from the workspace | `yarn twenty app:uninstall` | Add `--yes` to skip the prompt. | | Ship a tarball to a server | `yarn twenty app:publish --private` | Requires a **strictly higher** `package.json` version — see [Publishing](/developers/extend/apps/operations/publishing). | | Publish to the marketplace (npm) | `yarn twenty app:publish` | — | | Install / upgrade a deployed version | `yarn twenty app:install` | Installs the version currently deployed. | | Wipe the local server and start clean | `yarn twenty docker:reset` | Deletes **all** local data — last resort. | + +`yarn twenty dev --once` and `yarn twenty dev --once --dry-run` still work as deprecated aliases for `yarn twenty apply` and `yarn twenty plan`. + + ### Local sync does not need a version bump The strictly-increasing `version` rule (`VERSION_ALREADY_EXISTS` on deploy, `APP_ALREADY_INSTALLED` / `CANNOT_DOWNGRADE_APPLICATION` on install) applies to **`app:publish` / `app:install`** — the release path. `yarn twenty dev` syncs your manifest in place and never requires a version change, so you don't need to touch `package.json` to iterate. If you find yourself bumping the version to test a local change, you're using the release path when you want the dev loop. ## Reading the sync output -Every sync prints the metadata changes it applied (or would apply, with `--dry-run`): +Every sync prints the metadata changes it applied (or would apply, with `plan`), Terraform-style — one block per entity with its attributes, then a summary line: ```text filename="Terminal" -Metadata changes: 2 created, 1 updated, 1 deleted - created objectMetadata rocket - created fieldMetadata timelineActivities - updated fieldMetadata launchedAt - deleted pageLayout legacyTab -✓ Synced + # objectMetadata "rocket" will be created + + icon = "IconRocket" + + labelSingular = "Rocket" + + ... + + # fieldMetadata "launchedAt" will be updated + ~ isNullable = false -> true + +Plan: 2 to add, 1 to change, 1 to destroy. + +✓ Synced My App (4 files) ``` This is your first diagnostic: it tells you exactly which objects, fields, and layouts changed, so you can confirm a sync did what you expected before checking the UI. +Destructive changes (`to destroy`) are listed with what they drop (e.g. `objectMetadata "auditNote" — drops the table and all its rows`) and require interactive confirmation, or `--force` in scripts. + When a sync fails on a single entity, the error names the offending entity and its `universalIdentifier`, for example: ```text @@ -50,39 +61,42 @@ Migration action 'create' for 'fieldMetadata' (universalIdentifier: 2020...4337) Use that identifier to find the entity in your manifest (and, if needed, in the workspace) instead of guessing which one conflicts. -## Previewing changes (dry run) +## Previewing changes (plan) -`yarn twenty dev --once --dry-run` builds your manifest, asks the server for the migration plan, and prints it — **without applying anything**. It's the safe way to answer "what would this sync change?" before committing to it. +`yarn twenty plan` builds your manifest, asks the server for the migration plan, and prints it — **without applying anything**. It's the safe way to answer "what would this sync change?" before committing to it. ```bash filename="Terminal" -yarn twenty dev --once --dry-run +yarn twenty plan ``` ```text filename="Terminal" Building manifest... -Computing metadata diff (dry run, nothing will be applied)... -Metadata changes: 1 created, 1 updated - created fieldMetadata timelineActivities - updated objectMetadata rocket -✓ Dry run complete for My App — no changes were applied +Computing metadata plan (read-only, nothing will be applied)... + + # fieldMetadata "timelineActivities" will be created + + ... + +Plan: 1 to add, 1 to change, 0 to destroy. + +✓ Plan complete for My App — no changes were applied ``` -A dry run: +A plan: - **Writes nothing** — no metadata migration, no application record update, no default role/tab changes, and no API client generation. - Returns the **same diff** a real sync would apply, so you can review created/updated/deleted entities up front. - Is useful before a risky change, when reviewing an AI-generated change, or in a script that should fail if an unexpected change is about to land. -A dry run only previews **metadata** changes, and it requires the app to have been synced at least once (so the workspace knows about it). If you run it against an app that was never synced, the server reports that the app is not installed — run `yarn twenty dev` once first. +A plan only previews **metadata** changes, and it requires the app to have been synced at least once (so the workspace knows about it). If you run it against an app that was never synced, the server reports that the app is not installed — run `yarn twenty dev` once first. ## Recovery ladder When local metadata looks wrong, escalate in this order and stop as soon as you're unblocked. Each step is more disruptive than the last. -1. **Re-sync.** Run `yarn twenty dev --once` again. Syncs are idempotent — re-running a clean manifest is safe and often resolves a transient hiccup. -2. **Preview the plan.** Run `yarn twenty dev --once --dry-run` to see exactly what the next sync intends to change, without applying it. +1. **Re-sync.** Run `yarn twenty apply` again. Syncs are idempotent — re-running a clean manifest is safe and often resolves a transient hiccup. +2. **Preview the plan.** Run `yarn twenty plan` to see exactly what the next sync intends to change, without applying it. 3. **Read the named error.** If a sync fails, note the metadata type and `universalIdentifier` in the message (see above) and locate that entity in your manifest. A conflict usually points to a duplicated or re-used identifier. 4. **Uninstall and reinstall.** `yarn twenty app:uninstall`, then sync again (`yarn twenty dev`). This rebuilds the app's metadata from a clean slate while keeping the rest of your workspace intact. 5. **Full reset (last resort).** `yarn twenty docker:reset`, then re-seed and re-sync. diff --git a/packages/twenty-docs/developers/extend/apps/tutorials/document-generator/publishing.mdx b/packages/twenty-docs/developers/extend/apps/tutorials/document-generator/publishing.mdx index 0dd05ae0ad..570f45ec4f 100644 --- a/packages/twenty-docs/developers/extend/apps/tutorials/document-generator/publishing.mdx +++ b/packages/twenty-docs/developers/extend/apps/tutorials/document-generator/publishing.mdx @@ -77,10 +77,10 @@ Run the same gates CI does: yarn lint # oxlint yarn typecheck # tsgo yarn test:unit # unit tests -yarn twenty dev --once --dry-run # preview the metadata diff +yarn twenty plan # preview the metadata diff ``` -The dry run prints exactly what would change on the server without applying it — +The plan prints exactly what would change on the server without applying it — a good final sanity check. See [Testing](/developers/extend/apps/operations/testing) and [Syncing & recovery](/developers/extend/apps/operations/sync-and-recovery).