references/architecture.md
# Catalyst Architecture — Service Selection Guide
Use this file when a user asks "which Catalyst service should I use for X?" or is starting a new project and needs to pick the right components. Load it before writing any service-specific code for a new project.
---
## Service Selection Matrix
### Compute
| If you need… | Use | Do NOT use |
|---|---|---|
| Stateless HTTP endpoints, event-driven logic, scheduled jobs, or Zoho service integrations | **Functions** | AppSail |
| A persistent server process, long-running background workers, or a custom Docker container | **AppSail** | Functions |
| Visual workflow orchestration across multiple functions (parallel/sequential) | **Circuits** | Manual function chaining in code — *check DC restriction first* |
**Rule:** Default to Functions. Reach for AppSail only when the process genuinely cannot be stateless. Functions bill per invocation; AppSail bills per instance uptime.
---
### Data Storage
| If you need… | Use | Do NOT use |
|---|---|---|
| Relational data, SQL-style queries (ZCQL), joins, fixed schema, ACID compliance | **Data Store** | NoSQL |
| Flexible/schemaless document data, JSON-heavy payloads, no predefined structure, high write throughput | **NoSQL** | Data Store |
| File/binary storage: images, PDFs, CSVs, uploads | **Stratus** | Data Store, NoSQL |
| Ephemeral key-value data, session tokens, short-lived state (max 48-hour TTL) | **Cache** | Data Store |
---
### Frontend Hosting
| If you need… | Use |
|---|---|
| Static sites or SPAs (React, Next.js, Vue, Angular, Svelte, Astro) | **Slate** |
| Server-rendered or full-stack frameworks with backend | **AppSail** |
---
### Authentication & Identity
| If you need… | Use |
|---|---|
| End-user login/signup for your application | **Authentication** (Catalyst built-in) |
| OAuth tokens for external APIs (Zoho CRM, Zoho Mail, etc.) | **Connections** (part of `catalyst-authentication` skill) |
| Row-level data access control tied to the logged-in user | **Security Rules** + Data Store permissions |
---
### AI / ML
| If you need… | Use | DC restriction |
|---|---|---|
| OCR, face detection, text analytics, object detection, barcode scanning, content moderation | **Zia Services** | US DC only for AutoML; see Never Use table |
| Train a custom ML model on your own data | **QuickML (AutoML)** | Not available in EU, AU, IN, JP, SA, CA |
| Browser automation, web scraping, PDF generation | **SmartBrowz / Browser Logic** | No DC restriction |
---
### Events & Scheduling
| If you need… | Use | Do NOT use |
|---|---|---|
| Trigger logic when data changes in Catalyst services | **Signals** | ~~Event Listeners~~ (deprecated) |
| Run a function on a schedule (cron-style) | **Job Scheduling** | ~~Cron~~ (deprecated) |
| Zoho service integration (Cliq, etc.) | **Integration Functions** | *Check DC restriction first* |
---
## Typical Stack Patterns
### Simple REST API + database
```
Functions (Basic I/O or Advanced I/O)
+ Data Store (relational data)
+ Authentication (if user login needed)
+ API Gateway (rate limiting, routing)
```
**Cost signal:** Within free tier for < ~1K daily active users.
---
### Full-stack web app
```
Slate (React/Next.js frontend)
+ Functions (API backend)
+ Data Store (structured data)
+ Stratus (file uploads)
+ Authentication (user login)
```
**Cost signal:** Free tier covers most hobby projects. DataStore write volume is usually the first paid item.
---
### Persistent Node.js/Python/Java server (Express, FastAPI, Spring Boot)
```
AppSail (managed runtime or Docker)
+ Data Store / NoSQL (data)
+ Stratus (files)
```
**Cost signal:** AppSail bills per GB-hour of instance uptime ($0.08/GB-hour). A 512 MB instance running 24/7 = ~$0.04/day.
---
### File processing pipeline
```
Functions (trigger on upload event via Signals)
+ Stratus (source files + processed output)
+ Data Store (processing metadata/status)
+ Job Scheduling (retry / batch jobs)
```
---
### ML-powered app
```
Functions (API layer)
+ Zia Services (OCR/text analytics/image) — or — QuickML (custom model)
+ Data Store (results/metadata)
+ Cache (cache frequent predictions)
```
**Cost signal:** Zia APIs are $0.001/request. 100 calls/month free. QuickML inference starts at $0.0025/call after 500 free.
---
## DC Availability Quick Reference
Before recommending Circuits, Integration Functions, AutoML, Push Notifications, or Mobile Device Management — confirm the user's DC:
| Service | US | EU | IN | AU | JP | SA | CA |
|---------|----|----|----|----|----|----|-----|
| Circuits | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Integration Functions | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| AutoML (QuickML) | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Push Notifications | ✅ | ❌ | ❌ | ❌ | ✅ | ✅ | ❌ |
| Identity Scanner (Zia) | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ |
| All other services | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
Source: https://docs.catalyst.zoho.com/en/
## Common Errors
| Error | Cause | Fix |
|-------|-------|-----|
| Circuits not visible in console | User is on EU/AU/IN/JP/SA/CA DC | Use function chaining or Job Scheduling instead |
| Integration Functions grayed out | User is on EU/AU/IN/JP/SA/CA DC | Use a Basic I/O function with the Zoho API directly via Connections |
| AutoML not available | User is on EU/AU/IN/JP/SA/CA DC | Use Zia's pre-built ML services (OCR, Text Analytics) which have no DC restriction |
| "File Store not found" error | Deprecated service accessed by pre-Aug 2025 account trying new feature | Migrate to Stratus |
references/cli.md
# CLI Command Reference
Complete reference for the Catalyst CLI (`catalyst` / `zcatalyst`). For official docs see: https://docs.catalyst.zoho.com/en/cli/v1/cli-command-reference/
---
## Table of Contents
1. [Global Options](#global-options)
2. [Authentication & Identity](#authentication--identity)
3. [Token Management](#token-management)
4. [Project Management](#project-management)
5. [Initialization & Setup](#initialization--setup)
6. [Functions](#functions)
7. [Client](#client)
8. [Slate](#slate)
9. [AppSail Setup](#appsail-setup)
10. [Data Store](#data-store)
11. [API Gateway](#api-gateway)
12. [IAC (Infrastructure as Code)](#iac)
13. [Event & Signal Payload Generation](#event--signal-payload-generation)
14. [Configuration](#configuration)
15. [Code Library](#code-library)
16. [Local Development](#local-development)
17. [Deployment](#deployment)
18. [Other Commands](#other-commands)
19. [Safety Rules](#safety-rules)
20. [Troubleshooting](#troubleshooting)
21. [Resource-First Development Order](#resource-first-development-order)
---
## Global Options
These flags can be used with any command:
| Flag | Description |
|------|-------------|
| `-v`, `--version` | Print CLI version |
| `-p`, `--project` | Specify the project ID or name to target |
| `--org` | Specify the organization ID |
| `--token` | Use a Catalyst auth token instead of interactive login |
| `--dc` | Data center region: `us`, `eu`, `in`, `au`, `jp`, `sa`, `ca` |
| `--verbose` | Enable verbose/debug output for troubleshooting |
| `-h`, `--help` | Show help for a command |
| `-ni`, `--non-interactive` | Skip all interactive prompts — requires CLI v1.27.0+. Equivalent env var: `ZCATALYST_NON_INTERACTIVE=1` |
---
## Authentication & Identity
### `catalyst login`
Authenticate with Zoho Catalyst. Opens a browser for OAuth by default.
```bash
catalyst login --dc <dc> -ni # Non-interactive (--dc is REQUIRED in NI mode)
catalyst login # Interactive browser-based login
catalyst login --no-localhost # Use manual code entry (for remote/headless machines)
catalyst login --force # Force re-login even if already authenticated
```
> **NI mode:** `--dc` is required. Valid values: `us`, `eu`, `in`, `au`, `ca`, `sa`, `jp`, `uae`. Logging into a different DC correctly switches the active data center.
### `catalyst logout`
Log out of the current session, clearing stored credentials.
```bash
catalyst logout
```
### `catalyst whoami`
Display the currently logged-in user and associated org details.
```bash
catalyst whoami
```
---
## Token Management
### `catalyst token:generate`
Generate a new auth token for CI/CD or automation.
```bash
catalyst token:generate # Generate a new token
catalyst token:generate --current # Generate token for the current project context
```
### `catalyst token:list`
List all active tokens.
```bash
catalyst token:list
```
### `catalyst token:revoke`
Revoke an existing token.
```bash
catalyst token:revoke
```
---
## Project Management
### `catalyst project:list`
List all projects accessible in the current org.
```bash
catalyst project:list
```
### `catalyst project:use`
Set the active project context for subsequent commands.
```bash
catalyst project:use
```
### `catalyst project:reset`
Clear the current project context.
```bash
catalyst project:reset
```
---
## Initialization & Setup
### CLI Version Pre-flight
All `-ni` (non-interactive) flags require CLI **v1.27.0 or later**. Verify before using any `-ni` command:
```bash
catalyst --version
```
If the version is below 1.27.0, upgrade first:
```bash
npm install -g zcatalyst-cli
```
### `catalyst init`
Initialize a Catalyst project in the current directory. **Supports non-interactive mode in CLI v1.27.0+** — use `--org`, `-p`, and `-ni` flags.
Both `--org` and `-p` are required in NI mode. Always get both IDs before running init:
```bash
# Step 1: get org ID and project ID
catalyst project:list
# Step 2: initialize — both flags required
catalyst init --org <orgId> -p <projectId> -ni
catalyst init --org <orgId> -p <projectId> -ni --force # Re-initialize
```
If `catalyst init --org <orgId> -ni` is run without `-p`, the CLI errors and prints a list labelled `"The following orgs are available:"` — that label is wrong; the list contains **project names and IDs**. Use those IDs as the `-p` value, not as `--org`.
| Flag | Description |
|------|-------------|
| `--project`, `-p` | Project name or ID to link — **required** in NI mode |
| `--org` | Organization name or ID — **required** in NI mode (some setups only enforce this when more than one org is associated with the account, but passing it is always safe) |
| `-ni` | Non-interactive mode (CLI v1.27.0+) |
| `--force` | Overwrite existing `.catalystrc` |
> **NI mode limitation:** only linking an existing project is supported. Creating a new project requires the browser flow — create the project in the Catalyst console first, then run `catalyst init -ni` to link it.
> **NI mode output:** `catalyst init -ni` creates only `.catalystrc`. `catalyst.json` is created by the first feature command — `catalyst functions:add -ni`, `catalyst slate:create -ni`, etc. Its absence after `init -ni` is expected, not an error.
### `catalyst functions:setup`
**DISABLED in non-interactive mode.** Use `catalyst functions:add -ni` instead — it creates the directory structure and adds the function in one step.
### `catalyst functions:add`
Add a new function to the project. **Supports non-interactive mode in CLI v1.27.0+** — use `--name`, `--type`, `--stack`, and `-ni` flags. On older CLI versions the command is fully interactive (arrow-key menus).
```bash
# ✅ Non-interactive (CLI v1.27.0+) — preferred for agents and CI/CD
catalyst functions:add --name <name> --type <type> --stack <stack> -ni
# Examples:
catalyst functions:add --name api --type aio --stack node20 -ni
catalyst functions:add --name scheduler --type cron --stack node20 -ni
catalyst functions:add --name processor --type job --stack python_3_12 -ni
# Interactive fallback (any CLI version)
catalyst functions:add # Arrow-key menus for name, type, stack
```
| Flag | Description |
|------|-------------|
| `--name` | Function name (alphanumeric + underscores) |
| `--type` | Function type: `bio`, `aio`, `event`, `cron`, `job`, `integ`, `browserlogic` |
| `--stack` | Runtime stack (see values below) |
| `--integ-service` | Integration service — **required when `--type integ`**. Valid values: `ZohoCliq`, `Convokraft` |
| `--overwrite` | Overwrite existing function with the same name — **required in NI mode if function already exists** |
| `-ni` | Non-interactive mode (CLI v1.27.0+) |
**`--type` values:**
| Value | Function type |
|-------|--------------|
| `bio` | Basic I/O |
| `aio` | Advanced I/O |
| `event` | Event function |
| `cron` | Cron/scheduled function |
| `job` | Job function |
| `integ` | Integration function (requires `--integ-service`: `ZohoCliq` or `Convokraft`) |
| `browserlogic` | Browser Logic (SmartBrowz) |
**`--stack` values:**
- Node.js: `node24`, `node22`, `node20`, `node18`, `node16`, `node14`, `node12` (prefer `node20` or `node24`)
- Java: `java25`, `java21`, `java17`, `java11`, `java8`
- Python: `python_3_13`, `python_3_12`, `python_3_11`, `python_3_10`
**Legacy fallback (CLI < v1.27.0):** If the user cannot upgrade, ask them to run `functions:add` interactively and provide the name, type, and stack values to enter. Once they complete the interactive run, you can take over for the remaining implementation steps.
### `catalyst client:setup`
Set up the client (frontend) directory in the current project. **Supports non-interactive mode in CLI v1.27.0+** with `--type` and `--name` flags.
```bash
# ✅ Non-interactive (CLI v1.27.0+)
catalyst client:setup --type react --name <name> --flavour js -ni
catalyst client:setup --type react --name <name> --flavour ts -ni
catalyst client:setup --type angular --name <name> --routing --stylesheet scss -ni
catalyst client:setup --type basic --name <name> -ni
# If the client directory already exists, --overwrite is REQUIRED in NI mode
catalyst client:setup --type basic --name <name> --overwrite -ni
# Interactive fallback (any CLI version)
catalyst client:setup
```
| Flag | Description |
|------|-------------|
| `--type` | Client type: `react`, `angular`, `basic` (required for `-ni`) |
| `--name` | Client application name (required for `-ni`) |
| `--flavour` | `js` or `ts` — React only |
| `--routing` | Enable routing — Angular only |
| `--stylesheet` | `css`, `scss`, `sass`, `less` — Angular only |
| `--overwrite` | Overwrite existing client directory — **required in NI mode if client dir already exists** |
### `catalyst appsail:add`
Add an AppSail service. **ALWAYS use flags to avoid interactive prompts.**
`--source` is required and determines the runtime automatically (directory path → managed runtime; Docker image/archive → custom runtime).
```bash
# Catalyst-managed runtime (source is a local directory)
catalyst appsail:add --name <name> --source <dir> --stack <stack>
catalyst appsail:add --name <name> --source <dir> --stack java17 --platform war --overwrite-config
# Custom (Docker) runtime (source is a Docker image or archive)
catalyst appsail:add --name <name> --source <image-or-archive> --port <port>
```
| Flag | NI | Description |
|------|----|-------------|
| `--name` | Required | Service name |
| `--source` | Required | Local source directory (managed) or Docker image/archive (custom) |
| `--stack` | Required — managed runtime only | Runtime stack: `node24`, `node22`, `java25`, `java21`, `python_3_13`, `python_3_12`, `python_3_11`, `python_3_10` |
| `--build` | Optional | Build path relative to source (managed only) |
| `--platform` | Java only | `javase` or `war` |
| `--port` | Custom runtime only | HTTP port |
| `--overwrite-config` | Conditional | Required only to overwrite an existing service config |
---
## Functions
### `catalyst functions:shell`
Open an interactive shell for testing functions locally.
**DISABLED in non-interactive mode.** Use `catalyst functions:execute` to run Event/Cron/Job/Integration functions from automation.
```bash
catalyst functions:shell # Interactive only — not available with -ni
```
### `catalyst functions:execute`
Execute a function locally. Use this instead of `functions:shell` in non-interactive mode.
```bash
catalyst functions:execute # Single function — runs automatically
catalyst functions:execute <function_name> # Required when more than one function exists
catalyst functions:execute <function_name> --input '{"key":"value"}' # Inline JSON input
catalyst functions:execute <function_name> --input payload.json # File input
catalyst functions:execute <function_name> --input - --key myInput # stdin input
```
| Flag | NI | Description |
|------|----|-------------|
| `[function name]` | Conditional — required when more than one function exists | The function to run; auto-selected with a single function |
| `--input <value>` | Optional | Function input — inline JSON, a file path, or `-` for stdin |
| `--key <input key>` | Conditional — required when the function has multiple named inputs | Selects which input to use |
| `--debug` | Optional | Enable debugging |
### `catalyst functions:config`
View or modify function configuration.
```bash
catalyst functions:config # View config
catalyst functions:config --memory # View/set memory allocation
```
### `catalyst functions:delete`
Delete a function.
```bash
catalyst functions:delete <function_name> --local # Remove only from local project (default in NI mode)
catalyst functions:delete <function_name> --remote # ⛔ BLOCKED in NI mode — delete locally only
```
> **NI mode:** `<function_name>` positional argument is required in non-interactive mode — omitting it falls back to an interactive selector.
---
## Client
### `catalyst client:setup`
Initialize the client directory for the project.
```bash
catalyst client:setup
```
### `catalyst client:delete`
Delete the client component.
```bash
catalyst client:delete --local # Remove only from local project (default in NI mode)
catalyst client:delete --remote # ⛔ BLOCKED in NI mode — delete locally only
```
> **NI mode caveat:** `client:delete --local` may still prompt interactively in some CLI versions despite `-ni`. If it does, manually remove the client entry from `catalyst.json` → `client.targets` array and delete the local client directory instead.
---
## Slate
Slate is Catalyst's frontend framework scaffolding system. **NEVER scaffold manually (no `npm create vite`, etc.).** Always use Slate commands. Additional libraries should be installed AFTER scaffolding.
### `catalyst slate:create`
Create a new Slate frontend project.
```bash
# ✅ Non-interactive
catalyst slate:create --name <name> --framework <framework> -ni
```
| Flag | NI | Description |
|------|----|-------------|
| `--name` | Required | Slate app name |
| `--framework` | Required | Framework to use (see table below) |
| `--template <url>` | Optional | Template URL to initialize from |
| `--default` | Ignored | Not applicable in NI mode — ignored with a warning |
#### Framework Values
| Framework Value | Detection Keywords | Build Output Directory |
|----------------|-------------------|----------------------|
| `static` | Plain HTML/CSS/JS | `.` or `public/` |
| `angular` | Angular, @angular/core | `dist/<project-name>` |
| `astro` | Astro | `dist/` |
| `create-react-app` | CRA, create-react-app | `build/` |
| `nextjs` | Next.js, next | `out/` or `.next/` |
| `preact` | Preact | `dist/` |
| `react-vite` | React + Vite | `dist/` |
| `solidjs` | SolidJS, Solid | `dist/` |
| `svelte` | Svelte, SvelteKit | `dist/` or `build/` |
| `vue` | Vue.js, Vue 3 | `dist/` |
| `other` | Custom/unknown | Varies |
#### `dev_command` per Framework (in `cli-config.json`)
| Framework | Dev Command |
|-----------|------------|
| React + Vite | `npx vite --port $PORT` |
| Next.js | `npx next dev --port $PORT` |
| Angular | `npx ng serve --port $PORT` |
| Astro | `npx astro dev --port $PORT` |
| Vue | `npx vite --port $PORT` |
| SolidJS | `npx vite --port $PORT` |
| Preact | `npx vite --port $PORT` |
| Svelte | `npx vite --port $PORT` |
| Create React App | `npx react-scripts start` (PORT env var) |
### `catalyst slate:link`
Link an existing local directory as a Slate project.
```bash
# ✅ Non-interactive
catalyst slate:link --source <path> -ni
catalyst slate:link --source <path> --name <name> --framework <framework> -ni
```
| Flag | NI | Description |
|------|----|-------------|
| `--source` | Required | Path to existing app directory |
| `--name` | Optional | Slate app name |
| `--framework` | Optional | Frontend framework — auto-detected from app if omitted |
| `--template` | Ignored | Not applicable when linking |
| `--default` | Ignored | Not applicable in NI mode |
### `catalyst slate:unlink`
Unlink a Slate project from the Catalyst project.
```bash
# ✅ Non-interactive
catalyst slate:unlink --name <app-name> -ni
catalyst slate:unlink --name <app-name> --remove-source -ni # Also delete source directory
```
| Flag | NI | Description |
|------|----|-------------|
| `--name` | Required | App to unlink — unknown/missing name fails with list of available apps |
| `--remove-source` | Optional | Delete the source directory (kept by default) |
---
## AppSail Setup
AppSail is for deploying full application servers (Express, Spring Boot, Flask, etc.).
**ALWAYS use flags to avoid interactive prompts.**
```bash
# Node.js 18
catalyst appsail:add --name my-api --source ./server --stack node18
# Java 17 WAR
catalyst appsail:add --name my-service --source ./server --stack java17
# Python 3.13
catalyst appsail:add --name my-app --source ./app --stack python_3_13
# With all options
catalyst appsail:add --name my-api --source ./server --stack node18 --build ./build --overwrite-config
```
---
## Data Store
### `catalyst ds:import`
Import data into the Data Store from a CSV file.
```bash
catalyst ds:import data.csv --table <TableName>
catalyst ds:import data.csv --table <TableName> --production
```
### `catalyst ds:export`
Export Data Store tables to CSV.
```bash
catalyst ds:export <TableName>
catalyst ds:export <TableName> --production
```
### `catalyst ds:status`
Check the status of a Data Store import/export operation.
```bash
catalyst ds:status import <jobid>
catalyst ds:status export <jobid>
```
---
## API Gateway
### `catalyst apig:enable`
Enable the API Gateway for the current project.
```bash
catalyst apig:enable
```
### `catalyst apig:disable`
Disable the API Gateway.
```bash
catalyst apig:disable
```
### `catalyst apig:status`
Check API Gateway status.
```bash
catalyst apig:status
```
---
## IAC
Infrastructure as Code for managing project resources declaratively.
### `catalyst iac:pack`
Package the current project state into an IAC archive.
```bash
catalyst iac:pack
```
### `catalyst iac:import`
Import an IAC package into the project.
```bash
catalyst iac:import -n # Import with a specific name
```
### `catalyst iac:export`
Export the project configuration as an IAC package.
```bash
catalyst iac:export # Export development config
catalyst iac:export --production # Export production config (CAUTION: targets live environment)
```
### `catalyst iac:status`
Check the status of an IAC operation.
```bash
catalyst iac:status
```
---
## Event & Signal Payload Generation
Generate sample payload files for testing event listeners, integrations, jobs, and signals.
### `catalyst event:generate`
Generate a sample event payload.
```bash
catalyst event:generate
```
### `catalyst event:generate:integ`
Generate a sample integration event payload.
```bash
catalyst event:generate:integ
```
### `catalyst event:generate:job`
Generate a sample job event payload.
```bash
catalyst event:generate:job
```
### `catalyst signals:generate`
Generate a sample signal payload.
```bash
catalyst signals:generate
```
---
## Configuration
Manage CLI configuration key-value pairs.
### `catalyst config:set`
Set a configuration value.
```bash
catalyst config:set <key> <value>
```
### `catalyst config:get`
Get a configuration value.
```bash
catalyst config:get <key>
```
### `catalyst config:delete`
Delete a configuration key.
```bash
catalyst config:delete <key>
```
### `catalyst config:list`
List all configuration values.
```bash
catalyst config:list
```
---
## Code Library
### `catalyst codelib:install`
Install a code library into the project.
```bash
catalyst codelib:install
```
---
## Local Development
### `catalyst serve`
Start the local development server. Serves functions, client, and AppSail locally.
**IMPORTANT: The `catalyst serve` port is dynamic. Never hardcode the port. Never use Vite's dev server directly -- always use `catalyst serve`.**
```bash
catalyst serve # Start with defaults
catalyst serve --http <port> # Force HTTP on a specific port (stable, recommended)
catalyst serve --http # Force HTTP, dynamic port
catalyst serve --debug # Enable debug mode
catalyst serve --proxy # Enable proxy mode
catalyst serve --only functions # Serve only functions
catalyst serve --only client # Serve only client
catalyst serve --except appsail # Serve everything except AppSail
catalyst serve --no-watch # Disable file watching/hot reload
catalyst serve --no-open # Don't auto-open browser
```
| Flag | Description |
|------|-------------|
| `--http <port>` | Use HTTP on a fixed port — recommended for stable local development (e.g. `--http 3000`) |
| `--debug` | Enable debug/verbose output |
| `--proxy` | Enable proxy mode for API calls |
| `--only <component>` | Serve only the specified component(s) |
| `--except <component>` | Serve everything except specified component(s) |
| `--no-watch` | Disable file watcher / hot reload |
| `--no-open` | Don't open the browser automatically |
---
## Deployment
### `catalyst deploy`
Deploy the project to Catalyst cloud.
> ⚠️ **`catalyst deploy` silently overwrites environment variables** — only values defined in `catalyst-config.json` survive a deploy. Any env vars set through the Console are wiped on every deploy. Keep all env vars in `catalyst-config.json`, not the Console.
```bash
catalyst deploy # Deploy everything
catalyst deploy --only functions # Deploy only functions
catalyst deploy --only client # Deploy only client
catalyst deploy --except appsail # Deploy everything except AppSail
```
#### AppSail Deploy Options
```bash
catalyst deploy appsail
```
#### Slate Deploy Options
```bash
# ✅ Non-interactive — app name is required
catalyst deploy slate <name> -ni
catalyst deploy slate <name> -m "Deployment message" -ni
catalyst deploy slate <name> --production -ni # Deploy to production (CAUTION)
catalyst deploy slate <name> --no-wait -ni # Don't wait for completion
```
| Flag | Description |
|------|-------------|
| `--only <component>` | Deploy only the specified component |
| `--except <component>` | Deploy everything except specified component |
| `-m` | Deployment message (for Slate) |
| `--production` | Deploy to production environment (CAUTION) |
---
## Other Commands
### `catalyst pull`
Pull remote project resources to local.
```bash
# ✅ Non-interactive — feature and resource are required
catalyst pull functions --resource <functionName> -ni
catalyst pull functions --resource <fn1>,<fn2> -ni # Multiple functions
catalyst pull client --resource <version> -ni
catalyst pull client --resource <version> --overwrite -ni # Overwrite existing local files
# If function already exists locally, --overwrite is REQUIRED in NI mode
catalyst pull functions --resource <functionName> --overwrite -ni
```
| Argument/Flag | NI | Description |
|---------------|----|-------------|
| `[feature]` | Required | Feature to pull: `functions`, `client` — one per run |
| `--resource` | Required | Function name(s) or client version to pull (comma-separated for multiple) |
| `--overwrite` | Required in NI if target exists locally | Skips without overwriting and exits with error in NI mode if omitted and target exists |
### `catalyst run-script`
Run a custom script defined in the project.
```bash
catalyst run-script
```
### `catalyst help`
Display help for any command.
```bash
catalyst help
catalyst help <command>
catalyst <command> --help
```
---
## Safety Rules
### Destructive Commands Reference
| Command | Risk Level | What It Does | Safeguard |
|---------|-----------|--------------|-----------|
| `functions:delete --remote` | HIGH | Deletes deployed function | Confirm project first |
| `client:delete --remote` | HIGH | Deletes deployed client | Confirm project first |
| `deploy --production` | HIGH | Pushes to production | Verify project and changes |
| `deploy slate --production` | HIGH | Pushes Slate to production | Verify project and changes |
| `iac:export --production` | MEDIUM | Exports production config | May expose secrets |
| `iac:import` | MEDIUM | Overwrites project resources | Verify package contents |
| `ds:import` | MEDIUM | Overwrites Data Store data | Verify CSV and table |
| `project:reset` | LOW | Clears project context | Re-run `project:use` |
### Critical Rules
- **`--production` flag warning**: Any command with `--production` targets the live production environment. Always double-check the project context before using this flag.
- **Always confirm project before mutating**: Run `catalyst whoami` and verify the project context before running any destructive or deployment command.
- **Exit code 0 ≠ full deploy**: `catalyst deploy` can succeed while silently skipping components. Read the deploy output and confirm every expected component (Functions, Client, Slate, AppSail) is listed before declaring the deploy complete.
- **Functions are packaged flat, one zip per function**: shared local modules are NOT resolved across function directories. Copy (or sync) shared files into every function directory before deploying.
- **CLI tokens are not REST OAuth tokens**: output from `catalyst token:generate` authenticates the Catalyst CLI/automation — it is not a generic `Authorization: Bearer` token for Catalyst REST APIs.
---
## Common Errors
### Common Issues
| Issue | Diagnosis | Solution |
|-------|-----------|---------|
| Login fails | Auth token expired or browser blocked | Run `catalyst login --force` or use `--no-localhost` for headless |
| Wrong project targeted | Stale `.catalystrc` or context | Run `catalyst whoami`, then `catalyst project:use` or `catalyst init` |
| Wrong data center | Mismatched `--dc` flag | Re-login with correct `--dc` (us/eu/in/au/jp/sa/ca) |
| Deploy fails | Missing config, build errors | Check `catalyst.json`, run `catalyst deploy --verbose` |
| `Deploy fails: Invalid input value for name — Cannot have different name than <project-name>` | Client `package.json` `name` field does not match the Catalyst project name | Set `"name"` in `client/<app>/package.json` to exactly match the Catalyst project name (e.g. `"name": "bandwidth-cost"`) |
| `client:delete --local` still prompts despite `-ni` | Known CLI edge case — confirmation prompt not suppressed in some versions | Manually remove the client folder name from `catalyst.json` → `client.targets` array and delete the local directory |
| Env vars missing after deploy | `catalyst deploy` overwrites env vars with `catalyst-config.json` values — Console-set vars are lost | Move all env vars into `catalyst-config.json` before deploying |
| Functions not found | Missing `catalyst-config.json` or wrong directory structure | Verify `functions/<name>/catalyst-config.json` exists |
| Port conflicts | Another process using the port | Stop other servers; `catalyst serve` assigns ports dynamically |
| Function missing from serve output | Node binary path for the function's stack is invalid or not configured | See below — set `node24.bin` (or equivalent stack) via `catalyst config:set` |
| Token expired | Stale auth token | Run `catalyst token:generate` or `catalyst login --force` |
| IAC status stuck | Long-running import/export | Run `catalyst iac:status` to check progress |
| DS import fails | Malformed CSV or schema mismatch | Verify CSV format matches table schema; run `catalyst ds:status` |
| `catalyst functions:execute` runs old code | Stale build artifacts cached in `functions/<name>/.build` | Delete `functions/<name>/.build` and re-run |
| AppSail Docker build fails on macOS | Docker socket points at the wrong provider (Colima vs Docker Desktop) | Set `ZC_DOCKER_SOCK_PATH` (supported since CLI v1.22.0) to the active provider's socket (Colima default: `$HOME/.colima/default/docker.sock`) before deploying |
### Function missing from `catalyst serve` output
If a function doesn't appear in the serve URL table, check the output for:
```
⚠ skipping serve of function [api] since Invalid NodeJS binary path set for stack node24
⚠ functions: No targets are ready to be served in local
✖ Invalid NodeJS binary path set for stack node24
```
Slate and AppSail continue serving normally — only the function is skipped. Fix by pointing the CLI at the actual Node binary:
```bash
catalyst config:set node24.bin=$(which node)
# Verify:
catalyst config:get node24.bin
```
Replace `node24` with the stack value in your function's `catalyst-config.json`.
### Debugging
- **Enable verbose output**: Add `--verbose` to any command for detailed logs.
- **Get command help**: Run `catalyst help <command>` or `catalyst <command> --help`.
---
## Resource-First Development Order
Always follow this order when building a Catalyst project:
1. **Login**: `catalyst login`
2. **Init**: `catalyst init --org <orgId> -p <projectId> -ni` (non-interactive; use MCP tools to get org/project IDs)
3. **Create tables**: Set up Data Store tables (via console or IAC)
4. **Configure permissions**: Set table-level and row-level access
5. **Seed data**: Import initial data with `catalyst ds:import`
6. **Set up compute**: Add functions (`catalyst functions:add --name <n> --type aio --stack node20 -ni`), AppSail (`appsail:add --name <n> --source <dir> --stack node20`), or Slate (`slate:create --name <n> --framework react-vite -ni`)
7. **Write code**: Implement business logic using the Catalyst SDK
8. **Serve locally**: `catalyst serve` (port is dynamic, never hardcode)
9. **Deploy**: `catalyst deploy`
---
External documentation: https://docs.catalyst.zoho.com/en/cli/v1/cli-command-reference/
references/console-ui-guide.md
# Catalyst Console UI Guide
Step-by-step navigation for the most common console tasks.
> **Coverage note:** This guide documents the most commonly needed console flows. The following areas are **not yet documented here** and require consulting the [official Catalyst docs](https://docs.catalyst.zoho.com):
> - Hosted Authentication (OAuth providers, custom login pages)
> - Billing activation and plan upgrades
> - Cache segment creation (Cloud Scale → Cache → New Segment)
> - NoSQL collection and table creation (Cloud Scale → NoSQL)
> - Stratus bucket creation and IAM policy setup (Cloud Scale → Stratus)
> - Connections configuration (Connections → New Connection → OAuth provider setup)
> - Signals and Job Scheduling setup
---
## Finding Project ID and Table ID
### Project ID
1. Open [console.catalyst.zoho.com](https://console.catalyst.zoho.com/baas/index) and click your project
2. Look at the browser URL: `https://console.catalyst.zoho.com/baas/<ORG_ID>/project/<PROJECT_ID>/`
3. `PROJECT_ID` is the numeric segment after `/project/`
### Table ID
1. Console → your project → **Data Store** → click your table
2. Look at the browser URL: `.../datastore/<TABLE_ID>/table`
3. `TABLE_ID` is the numeric segment after `/datastore/`
---
## Creating a Data Store Table with Columns
1. Console → your project → **Data Store**
2. Click **Add Table** (top-right)
3. Enter a **table name** (e.g., `Tasks`) — names are case-sensitive in ZCQL
4. Click **Add Column** for each field you need:
| Column type | SDK type | Notes |
|------------|----------|-------|
| `Text` | string | Default for most string fields |
| `Number` | number | Integer or decimal |
| `Boolean` | boolean | `true`/`false` |
| `Date` | date | Date only (no time) |
| `DateTime` | datetime | Full timestamp |
| `Email` | string | Validated email format |
| `File` | file reference | Link to Stratus/File Store object |
5. Save the table
6. `ROWID` is auto-created as the primary key — you cannot remove it
---
## Enabling App User Insert / Update / Delete (Scopes and Permissions)
By default, App Users (logged-in users) cannot write to Data Store tables. You must enable it explicitly.
1. Console → your project → **Data Store** → click your table
2. Click **Scopes and Permissions** (gear icon or tab, depending on UI version)
3. You'll see a matrix of roles vs operations:
| Row | What it controls |
|-----|-----------------|
| **App User** | Operations available to authenticated end users via Web/Mobile SDK |
| **App Administrator** | Operations available to admin users |
4. Check **Insert**, **Update**, **Delete** checkboxes in the **App User** row as needed
5. Click **Save**
> If you don't enable Insert and try to call `row.insert()` from the Web SDK, you get a 403 error.
---
## Authorized Domains + CORS Toggle
This controls which frontend origins are allowed to call your Catalyst functions via the API gateway.
1. Console → your project → **Settings** (gear icon in sidebar)
2. Click **Authorized Domains**
3. Click **Add Domain**
4. Enter the full origin with protocol: `https://myapp-12345.catalystapps.com`
- Include `https://` — bare domains are rejected
- For local dev, add `http://localhost:3000` separately
5. Toggle **CORS** to **ON** for the domain
6. Click **Save**
> Once a domain is in the Authorized Domains list with CORS enabled, the Catalyst gateway automatically
> injects the correct `Access-Control-Allow-Origin` headers. **You do NOT need CORS code in your functions
> for these production domains.**
---
## Connecting the Catalyst CLI to Your Project
After creating a project in the console, link it to a local directory:
```bash
cd my-app-folder
catalyst init
# or if project already exists:
catalyst project:use "My Project Name"
```
Verify the link:
```bash
cat catalyst.json # should contain project_id and project_key
catalyst whoami # shows logged-in user
```
## Common Errors
| Error | Cause | Fix |
|-------|-------|-----|
| Table ID not visible in URL | Some console versions show it differently | Use MCP tool `CatalystbyZoho_GetTableID` or run `catalyst datastore:list` |
| CORS error despite domain being in Authorized Domains | CORS toggle is OFF, or protocol mismatch (`http` vs `https`) | Ensure toggle is ON; domain must include exact protocol |
| App User Insert returns 403 | Insert not enabled in Scopes and Permissions | Enable Insert for App User in Data Store → table → Scopes and Permissions |
references/project-basics.md
# Catalyst Project Basics — Reference
## Project Constraints (Know Before Creating)
- **First project must be created from the console** — `catalyst init` can create subsequent projects from the CLI, but the very first one must be done at https://console.catalyst.zoho.com.
- **Project name rules** — alphanumeric, underscores (`_`), and hyphens (`-`) only. No spaces or special characters.
- **50-project limit** per account — contact support@zohocatalyst.com to request an increase.
- **Console URL differs by data center:**
- US and others: `https://console.catalyst.zoho.com/baas/index`
- EU: `https://console.catalyst.zoho.eu/baas/index`
- IN: `https://console.catalyst.zoho.in/baas/index`
### "Start Exploring" Requirement
Before any service can be deployed to Production, a user **must click "Start Exploring"** for that service in the Catalyst console. This is a one-time activation per service per project — without it, deploying that service to Production is blocked. This applies to all services: Slate, Functions, AppSail, Data Store, etc.
---
## Project Directory Structure
When `catalyst init` is run, a standard project layout is created:
```
my-catalyst-project/
├── catalyst.json # Auto-generated project config — NEVER create manually
├── .catalystrc # Auto-generated project identity — NEVER create manually
├── functions/ # All server-side functions
│ └── function_name/
│ ├── index.js # Entry point (Node.js)
│ ├── catalyst-config.json # Function-specific config
│ ├── package.json
│ └── node_modules/
├── my-slate-app/ # Slate frontend (PREFERRED for new projects)
│ └── catalyst-config.json
├── client/ # ⚠️ LEGACY — use Slate instead
└── appsail/ # AppSail services (optional)
├── app.js
├── catalyst-config.json
└── package.json
```
Key rules:
- The `functions/` directory name is fixed and cannot be renamed.
- Each function must be in its own subdirectory under `functions/`.
- **For frontends, always use Slate** — do NOT select "Client" during `catalyst init`, it is legacy.
- `catalyst.json` and `.catalystrc` are auto-generated — **NEVER create them manually**.
---
## catalyst.json
Holds deployment configuration. Auto-generated by the CLI.
```json
{
"functions": {
"targets": ["myFunction1", "myFunction2"],
"ignore": [],
"source": "functions"
},
"appsail": {
"targets": ["my-appsail-service"],
"source": "appsail"
},
"slate": [
{ "name": "my-frontend", "source": "/absolute/path/to/client" }
]
}
```
- The `functions` block **must** include `targets`, `ignore`, and `source` or CLI errors.
- Slate `source` **must be an absolute path**.
---
## .catalystrc — Project Identity File
```json
{
"project_id": "YOUR_PROJECT_ID",
"project_domain": "your-app-YOUR_ENV_ID.development",
"env_id": "YOUR_ENV_ID",
"timezone": "Asia/Kolkata"
}
```
Contains `project_id`, `env_id`, `project_domain`, and `timezone`. If missing, `catalyst deploy` fails.
---
## catalyst-config.json for Functions
```json
{
"deployment": {
"name": "my_function",
"type": "advancedio",
"stack": "node20",
"env_variables": {}
},
"execution": {
"main": "index.js"
}
}
```
Valid `type` values (use exactly as shown — do not change this after function creation):
| Function Type | `type` value |
|--------------|-------------|
| Basic I/O | `basicio` |
| Advanced I/O | `advancedio` |
| Cron | `cron` |
| Job | `job` |
| Event | `event` |
| Integration | `integration` |
| Browser Logic | `browserlogic` |
> `browserlogic` — NOT `browselogic`.
Valid `stack` values: `node24` *(recommended)*, `node22`, `node20`, `node18`, `node16`, `node14`, `node12`, `java25`, `java21`, `java17`, `java11`, `java8`, `python_3_13`, `python_3_12`, `python_3_11`, `python_3_10`
---
## Environments
Catalyst has two environments:
1. **Development (sandbox)**: CLI deploys go here. Free to use within limits. Used for testing.
2. **Production**: Requires billing setup. Serves live traffic. Deployed from the console, not CLI.
### Application URL Format
| Environment | URL Pattern | Example |
|-------------|-------------|----------|
| Development | `https://{project-domain}.development.catalystserverless.com` | `https://shipmenttracking-57673975.development.catalystserverless.com` |
| Production | `https://{project-domain}.catalystserverless.com` | `https://shipmenttracking-57673975.catalystserverless.com` |
The project domain is auto-generated when you first host a web client.
### Dev-to-Prod promotion checklist
1. **Verify in Development** — all functions, AppSail, and frontend working correctly.
2. **Set up billing** — Catalyst Console → Settings → Billing.
3. **Deploy to Production** — Console → Deploy → select Production environment.
4. **Update environment variables** — Production uses separate env vars.
5. **Reconfigure social login** — OAuth redirect URLs must point to the Production domain.
7. **Map custom domain** — Console → Domain Mapping → add your production domain.
8. **Test the full flow** — auth, data, file uploads, email — all on the Production URL.
9. **Monitor** — enable APM and Application Alerts for Production.
---
## Catalyst IDs Quick Reference
| ID | What | Where to Find | Format |
|---|---|---|---|
| **Project ID** | Project identifier | Settings → General; `.catalystrc`; `catalyst projects:list` | Numeric string |
| **API Key** | API Gateway auth key | Settings → Environments → General tab | String (common in Dev across all projects; unique per project in Prod) |
| **Table ID** | Data Store table | Cloud Scale → Data Store → click table | Numeric |
| **ROWID** | Data Store row | Auto-assigned; returned in queries | BigInt |
| **Segment ID** | Cache segment | Cloud Scale → Cache → segment list | Numeric |
| **Function ID** | Serverless function | Serverless → Functions → function details | Numeric |
| **Circuit ID** | Circuits workflow | Serverless → Circuits → circuit details | Numeric |
| **Pool ID** | Job Scheduling pool | Job Scheduling → pool details | Numeric |
| **Bot ID** | ConvoKraft bot | ConvoKraft → bot details | String |
| **ZUID** | Zoho user (per-app) | Auth API responses; Authentication → Users | Numeric string |
| **User ID** | Catalyst-only user | Auth API responses; Authentication → Users | Numeric |
| **Org ID / ZAAID** | Organization | Auth API responses; Authentication → Users | Numeric string |
| **Bucket Name** | Stratus bucket | Cloud Scale → Stratus | String |
| **Collection Name** | NoSQL collection | Cloud Scale → NoSQL | String |
### Table / Column IDs
```javascript
// Access by name (case-sensitive — must match console exactly)
const table = catalystApp.datastore().table('Employees');
// Access by ID (from Console → Data Store → click table)
const table = catalystApp.datastore().table(1510000000110121);
```
### Segment ID (Cache)
```javascript
// Segment ID from Console → Cache → segment list
const segment = catalystApp.cache().segment(SEGMENT_ID);
```
### Pool ID (Job Scheduling)
```javascript
// Pool ID from Console → Job Scheduling → pool details
const pool = catalystApp.jobScheduling().pool(POOL_ID);
```
### Circuit ID
```javascript
// Circuit ID from Console → Circuits → circuit details
const circuit = catalystApp.circuit();
const result = await circuit.execute(CIRCUIT_ID, { inputKey: 'value' });
```
---
## Catalyst Organizations
Catalyst supports multiple organizations per account under the same email address.
### Key concepts
- **Org owner**: Created the org. Can add collaborators (admins or project members), grant permissions per org or per project.
- **Collaborator types**: `Admin` (org-wide access) or `Project Member` (scoped to specific projects). Permissions are based on the assigned profile.
- **Org ID**: Auto-generated unique ID for each org. Part of the console URL: `https://console.catalyst.zoho.com/baas/{OrgID}/index`
- **Default org**: The org Catalyst assigns you to at signup. Can be changed to any other org you own.
### Default organization behavior — critical for MCP and API usage
The default org affects everything:
- **CLI login** — always logs into the default org unless you switch explicitly.
- **Every API call** — executed against a project in the default org unless you pass the `CATALYST-ORG: {org_id}` header explicitly.
- **MCP tools** — `CatalystbyZoho_*` calls target the default org; always call `List_All_Organizations` first to confirm the correct org, then pass its ID in subsequent calls.
> **Cannot delete the default org.** Set a different org as default before attempting to delete.
### Accessing the multi-org organization
Console → profile icon (top-left) → Organizations dropdown → **Manage Organizations**
The organization view shows each org's unique ID and console URL.
### Switching organizations via CLI
```bash
catalyst whoami # shows current logged-in user
catalyst switch:org # interactive org selector (arrow-key menu)
```
---
## IaC Export / Import
Catalyst supports project export and import (Infrastructure as Code) for migrating between data centers, duplicating projects, or sharing project templates.
### What is exported
- ✅ Component configurations (Data Store schema, Cache segments, Circuits, Security Rules, API Gateway routes, email templates, user profiles, etc.)
- ✅ Function and client code
- ❌ **Data is NOT exported** — no DataStore rows, no file contents, no user list records
### How to export
Console → Settings → General → **Export Project** → downloads a ZIP file in Catalyst IaC format.
Also available via CLI:
```bash
catalyst project:export # export to local directory
catalyst project:export --zip # generate import-ready ZIP
```
### How to import
Console → index page → **Import Project** → upload the ZIP → new project is created.
Also available via CLI:
```bash
catalyst project:import --file ./my-project.zip
```
### Common use cases
| Use case | How |
|----------|-----|
| Move project to a different DC (e.g., US → EU) | Export → log into EU console → Import |
| Duplicate a project for a new client | Export → Import as new project in same or different org |
| Test a GitHub-hosted project | Clone repo → generate ZIP → import and test |
| CI/CD project templating | Script `catalyst project:export` + `catalyst project:import` |
## Common Errors
| Error | Cause | Fix |
|-------|-------|-----|
| `catalyst init` fails with "project already exists" | Re-running init in a directory that already has `catalyst.json` | Delete `catalyst.json` and `.catalystrc` and re-run, or use `catalyst init` in a fresh directory |
| `No project found` when running `catalyst deploy` | Working directory has no `catalyst.json` | Run `catalyst init` first, or `cd` to the correct project root |
| Environment not switching after `catalyst env:switch` | Session-level env cached | Run `catalyst login` again after switching environments |
| `Permission denied` on deploy | API key lacks deploy permissions for this project | Confirm the key has Developer or higher role in Console → Project Settings |
references/quick-start.md
# Catalyst Quick Start
Catalyst is Zoho's serverless application platform. You write backend logic as
Node.js/Java/Python functions, store data in Data Store or NoSQL, serve frontends
via Slate, and ship without managing servers.
## The 5 core services
| Service | What it does | When to use |
|---------|-------------|-------------|
| **Functions** | Run Node.js/Java/Python code on HTTP triggers or events | Any backend logic, APIs, file processing |
| **Data Store** | Managed relational DB — CRUD via SDK + ZCQL queries | Structured, tabular data with fixed schema |
| **Stratus** | Object storage (files, images, blobs up to 250 GB each) | File uploads, static assets, large data |
| **Slate** | Git-based frontend hosting (React, Next.js, Vue, Angular, …) | Serving your web UI |
| **Cache** | In-memory key-value store with TTL (max 48 h) | Sessions, rate-limit counters, ephemeral data |
---
## From zero to deployed — the walkthrough
### Step 1 — Install CLI and log in
```bash
npm install -g zcatalyst-cli
catalyst login # opens browser auth, stores credentials locally
catalyst whoami # confirm logged-in user
```
### Step 2 — Find your Org ID
Open the Catalyst Console at `https://console.catalyst.zoho.com/baas/index`. Your Org ID appears in the URL once you're inside an org:
`https://console.catalyst.zoho.com/baas/{OrgID}/index`
Copy that number — you'll need it when prompted during `catalyst init`.
> **First time?** If you haven't created a Catalyst project yet, go to the console → **Create Project** first. Then return here. `catalyst init` only links to existing projects — it cannot create them.
### Step 3 — Initialize the project
#### Non-interactive mode (agents / CI)
```bash
# Step 1: get your project ID
catalyst project:list --org <orgId>
# Step 2: initialize — both --org and -p are required
mkdir my-app && cd my-app
catalyst init --org <orgId> -p <projectId> -ni
```
This creates **only** `.catalystrc`. `catalyst.json` does **not** exist yet — it is created automatically the first time you run `catalyst functions:add -ni` (or another feature command like `catalyst slate:create -ni`). This is expected; do not treat the absence of `catalyst.json` after `init -ni` as an error.
#### Interactive mode
```bash
mkdir my-app && cd my-app
catalyst init
# Follow the prompts:
#
# 1. "Select a default Catalyst organization for this directory:"
# Pick your organization from the list (arrow keys + Enter)
#
# 2. "Select a default Catalyst project for this directory:"
# Pick an existing project, OR select:
# [import a existing project] — link to a project by ID
# [create a new project] — create one from the console first, then re-run
#
# 3. "Which are the features you want to setup for this folder?"
# (This step is optional — press Enter to skip)
# Space to select, Enter to confirm. Options:
# ◯ Functions: Configure and deploy http/non-http functions
# ◯ Client: Configure and deploy client files
# ◯ AppSail: Configure and deploy AppSails
# ◯ Slate: Configure and deploy slate apps
#
# 4. If Functions selected:
# a) "Which type of function do you like to create?" (arrow keys)
# BasicIO — simple request/response (use for most HTTP APIs)
# AdvancedIO — raw HTTP control (req/res), full Express-style access
# Event — triggered by Catalyst events (e.g. Data Store row insert)
# Cron — runs on a schedule (cron expression)
# Browser Logic — Puppeteer-based headless browser automation
# Job — long-running background job
# Integration — triggered by Zoho service events (CRM, Desk, etc.)
#
# b) "Which runtime do you prefer to write your function?" (arrow keys)
# ----Java----
# Java 25 / Java 21 / Java 17 / Java 11 / Java 8
# ---NodeJS---
# NodeJS 24 / NodeJS 22 / NodeJS 20 / NodeJS 18
# ---Python---
# Python 3.10 / Python 3.9
#
# c) npm-init style questions (press Enter to accept defaults):
# package name: (defaults to your project name)
# version: (1.0.0)
# description:
# entry point: (index.js)
# test command:
# git repository:
# keywords:
# author:
# license: (ISC)
# Is this OK? → press Enter (yes)
#
# d) "Install all dependencies now?" → Yes (recommended)
#
# 5. If Slate selected:
# Select a framework → React + Vite (or your preference)
# App name → e.g. my-ui
# Modify default configurations? → No
# Development command → press Enter to accept default
```
Interactive `catalyst init` creates both files when features are selected in the prompts:
- `catalyst.json` — project metadata (do not edit manually)
- `.catalystrc` — org/env config (do not edit manually)
### Step 4 — Find your Project ID
After `catalyst init`, open the Catalyst Console and navigate to your project. Your Project ID appears in the URL:
`https://console.catalyst.zoho.com/baas/<ORG_ID>/project/<PROJECT_ID>/`
### Step 5 — Add a function
```bash
catalyst functions:add
# Prompts (in order):
# 1. Which type of function do you like to create?
# BasicIO / AdvancedIO / Event / Cron / Browser Logic / Job / Integration
# 2. Which runtime do you prefer to write your function?
# Java: 25 / 21 / 17 / 11 / 8
# NodeJS: 24 / 22 / 20 / 18
# Python: 3.10 / 3.9
# 3. npm-init style questions (package name, version, description,
# entry point, test command, git repository, keywords, author,
# license, Is this OK?)
# 4. Install all dependencies now? → Yes
```
This creates `functions/<your_function>/index.js` (for Node.js).
A minimal Advanced I/O function (raw-http template):
```javascript
// functions/my_api/index.js
'use strict';
const catalyst = require('zcatalyst-sdk-node');
module.exports = async (catalystApp, context, req, res) => {
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ message: 'Hello from Catalyst' }));
};
```
### Step 6 — Serve locally
```bash
catalyst serve
# Runs functions at: http://localhost:3000/server/<function_name>/execute
```
Test it:
```bash
curl http://localhost:3000/server/my_api/execute
```
### Step 7 — Deploy
```bash
catalyst deploy
# or deploy only functions:
catalyst deploy --only functions
```
Your function is live at:
`https://<project_domain>.catalystserverless.com/server/<function_name>/execute`
---
## Create a Data Store table
1. Open Console → your project → **Data Store**
2. Click **Add Table** → enter a table name (e.g., `Tasks`)
3. Click **Add Column** for each field:
- Column name (e.g., `Title`)
- Type: `Text`, `Number`, `Boolean`, `Date/DateTime`, `Email`
4. Save the table
Your table now has a `ROWID` column automatically (Catalyst's primary key).
### Set row-level permissions
1. Console → Data Store → your table → **Scopes and Permissions**
2. Enable **App User** row (required for SDK operations from authenticated users)
3. Check **Insert**, **Update**, **Delete** as needed
4. Save
---
## Configure CORS / Authorized Domains
If your Slate frontend calls a function and you get a CORS error in production:
1. Console → your project → **Settings** → **Authorized Domains**
2. Click **Add Domain** → enter your Slate domain (e.g., `https://myapp-12345.catalystapps.com`)
3. Enable the **CORS** toggle for that domain
4. Save
> The Catalyst gateway injects the CORS headers automatically — you do NOT need CORS code in your function for production origins. CORS code in functions is only for local dev (`localhost`).
## Common Errors
| Error | Cause | Fix |
|-------|-------|-----|
| `catalyst: command not found` | CLI not installed globally | Run `npm install -g zcatalyst-cli` |
| `catalyst.json` missing after `init -ni` | Expected — NI init only creates `.catalystrc` | Run `catalyst functions:add --name <n> --type <t> --stack <s> -ni` to create it |
| `catalyst.json` is `{}` after interactive init | No features selected during init prompts | Re-run `catalyst init` and select at least one feature, or run `catalyst functions:add` |
| Function 401 in browser but works with curl | Authentication required in Security Rules | Add `"authentication": "open"` to `catalyst-config.json` for public endpoints |
| CORS error in production frontend | Domain not in Authorized Domains | Add the Slate/frontend domain in Console → Settings → Authorized Domains and enable CORS toggle |
references/setup/claude-code.md
# Using Catalyst Skills with Claude Code
## Installation
Add the catalyst-skills repo to your Claude Code workspace:
```bash
# From your project directory
git clone https://github.com/catalystbyzoho/agent-skills.git .catalyst-skills
```
Or install via the skills CLI if available:
```bash
npx skills add catalystbyzoho/agent-skills
```
## Skill Activation
Claude Code picks up skills automatically from the `skills/` directory. To verify:
1. Open Claude Code in your Catalyst project directory
2. Ask: "What Catalyst skills are available?"
3. Claude will list the active skills from `catalyst-by-zoho/SKILL.md`
## MCP Setup (Recommended)
Connect Zoho MCP so Claude can manage Catalyst infrastructure directly (create tables, list projects, etc.) without you copying IDs from the console.
**Step 1 — Get your Zoho MCP URL:**
1. Go to [mcp.zoho.com](https://mcp.zoho.com) and create or open an MCP server
2. Under **Tools → Config Tools**, search for **"Catalyst by Zoho"** and add it
3. Under **Connections**, set authorization to **"On Demand"**
4. Click **Connect** → copy your server URL (format: `https://<server-name>-<org-id>.zohomcp.com/mcp/<auth-token>/message`)
**Step 2 — Add to Claude Desktop config:**
Edit `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows):
```json
{
"mcpServers": {
"catalyst-by-zoho": {
"type": "streamable-http",
"url": "https://<server-name>-<org-id>.zohomcp.com/mcp/<auth-token>/message"
}
}
}
```
Alternatively, copy the `.mcp.json` file from this repo into your project root and replace the `<YOUR_ZOHO_MCP_URL>` placeholder.
After saving, restart Claude. Confirm MCP is connected by looking for `CatalystbyZoho_*` in the tool list.
## Pre-flight Checklist
Before asking Claude to write Catalyst code, ensure:
- [ ] `catalyst login` has been run in your terminal
- [ ] `catalyst init` has been run in the project directory
- [ ] `.catalystrc` and `catalyst.json` exist at the project root
- [ ] (Optional) Zoho MCP is connected and `CatalystbyZoho_*` tools appear in Claude
## Common Errors
| Error | Cause | Fix |
|-------|-------|-----|
| Claude writes files without a project | `.catalystrc` or `catalyst.json` missing | Run `catalyst login` then `catalyst init` |
| MCP tools not appearing | MCP config not saved or Claude not restarted | Save config and fully restart Claude |
| Wrong project context | Multiple projects in `.catalystrc` | Run `catalyst project:use <project-name>` first |
references/setup/cursor.md
# Using Catalyst Skills with Cursor
## Installation
Add the catalyst-skills repo to your Cursor workspace:
```bash
# From your project directory
git clone https://github.com/catalystbyzoho/agent-skills.git .catalyst-skills
```
Or install via the skills CLI if available:
```bash
npx skills add catalystbyzoho/agent-skills
```
## Skill Activation
Cursor reads skills from the `skills/` directory in your workspace. To verify:
1. Open Cursor in your Catalyst project directory
2. Open the Composer (Cmd+I / Ctrl+I)
3. Ask: "What Catalyst skills are available?"
## MCP Setup (Recommended)
Connect Zoho MCP so Cursor's AI can manage Catalyst infrastructure directly.
**Step 1 — Get your Zoho MCP URL:**
1. Go to [mcp.zoho.com](https://mcp.zoho.com) and create or open an MCP server
2. Under **Tools → Config Tools**, search for **"Catalyst by Zoho"** and add it
3. Under **Connections**, set authorization to **"On Demand"**
4. Click **Connect** → copy your server URL (format: `https://<server-name>-<org-id>.zohomcp.com/mcp/<auth-token>/message`)
**Step 2 — Add to Cursor MCP config:**
Create or edit `.cursor/mcp.json` in your project root:
```json
{
"mcpServers": {
"catalyst-by-zoho": {
"type": "streamable-http",
"url": "https://<server-name>-<org-id>.zohomcp.com/mcp/<auth-token>/message"
}
}
}
```
Alternatively, configure globally via **Cursor Settings → MCP → Add Server** and paste the URL.
After saving, restart Cursor. Confirm MCP is active by checking **Cursor Settings → MCP** for a green status indicator next to `catalyst-by-zoho`.
## Pre-flight Checklist
Before asking Cursor to write Catalyst code, ensure:
- [ ] `catalyst login` has been run in your terminal
- [ ] `catalyst init` has been run in the project directory
- [ ] `.catalystrc` and `catalyst.json` exist at the project root
- [ ] (Optional) Zoho MCP server shows connected in Cursor MCP settings
## Common Errors
| Error | Cause | Fix |
|-------|-------|-----|
| Cursor writes files without a project | `.catalystrc` or `catalyst.json` missing | Run `catalyst login` then `catalyst init` |
| MCP not connecting | Config path wrong or URL placeholder not replaced | Verify the URL in `.cursor/mcp.json` is your actual Zoho MCP URL from mcp.zoho.com |
| MCP shows red/error status | Invalid or expired URL | Regenerate the URL at mcp.zoho.com and update the config |
references/setup/github-copilot.md
# Using Catalyst Skills with GitHub Copilot (VS Code)
## Installation
Add the catalyst-skills repo to your VS Code workspace:
```bash
# From your project directory
git clone https://github.com/catalystbyzoho/agent-skills.git .catalyst-skills
```
Or install via the skills CLI if available:
```bash
npx skills add catalystbyzoho/agent-skills
```
## Skill Activation
GitHub Copilot in VS Code picks up skills from the `skills/` directory. To verify:
1. Open the Copilot Chat panel (Ctrl+Shift+I / Cmd+Shift+I)
2. Ask: "What Catalyst skills are available?"
## MCP Setup (Recommended)
Connect Zoho MCP so Copilot can manage Catalyst infrastructure directly (no console copy-pasting).
**Step 1 — Get your Zoho MCP URL:**
1. Go to [mcp.zoho.com](https://mcp.zoho.com) and create or open an MCP server
2. Under **Tools → Config Tools**, search for **"Catalyst by Zoho"** and add it
3. Under **Connections**, set authorization to **"On Demand"**
4. Click **Connect** → copy your server URL (format: `https://<server-name>-<org-id>.zohomcp.com/mcp/<auth-token>/message`)
**Step 2 — Add to VS Code MCP config:**
Create `.vscode/mcp.json` in your workspace root:
```json
{
"servers": {
"catalyst-by-zoho": {
"type": "http",
"url": "https://<server-name>-<org-id>.zohomcp.com/mcp/<auth-token>/message"
}
}
}
```
Alternatively, configure globally via **VS Code Settings → MCP** (search "MCP" in Settings UI).
After saving, VS Code will prompt you to start the MCP server. Accept. Confirm it's running via **View → Output → MCP Server: catalyst-by-zoho**.
## Pre-flight Checklist
Before asking Copilot to write Catalyst code, ensure:
- [ ] `catalyst login` has been run in your terminal
- [ ] `catalyst init` has been run in the project directory
- [ ] `.catalystrc` and `catalyst.json` exist at the project root
- [ ] (Optional) MCP Output channel shows `catalyst` server running
## Common Errors
| Error | Cause | Fix |
|-------|-------|-----|
| Copilot writes files without a project | `.catalystrc` or `catalyst.json` missing | Run `catalyst login` then `catalyst init` |
| MCP server not starting | URL in `.vscode/mcp.json` is a placeholder | Replace `<YOUR_ZOHO_MCP_URL>` with your actual URL from mcp.zoho.com |
| `CatalystbyZoho_*` tools not appearing in Copilot | `.vscode/mcp.json` not detected or URL invalid | Check the MCP Output channel for errors; verify the URL is your actual Zoho MCP URL from mcp.zoho.com |
| Wrong environment targeted | Zoho MCP defaults to Development | The MCP server targets Development by default — switch explicitly in the Zoho MCP console if needed |
SKILL.md
---
name: catalyst-basics
description: "Core Catalyst project setup — directory structure, environments, CLI commands, and all Catalyst IDs (Project ID, ZAID, Table ID, Segment ID, Org ID). Trigger on 'start a Catalyst project', 'what is .catalystrc', 'where do I find my Table ID', 'difference between Development and Production', or any Catalyst ID or CLI question."
metadata:
version: "2.0.0"
---
> **⚠️ PRE-FLIGHT CHECK:** Before creating any project files, confirm that `.catalystrc` and
> `catalyst.json` exist in the project directory. If they don't:
> 1. Use MCP (`CatalystbyZoho_List_All_Organizations` → `CatalystbyZoho_List_All_Projects`) to get the org ID and project ID.
> 2. Run: `catalyst init --org <orgId> -p <projectId> -ni`
> 3. **Never ask the user to run `catalyst init` interactively. Never create these files manually** — they are CLI-generated and must come from the CLI.
## How It Works
1. **MCP check first** — Before reading any local files, look for `CatalystbyZoho_*` tools. If available, use MCP to get org ID, project ID, and all resource IDs instead of asking the user.
2. **Account alignment check — do this before `catalyst init`** — MCP and CLI can be authenticated as different accounts. Before running `catalyst init --org <id>`, verify they match:
```bash
catalyst whoami
```
Compare the org name shown to the result of `CatalystbyZoho_List_All_Organizations`. If they differ, run `catalyst login --force` to re-authenticate the CLI before proceeding.
3. **New to Catalyst?** — If the user is setting up Catalyst for the first time or asking "how do I start", load `references/quick-start.md` for the full walkthrough.
4. **Console navigation** — If the user asks how to find IDs, create tables, set permissions, or configure CORS in the console, load `references/console-ui-guide.md`.
5. **Pre-flight** — Confirm `.catalystrc` and `catalyst.json` exist. If missing, use MCP to get org/project IDs and run `catalyst init --org <orgId> -p <projectId> -ni`. Never use interactive `catalyst init`.
6. **Project structure** — Load `references/project-basics.md` for directory layout, `catalyst.json`, IDs, and dev-to-prod checklist.
7. **CLI questions** — Load `references/cli.md` for the exact command, flags, and safety rules.
8. **Answer** — Provide the specific ID path or CLI command needed. Never ask the user to manually look up IDs when MCP is connected.
## Triggers
Use this skill for: "how do I start a Catalyst project", "what is .catalystrc", "where do I find my Table ID / ZAID / Segment ID / Project ID", "difference between Development and Production", "Catalyst project structure", "catalyst.json explained", `catalyst init`, `catalyst deploy`, `catalyst serve`, `catalyst login`, "how do I set up Catalyst with Claude", "how do I use Catalyst in Cursor", "how do I use Catalyst with GitHub Copilot", "which service should I use", "what Catalyst service for X", or any question about Catalyst IDs, environments, organizations, IDE setup, architecture decisions, or CLI subcommands.
## 🔌 MCP Connection Check (Do This Before Anything Else)
**Before reading `.catalystrc`, asking the user for IDs, or doing anything project-related — check whether Zoho MCP tools are available in your tool list.**
Look for tools prefixed with `CatalystbyZoho_` (e.g., `CatalystbyZoho_List_All_Projects`, `CatalystbyZoho_List_All_Tables`).
**If MCP tools ARE available:**
- Use `CatalystbyZoho_List_All_Organizations` to get the org ID
- Use `CatalystbyZoho_List_All_Projects` to get the project ID
- Use MCP tools to fetch table names, bucket names, ZAIDs, and all other project details directly — do NOT ask the user to copy-paste IDs from the console
**If MCP tools are NOT available:**
- Prompt the user to connect Zoho MCP before proceeding
- Guide them to: **VS Code → Settings → MCP** (or Claude Desktop `claude_desktop_config.json`) and add the Catalyst MCP server
- Fall back to reading `.catalystrc` and `catalyst.json` from the local project directory only as a last resort
> **Never ask the user to manually look up IDs from the console** if MCP is connected. Every project detail — org ID, project ID, table IDs, ZAIDs, bucket names — is retrievable via MCP tools. Asking the user to hunt for IDs when MCP is available wastes time and introduces copy-paste errors.
## References
Load the relevant reference file for detailed information:
| Reference | Contents |
|-----------|----------|
| `references/quick-start.md` | First-time setup — install CLI, `catalyst init`, find org/project IDs, add a function, serve locally, deploy, create a Data Store table, configure CORS/Authorized Domains |
| `references/console-ui-guide.md` | Console navigation — finding Project ID/ZAID/Table ID, creating tables with typed columns, enabling App User permissions (Scopes and Permissions), Authorized Domains + CORS toggle |
| `references/project-basics.md` | Project directory structure, `catalyst.json`, `.catalystrc`, `catalyst-config.json`, environments, dev-to-prod checklist, all Catalyst IDs (Project ID, ZAID, Table ID, Segment ID, etc.) |
| `references/cli.md` | Full CLI command reference — all subcommands with flags, Slate/AppSail non-interactive setup, `catalyst serve` port behavior, deploy scoping, safety rules, resource-first development order |
| `references/architecture.md` | Service selection guide — which Catalyst service to use for which pattern, typical stack combinations, DC availability table for regionally restricted services |
| `references/setup/claude-code.md` | Installing skills and connecting Zoho MCP in Claude Code (Claude Desktop) |
| `references/setup/cursor.md` | Installing skills and connecting Zoho MCP in Cursor |
| `references/setup/github-copilot.md` | Installing skills and connecting Zoho MCP in GitHub Copilot (VS Code) |