Project Structure
How the .dokkimi/ folder is organized.
The .dokkimi/ folder
The only requirement is that a .dokkimi/ folder exists at your repo root. You can organize files inside however you want — there are no required subfolder conventions. All **/*.json and **/*.yaml / **/*.yml files inside .dokkimi/ are scanned. You can use JSON or YAML interchangeably for definitions and shared fragments.
A common convention:
.dokkimi/
├── config.yaml # Project-level config (optional)
├── definitions/ # Runnable definition files
├── shared/ # Shared item fragments (referenced via $ref)
└── init-files/ # Database init scripts (SQL, JS) Two file types
Dokkimi distinguishes file types by their JSON shape, not by folder or naming convention:
Runnable definition
Has top-level name (string) + items (array):
{
"name": "my-test-suite",
"variables": { ... },
"items": [ ... ],
"tests": [ ... ]
} Shared fragment
Any JSON file that does NOT have both name + items. Typically a single item object:
{
"type": "DATABASE",
"name": "postgres-db",
"database": "postgres"
} Fragments are not runnable on their own — they exist to be referenced via $ref from runnable definitions.
Config file
The .dokkimi/ folder can contain a project-level config file: config.yaml, config.yml, or config.json (first match wins). This file is not a definition — it's loaded separately by name.
dokkimi: 0.1.0
env:
REGISTRY: ghcr.io/dokkimi
IMAGE_TAG: v1.2.3
STRIPE_TEST_KEY: sk_test_abc123 | Field | Type | Description |
|---|---|---|
dokkimi | string | Target Dokkimi version. The CLI warns if your installed version is older. |
env | object | Flat string → string map of build-time values. Keys must be alphanumeric + underscores. |
Build-time interpolation: ${{VAR}}
Any string value in a definition or shared fragment can reference a config env variable with ${{VAR}}. These are resolved at build time by the definition resolver, before the definition is sent to Control Tower.
{
"type": "SERVICE",
"name": "my-service",
"image": "${{REGISTRY}}/my-service:${{IMAGE_TAG}}",
"port": 3000,
"healthCheck": "/health"
} After resolution, the image becomes ghcr.io/dokkimi/my-service:v1.2.3.
${{VAR}} vs {{VAR}} — These are different systems. ${{VAR}} is resolved at build time from the config file. {{VAR}} is resolved at runtime from test variables. If a ${{VAR}} reference doesn't match any key in env, the resolver errors.
.dokignore
You can create a .dokkimi/.dokignore file to exclude files from cloud/CI test runs. It uses the same syntax as .gitignore:
# Ignore experimental definitions
experiments/
# Ignore a specific file
definitions/broken-test.json
# Ignore all files matching a pattern
**/wip-*.json Paths are relative to the .dokkimi/ directory. Ignored files are still valid for local runs — .dokignore only affects cloud/CI pipelines.