A Helix project’s config lives in helix.config.ts at the project root. It holds the project’s name, its project and workspace IDs, the Helix environment the CLI talks to, and the map of auth aliases to credential UUIDs. You rarely edit it by hand, because helix init, helix workspace select, helix project set, and helix env set write to it for you.
A config file describes exactly one deploy target. Most projects have just the one file, but a project with more than one target, such as a separate production deployment, keeps one config file per target and picks one per command with --config.
What the file holds
// helix.config.ts
import { defineConfig } from '@trayai/helix-sdk';
export default defineConfig({
name: 'customer-health',
projectId: 'a1b2c3d4-5e6f-7a8b-9c0d-1e2f3a4b5c6d',
workspaceId: 'f8e7d6c5-4b3a-2190-8765-abcdef012345',
authentications: {
salesforce: '1a0fbf5c-2c9e-4aa1-ada3-ccbba65019ab',
},
});
| Key | What it names |
|---|---|
name | The project name. The first deploy uses it when it provisions the project on the platform. |
projectId | The provisioned project this checkout points at. Unset until a deploy provisions one, or until you set it yourself. |
workspaceId | The Tray workspace the project belongs to. Auth aliases resolve against it, locally and on deploy. |
environment | The Helix environment the CLI talks to. Written by helix env set. |
authentications | Alias to credential UUID, used as ctx.http.authed('alias') in function code. |
workspaceId is the one you need early: ctx.http.authed('alias') resolves against the workspace’s auth service during helix dev, not only in production. projectId matters when you deploy, and for anything the platform provisions for the project. Persistent key-value storage is the clearest case: with no project ID, helix dev has nothing provisioned to read from and falls back to in-memory storage that resets on restart.
See projects and workspaces for what each UUID refers to.
The CLI writes the file
| Command | What it writes |
|---|---|
helix init | Creates the file. --project-id and --workspace-id fill in those IDs; without them the ID is prompted for or left unset. |
helix workspace select [name] | Picks a workspace interactively, then writes workspaceId. |
helix workspace set <id> | Writes workspaceId when you already know the ID, for scripts and CI. |
helix project set <id> | Writes projectId, pointing this checkout at an existing provisioned project. |
helix env set <environment> | Writes the environment and persists it for later commands. |
The file is ordinary TypeScript, so you can edit it directly instead. The commands exist so CI pipelines and agent sessions don’t have to rewrite source to change which project they talk to. Full flags are in the project and auth session commands.
One config file per target
A config file names one target: one workspace, one project, one set of auth aliases. There is no environment map inside the file and no persisted “current target” state in the CLI. When you want a separate production target (typically its own workspace and its own credentials), you create one config file per target and name the one you mean. The convention is helix.<target>.config.ts:
helix.config.ts ← default; the target you develop against
helix.production.config.ts
Every command that reads or writes project config (dev, deploy, deployment get, the auth commands, project set, env set, the workspace commands, and mcp) accepts --config <path>:
helix dev # uses ./helix.config.ts
helix deploy # deploys the default target
helix deploy --config helix.production.config.ts # deploys production
The HELIX_CONFIG environment variable has the same effect, which is useful in CI where every step should hit the same target. Precedence, highest first: the --config flag, then HELIX_CONFIG, then ./helix.config.ts.
Commands that write config write to the selected file: helix project set <id> --config helix.production.config.ts updates the production file and leaves the default alone, and a first deploy with --config records the provisioned project ID in that file.
Keeping the target you develop against in helix.config.ts gives you a useful safety property: a bare helix dev or helix deploy only ever touches your development target. Reaching production always means naming the file, so there’s no environment switch to forget to reset.
Config files are ordinary TypeScript modules, so values shared between targets live in a module each target file imports and spreads. Each file stays complete and self-describing: open helix.production.config.ts and you see exactly what production is, with no mental merge of a base plus overrides. A sharing example is in the configuration reference.
Environments
An environment here is a Helix instance the CLI talks to. It is not your own development/production split, which is one config file per target.
helix env set writes the environment into helix.config.ts when you want to persist a choice for later commands:
helix env set <environment>
login, logout, and whoami also accept an optional --env <environment> flag for a single session command. It does not read the config file. Run helix env set --help to see which environment names your CLI version accepts.
What stays out of the file
- Credential values. The file maps aliases to UUIDs. The credentials themselves, and the rules for injecting them, stay on Helix’s servers. See the security model.
- Your Tray session. The token from
helix loginlives in~/.tray.config, outside the project. - Function-level settings. Handlers and input schemas live in the function files, through
defineFunction. - Who can open the deployed app. Access is a setting on the project’s Access Control tab in the dashboard, not a config key. See identity and roles.
For every key the config accepts, see the configuration reference.