Tray Sync CLI

CLI tool to clone Tray projects and related assets to a local directory, and promote them between Tray environments

CLI tool to clone tray projects and related assets on local machine which then can be used with version control system or promoted to different tray environment

Requirements

  • Node.js >= 22

Install

npm install -g @trayai/tray-sync-cli

CLI Commands

CommandDescription
tray init -r <region> -w <workspace-id>Scaffold a new tray-sync-cli repository
tray pullExport tracked projects from Tray and materialise them on disk
tray promote <env>Reconstruct local projects and import them into a target Tray environment
tray statusLocal checksum-based drift detection (zero API calls)
tray project remove <project-id>Untrack a project and delete its local directory (project scope only)
tray project listList managed projects with directory names and last-pulled timestamps
tray env add <name>Add a target environment
tray env listList source and target environments with connectivity status
tray env remove <name>Remove a target environment and its per-project mappings
tray env discover [env]List an env's projects (id + name, default) and/or matching authentications — env defaults to source
tray env resolve <env-name>Report unresolved auth requirements for a target env, with candidate matches
tray auth set -w <workspace-id> -r <region> -t <token>Set (or overwrite) a workspace's token
tray auth remove -w <workspace-id>Remove a workspace's stored token
tray auth listList workspaces with stored credentials
tray --versionPrint the installed CLI version
tray --helpShow help for the CLI or a specific command

Getting started: a first promotion, end to end

This is a concrete, step-by-step walkthrough of the most common workflow: pull a project from a source workspace, and promote it to a target workspace. It uses a two-org example (DEV_ORGPROD_ORG) since that's the realistic setup for most customer pipelines, but everything here works identically for two workspaces within the same org.

1. Pick a source and a target environment

Decide which workspace you're pulling from (the source) and which one you're promoting to (the target). For this guide:

  • Source: DEV_ORG
  • Target: PROD_ORG

You'll need each workspace's ID and region, and a Tray API token with access to it.

2. Create a local directory for this project

mkdir -p ~/tcli-projects/my-first-tcli-project
cd ~/tcli-projects/my-first-tcli-project

Everything the CLI manages — tray.yaml, environments.json, and every pulled project — lives under this directory.

3. Initialize the repository against your source workspace

tray init -r <region> -w <your-SOURCE-workspace-id> -t <your-token> -p <project-id-to-pull>

Example:

tray init -r us1 -w 11111111-1111-1111-1111-111111111111 -t <token> -p <project_id>

Don't know the project ID yet? Run init without -p (an empty scaffold is fine), then:

tray env discover

lists every project in your source workspace — id + name — so you don't have to dig it out of Tray's UI.

A few notes on the flags:

  • -p <project-id> pulls that project immediately after scaffolding. Omit it and init just scaffolds an empty repository — you can pull specific projects later with tray pull -p <project_id>, which tracks and pulls it in one step.
  • -s workspace (i.e. tray init -s workspace -r <region> -w <id> -t <token>, omitting -p) switches to workspace scope: every project in the workspace is pulled automatically, and tray pull keeps that mirror in sync going forward (including removing projects deleted from Tray). -p is ignored in this scope.
  • -t <token> is optional at init time. If you skip it (or need to replace it later — tokens expire), set or refresh it any time with:
    tray auth set -w <workspace-id> -r <region> -t <token>
    
    tray auth set always overwrites whatever token was stored for that workspace — no separate "force" flag needed.

At this point you have a local mirror of your source project(s), configured against DEV_ORG.

4. Add your target environment

Now register where you want to promote to:

tray env add <env-name> -r <region> -w <target-workspace-id> -t <target-token>

Example:

tray env add PROD_ORG -r us1 -w 22222222-2222-2222-2222-222222222222 -t <prod-token>

You can add more than one target environment this way (e.g. STAGING_ORG, PROD_ORG) — each gets its own entry in environments.json.

Same as init, providing -t here stores the token in ~/.tray/credentials.json immediately. You can always set or refresh it independently with tray auth set -w <target-workspace-id> -r <region> -t <token>.

5. Promote

You're ready to import your local projects into the target environment. A few common invocations:

# Recommended first: see what would happen without changing anything.
tray promote --to PROD_ORG --dry-run

# Promote a single project.
tray promote --to PROD_ORG -p <project-id>

# Promote multiple specific projects.
tray promote --to PROD_ORG -p <project-id-1> <project-id-2>

# Promote every project tracked in this directory (see them with `tray project list`).
tray promote --to PROD_ORG

Important: every project needs a target_project_id per environment

The first time you promote a given project to a given environment — or whenever the target project changes — you need to tell the CLI which project in the target workspace this should import into.

Each pulled project has its own mappings.json, at:

projects/<project-id>--<project-name>/mappings.json

You don't have to create this file by hand — tray pull / tray init already scaffold it for you (with a placeholder entry showing the full shape) the first time a project is pulled. What you do need to do is edit the target environment's entry and fill in the real target_project_id:

{
  "version": 1,
  "environments": {
    "PROD_ORG": {
      "target_project_id": "<project-id>",
      "authentications": {},
      "config": {},
      "connectors": [],
      "services": []
    }
  }
}

target_project_id here is the ID of the project in PROD_ORG that this local project should be imported into.

Authentications

If any workflow in the project you're promoting uses an authentication, you'll also need to map it. Tray tracks this per authentication group — a logical "auth slot" a workflow step references — not the authentication ID itself. When tray promote finds one it doesn't recognize, it tells you and scaffolds a placeholder into mappings.json for you:

{
  "version": 1,
  "environments": {
    "PROD_ORG": {
      "target_project_id": "<project-id>",
      "authentications": {
        "<source_authentication_id>": "MISSING_TARGET_AUTHENTICATION"
      },
      "config": {},
      "connectors": [],
      "services": []
    }
  }
}

The key (<source_authentication_id>) is the source-side auth group ID — leave it as-is. Replace the placeholder value with the ID of the actual authentication in your target environment (PROD_ORG) that should serve that slot — you can find this in Tray's app, under that workspace's authentications. For example:

"authentications": {
  "<source_authentication_id>": "<resolved_target_authentication_id>"
}

If you get it wrong

If a required field is missing or still holds a placeholder value, tray promote refuses the attempt and tells you exactly what's outstanding and where to fix it — it won't silently promote a project into the wrong target, or with an unresolved authentication.

Was this page helpful?