Skip to main content

CI.json reference

A CI.json file can be placed anywhere in your repository (max size 256 kB). It describes one job, or a list of jobs, that run independently of each other whenever the folder it lives in changes — see how CI/CD jobs are triggered.

Top-level shape

A single job:

{ "Name": "...", "On": ["push"], "Steps": [ ... ] }

Or a list of jobs:

[
{ "Name": "job-one", "On": ["push"], "Steps": [ ... ] },
{ "Name": "job-two", "On": ["submit"], "Steps": [ ... ] }
]

Job fields

FieldTypeRequiredNotes
Namestringyes
ImageNamestringnosee Images, defaults to the base image
Stepsarray of stepsyesmax 100 steps
Onarray of stringsyesonly "push" and/or "submit" (never "manual"), max 10 entries
TimeoutMilliSeconds / TimeoutSeconds / TimeoutMinutesnumberyesset exactly one of these three

Images

ImageNameRuns in
""alias for "base"
"base"base Docker image
"go"Docker image with the Go toolchain
"bun"Docker image with the Bun/JS toolchain
"vm"a full LXD virtual machine instead of a container

Timeouts

Set exactly one of TimeoutMilliSeconds, TimeoutSeconds or TimeoutMinutes. The value is also capped by your subscription plan's maximum job duration — see Parallelism & concurrency.

Step fields

Each entry in Steps is one command run in sequence (a step failing aborts the rest of the job):

FieldTypeRequiredNotes
TemplateNamestringnoexpands into a predefined sequence of steps, see Step templates
Runstringnoa shell command
Envmap of string to stringnoextra environment variables for this step, max 50 entries
Secretsarray of stringsnonames of secrets to inject as env vars and scrub from logs, max 50 entries
Dirstringnoworking directory for this step, see Working directory

Step templates

  • get-code — expands to:
    tw init
    tw key $TWIGG_TOKEN
    tw server $REPO_ID
    tw pull $COMMIT_ID
    This is the idiomatic first step of a job: it gets your repository's code onto the runner. Without it, the runner starts with an empty workdir.
  • debug-get-code — same as get-code, but every command runs with --debug, useful for troubleshooting a job that fails while pulling code.

Secrets

Secrets are configured per-repository in the repository's Settings page. Listing a secret's name in a step's Secrets field injects its value as an environment variable for that step and scrubs the value out of the job's logs.

Working directory

If a step doesn't set Dir, it defaults to the folder containing the CI.json file. Steps produced by the get-code template always run in . (the runner's root workdir) regardless of where the CI.json lives, since they set up the checkout itself.

Auto-injected environment variables

Every step automatically receives:

VariableValue
TWIGG_TOKENa short-lived token scoped to this job
COMMIT_IDthe commit being built, e.g. c123v456
REPO_IDthe repository id, e.g. id/id

Full examples

A job that runs on every submit:

{
"Name": "log-hi",
"On": ["submit"],
"Steps": [
{ "Run": "echo HI!" }
],
"TimeoutMinutes": 5
}

A job that checks out the code and runs tests on every push:

{
"Name": "test-on-push",
"ImageName": "go",
"On": ["push"],
"Steps": [
{ "TemplateName": "get-code" },
{ "Run": "go test ./..." }
],
"TimeoutMilliSeconds": 1200000
}

Validation limits

LimitValue
CI.json file size256 kB
Steps per job100
Env entries per step50
Secrets entries per step50
On entries per job10
Jobs created per commit (CI + CD combined)100