Where it lives
Everything specific to the managed project comes from a deck.yaml file (outside git; the template is
deck.example.yaml). deck looks, in this order, for:
- the path in
DECK_CONFIG; - a
deck.yamlin the current directory or any parent directory; deck.example.yaml, as a fallback.
The panel rereads the file on every request: editing the YAML shows up on screen without restarting deck ui. The
screens only receive the non-secret part (for example, never the profiles’ passwordEnv or the commands’ env).
Full example
name: Acme Platformworkspace: .. # folder containing the repositories, relative to this file
repos: - name: web path: acme-web url: git@github.com:acme/acme-web.git defaultBranch: dev launch: { command: npm run dev, port: 3000 } coverage: { format: lcov, path: coverage/lcov.info } secretFiles: - path: .env.local - { path: .npmrc, from: npmrc } - name: api path: acme-api url: git@github.com:acme/acme-api.git launch: { command: ./gradlew bootRun, port: 8080 } coverage: { format: jacoco, path: build/reports/jacoco/test/jacocoTestReport.xml }
environments: - name: local urls: { web: http://localhost:3000, api: http://localhost:8080 } - name: dev urls: { web: https://dev.acme.example, api: https://api.dev.acme.example }
github: owner: acme
azureBoards: organization: acme project: Acme Platform team: Acme Team workItemTypes: [User Story, Task, Bug] branchPattern: "{type}/AB#{id}-{slug}" phases: - { name: Ready for Development } - { name: In Development, role: start } - { name: Code Review, role: review } - { name: Ready for Testing, role: test } - { name: Done, role: done } doneStates: [Done, Closed, Removed]
azureLogs: environments: dev: resourceGroup: rg-acme-dev apps: { web: ca-acme-web-dev, api: ca-acme-api-dev }
mocks: - name: payments port: 4301 routes: - { method: GET, path: /health, body: { status: UP } } - { method: POST, path: /charges, status: 201, body: { id: ch_123, status: approved } }
database: queriesFile: queries.json profiles: - { name: local, host: localhost, database: acme, user: postgres, passwordEnv: DB_LOCAL_PASSWORD } - { name: prd, host: db.acme.example, database: acme, user: readonly, passwordEnv: DB_PRD_PASSWORD, readOnly: true } scripts: - { name: seed, description: Sample data, file: seeds/seed.sql }
compose: - name: infra files: [compose/infra.yml] env: { DB_PASSWORD: "secret:DB_LOCAL_PASSWORD" }
e2e: repo: web testDir: tests/e2e
tools: - { name: Node.js, command: node, minVersion: "22" } - { name: GitHub CLI, command: gh }Block reference
| Block | Required | Used by |
|---|---|---|
name, workspace | yes | Display name; repositories folder (default: the folder above the YAML) |
repos[] | yes | Every module. launch links the repo to the launcher; coverage to the coverage screen; secretFiles to deck secrets materialize |
environments[] | recommended | URLs per service: E2E BASE_URL, health checks, the panel’s environment selector |
github.owner | no | GitHub PRs and workflows (without it, the owner comes from the repo URL) |
azureBoards | no | Boards and the branch workflow. Remove the block to turn the integration off |
azureDevOps | no | Azure Repos and Pipelines, which may live in a different project than the board |
azureLogs | no | Container Apps logs, per environment and app alias |
mocks[] | no | deck mocks and the mocks screen |
database | no | Profiles, query catalog and SQL scripts |
compose[] | no | Docker Compose stacks |
e2e | no | Repository and folder of the Playwright tests; urlKey chooses which environment URL becomes BASE_URL |
wiki, notify, sonar | no | Per-task wiki, PR notice on Teams, Quality Gate |
tools[] | no | Tools checked by the diagnostics |
Board phases
phases are the board columns, in order. role links a phase to the CLI automations:
role | When the card moves to that phase |
|---|---|
start | When the task starts (git-workflow-start-dev) |
review | When the PR is opened (git-workflow-code-review) |
test | After the merge |
done | Closing |
The panel only lets you move a card to a phase declared here (or one of the doneStates).
Secrets
Secrets never go into the YAML or the repository. They live in an external directory, by default
<projects folder>/.env, outside any repository (DECK_SECRETS_DIR changes the location):
deck secrets path # where the directory isdeck secrets set DB_LOCAL_PASSWORD # reads the value from stdin/prompt, never from the command linedeck secrets materialize # copies the secretFiles (e.g. .env.local) into the reposdeck secrets capture # stores in the secrets directory the ones already in the reposIn the YAML, secrets are referenced by name: passwordEnv: DB_LOCAL_PASSWORD in database profiles and "secret:NAME"
in values such as compose[].env and notify.teamsWebhook.
Environment variables
| Variable | Effect |
|---|---|
DECK_CONFIG | Path to deck.yaml |
DECK_HOME | Deck root (where .data/ and .claude/skills/ live) |
DECK_SECRETS_DIR | Secrets directory |
DECK_AUTO_UPDATE, DECK_UPDATE_CHANNEL | Automatic updates and channel (estavel or dev) |
DECK_ANDROID_AVD | Emulator opened by deck open-emulator |
MOCKS_HOST | Mocks interface (default 127.0.0.1; 0.0.0.0 only inside a container) |