Skip to content

Workflows

Kod includes a built-in workflow engine that runs tasks when code is pushed to a repository. Workflows are defined in TOML files inside your repository.

Place workflow files in the .kod/workflows/ directory of your repository:

my-project/
.kod/
workflows/
build.toml
deploy.toml
src/
package.json

All .toml files in .kod/workflows/ are discovered and executed automatically on push.

A workflow file contains steps defined as TOML sections:

timeout: 120
[step:install]
run: npm ci
[step:lint]
run: npm run lint
[step:test]
run: npm test
[step:build]
run: npm run build
PropertyTypeDescription
runstringCommand(s) to execute. Supports multiline.
ifstringConditional expression. Step is skipped if false.
working_dirstringWorking directory relative to repo root.
continue_on_errorbooleanContinue to next step even if this one fails. Default: false.
PropertyTypeDescription
timeoutnumberMaximum execution time in seconds. Default: 300.

Use indented lines for multi-command steps:

[step:setup]
run:
npm ci
npm run generate
npm run migrate

Use if to run steps only on specific branches or when certain environment variables are set:

[step:deploy]
if: "branch == 'main'"
run: ./deploy.sh
[step:preview]
if: "branch != 'main'"
run: ./deploy-preview.sh
[step:notify]
if: "env.SLACK_WEBHOOK != ''"
run: curl -X POST $SLACK_WEBHOOK -d '{"text":"Deploy complete"}'

Supported conditions:

  • branch == 'value' — matches exact branch name
  • branch != 'value' — excludes a branch
  • env.VAR == 'value' — checks an environment variable
  • env.VAR != 'value' — checks an environment variable is not a value

Use {variable} syntax in commands:

[step:tag]
run: docker build -t myapp:{branch} .
[step:log]
run: echo "Building {repo} on {branch}"

Available variables:

VariableDescription
{branch}Current Git branch
{repo}Repository name
{env.VAR_NAME}Environment variable value

Set environment variables for subsequent steps:

[step:setup]
run:
env.NODE_ENV = "production"
env.BUILD_ID = "build-123"
[step:build]
run: npm run build

Run steps in a subdirectory:

[step:frontend-test]
working_dir: ./apps/frontend
run: npm test
[step:backend-test]
working_dir: ./apps/backend
run: npm test

By default, a failed step stops the entire workflow. Use continue_on_error to keep going:

[step:lint]
run: npm run lint
continue_on_error: true
[step:test]
run: npm test

Secrets stored via the Secrets feature are automatically injected as environment variables. Reference them like any other env var:

[step:deploy]
if: "branch == 'main'"
run: |
echo "Deploying with token..."
curl -H "Authorization: Bearer $DEPLOY_TOKEN" https://api.example.com/deploy

No special syntax needed — if a secret named DEPLOY_TOKEN exists for the repository, it’s available as $DEPLOY_TOKEN in all steps.

Workflows run automatically when you git push to any branch. The post-receive hook triggers all workflow files found in .kod/workflows/.

Trigger workflows through the API:

Terminal window
curl -X POST http://localhost:3000/repos/my-project/workflows \
-H "Authorization: Bearer kod_your_token" \
-H "Content-Type: application/json" \
-d '{"branch": "main"}'

Run workflow files locally without pushing:

Terminal window
kod workflow build.toml
kod workflow build.toml deploy.toml
Terminal window
# All workflow runs
kod workflow status
# For a specific repo
kod workflow status my-project
timeout: 300
[step:install]
run: npm ci
[step:lint]
run: npm run lint
continue_on_error: true
[step:test]
run: npm test
[step:build]
run: npm run build
[step:deploy]
if: "branch == 'main'"
run:
echo "Deploying to production..."
rsync -avz dist/ $DEPLOY_HOST:/var/www/app/