Files
twenty/packages/twenty-sdk
martmullandGitHub 40eef5c464 Improve application ast (#17016)
# Summary

- Introduces a new, flexible folder structure for Twenty SDK
applications using file suffix-based entity detection
- Adds defineApp, defineFunction, defineObject, and defineRole helper
functions with built-in validation
- Refactors manifest loading to use jiti runtime evaluation for
TypeScript config files
- Separates validation logic into dedicated module with comprehensive
error reporting

  # New Application Folder Structure

Applications now use a convention-over-configuration approach where
entities are detected by their file suffix, allowing flexible
organization within the src/app/ folder.

  # Required Structure

    my-app/
    ├── package.json
    ├── yarn.lock
    └── src/
        ├── app/
│ └── application.config.ts # Required - main application configuration
└── utils/ # Optional - handler implementations & utilities

  # Entity Detection by File Suffix

    - *.object.ts - Custom object definitions
    - *.function.ts - Serverless function definitions
    - *.role.ts - Role definitions

  # Supported Folder Organizations

  ## Traditional (by type):
    src/app/
    ├── application.config.ts
    ├── objects/
    │   └── postCard.object.ts
    ├── functions/
    │   └── createPostCard.function.ts
    └── roles/
        └── admin.role.ts

  ## Feature-based:
    src/app/
    ├── application.config.ts
    └── post-card/
        ├── postCard.object.ts
        ├── createPostCard.function.ts
        └── postCardAdmin.role.ts

  ## Flat:
    src/app/
    ├── application.config.ts
    ├── postCard.object.ts
    ├── createPostCard.function.ts
    └── admin.role.ts

  # New Helper Functions

  ## defineApp(config)

    import { defineApp } from 'twenty-sdk';

    export default defineApp({
      universalIdentifier: '4ec0391d-...',
      displayName: 'My App',
      description: 'App description',
      icon: 'IconWorld',
    });

  ## defineObject(config)

    import { defineObject, FieldType } from 'twenty-sdk';

    export default defineObject({
      universalIdentifier: '54b589ca-...',
      nameSingular: 'postCard',
      namePlural: 'postCards',
      labelSingular: 'Post Card',
      labelPlural: 'Post Cards',
      icon: 'IconMail',
      fields: [
        {
          universalIdentifier: '58a0a314-...',
          type: FieldType.TEXT,
          name: 'content',
          label: 'Content',
        },
      ],
    });

  ## defineFunction(config)

    import { defineFunction } from 'twenty-sdk';
    import { myHandler } from '../utils/my-handler';

    export default defineFunction({
      universalIdentifier: 'e56d363b-...',
      name: 'My Function',
      handler: myHandler,
      triggers: [
        {
          universalIdentifier: 'c9f84c8d-...',
          type: 'route',
          path: '/my-route',
          httpMethod: 'POST',
        },
      ],
    });

  ## defineRole(config)

    import { defineRole, PermissionFlag } from 'twenty-sdk';

    export default defineRole({
      universalIdentifier: 'b648f87b-...',
      label: 'App User',
      objectPermissions: [
        {
          objectNameSingular: 'postCard',
          canReadObjectRecords: true,
        },
      ],
      permissionFlags: [PermissionFlag.UPLOAD_FILE],
    });

  # Test plan

    - Verify npx twenty app sync works with new folder structure
    - Verify npx twenty app dev works with new folder structure
    - Verify validation errors display correctly for invalid configs
- Verify all three folder organization styles work (traditional,
feature-based, flat)
    - Run existing E2E tests to ensure backward compatibility
2026-01-09 13:06:30 +00:00
..
2025-12-03 15:50:16 +00:00
2026-01-09 13:06:30 +00:00
2026-01-09 13:06:30 +00:00

Twenty logo

Twenty SDK

NPM version License Join the community on Discord

A CLI and SDK to develop, build, and publish applications that extend Twenty CRM.

  • Typesafe client and workspace entity typings
  • Builtin CLI for auth, generate, dev sync, oneoff sync, and uninstall
  • Works great with the scaffolder: create-twenty-app

Prerequisites

Installation

npm install twenty-sdk
# or
yarn add twenty-sdk

Usage

Usage: twenty [options] [command]

CLI for Twenty application development

Options:
  --workspace <name>   Use a specific workspace configuration (default: "default")
  -V, --version        output the version number
  -h, --help           display help for command

Commands:
  auth                 Authentication commands
  app                  Application development commands
  help [command]       display help for command

Global Options

  • --workspace <name>: Use a specific workspace configuration profile. Defaults to default. See Configuration for details.

Commands

Auth

Authenticate the CLI against your Twenty workspace.

  • twenty auth login — Authenticate with Twenty.

    • Options:
      • --api-key <key>: API key for authentication.
      • --api-url <url>: Twenty API URL (defaults to your current profile's value or http://localhost:3000).
    • Behavior: Prompts for any missing values, persists them to the active workspace profile, and validates the credentials.
  • twenty auth logout — Remove authentication credentials for the active workspace profile.

  • twenty auth status — Print the current authentication status (API URL, masked API key, validity).

Examples:

# Login interactively (recommended)
twenty auth login

# Provide values in flags
twenty auth login --api-key $TWENTY_API_KEY --api-url https://api.twenty.com

# Login interactively for a specific workspace profile
twenty auth login --workspace my-custom-workspace

# Check status
twenty auth status

# Logout current profile
twenty auth logout

App

Application development commands.

  • twenty app sync [appPath] — One-time sync of the application to your Twenty workspace.

  • Behavior: Compute your application's manifest and send it to your workspace to sync your application

  • twenty app dev [appPath] — Watch and sync local application changes.

    • Options:
      • -d, --debounce <ms>: Debounce delay in milliseconds (default: 1000).
    • Behavior: Performs an initial sync, then watches the directory for changes and re-syncs after debounced edits. Press Ctrl+C to stop.
  • twenty app uninstall [appPath] — Uninstall the application from the current workspace.

    • Note: twenty app delete exists as a hidden alias for backward compatibility.
  • twenty app add [entityType] — Add a new entity to your application.

    • Arguments:
      • entityType: one of function or object. If omitted, an interactive prompt is shown.
    • Options:
      • --path <path>: The path where the entity file should be created (relative to the current directory).
    • Behavior:
      • object: prompts for singular/plural names and labels, then creates a new object definition file.
      • function: prompts for a name and scaffolds a serverless function file.
  • twenty app generate [appPath] — Generate the typed Twenty client for your application.

  • twenty app logs [appPath] — Stream application function logs.

    • Options:
      • -u, --functionUniversalIdentifier <id>: Only show logs for a specific function universal ID.
      • -n, --functionName <name>: Only show logs for a specific function name.

Examples:

# Start dev mode with default debounce
twenty app dev

# Start dev mode with custom workspace profile
twenty app dev --workspace my-custom-workspace

# Dev mode with custom debounce
twenty app dev --debounce 1500

# One-time sync of the current directory
twenty app sync

# Add a new object interactively
twenty app add

# Generate client types
twenty app generate

# Watch all function logs
twenty app logs

# Watch logs for a specific function by name
twenty app logs -n my-function

Configuration

The CLI stores configuration per user in a JSON file:

  • Location: ~/.twenty/config.json
  • Structure: Profiles keyed by workspace name. The active profile is selected with --workspace <name>.

Example configuration file:

{
  "profiles": {
    "default": {
      "apiUrl": "http://localhost:3000",
      "apiKey": "<your-api-key>"
    },
    "prod": {
      "apiUrl": "https://api.twenty.com",
      "apiKey": "<your-api-key>"
    }
  }
}

Notes:

  • If a profile is missing, apiUrl defaults to http://localhost:3000 until set.
  • twenty auth login writes the apiUrl and apiKey for the default profile.
  • twenty auth login --workspace custom-workspace writes the apiUrl and apiKey for a custom custom-workspace profile.

Troubleshooting

  • Auth errors: run twenty auth login again and ensure the API key has the required permissions.
  • Typings out of date: run twenty app generate to refresh the client and types.
  • Not seeing changes in dev: make sure dev mode is running (twenty app dev).

Contributing