Skip to main content

Predefined CI/CD variables

Loom injects a set of predefined environment variables into every job at runtime. Use them in scripts to access job identity, workspace paths, Git metadata, and runtime context without hardcoding values.

check:
stage: ci
target: linux
script:
- echo "Job $LOOM_JOB_NAME running in $LOOM_PROJECT_DIR"
- echo "Commit: $CI_COMMIT_SHORT_SHA on branch $CI_COMMIT_BRANCH"

Variable naming

Loom provides two sets of predefined variables:

PrefixPurpose
LOOM_Native Loom variables. Use these when writing Loom-first workflows.
CI_Compatibility layer for scripts that also run in GitLab CI, GitHub Actions, or other platforms.

Many CI_ variables are aliases of their LOOM_ counterparts (for example, CI_JOB_NAME and LOOM_JOB_NAME resolve to the same value). Prefer LOOM_ variables in new workflows — they are the canonical names and will always be supported.

Using variables in scripts

Variables are injected as shell environment variables. Reference them with $VARIABLE_NAME:

check:
stage: ci
target: linux
script:
- echo "Job $LOOM_JOB_NAME running in $CI_PROJECT_DIR"
- cd $CI_PROJECT_DIR && pnpm run build

Provider behavior affects which variables a job sees:

ProviderBehavior
Host (no image: set)Job inherits the local process environment, then Loom applies workflow/job variables as overrides.
Docker (image: set)Loom passes only workflow/job variables into the container. Host environment variables are not forwarded — declare any needed values in default.variables or job variables.

Precedence

When a workflow or job defines a variable with the same name as a predefined variable, the user-defined value wins. User intent always takes priority.

version: v1
stages: [ci]

default:
variables:
CI_PROJECT_DIR: "/custom/workdir"

show-dir:
stage: ci
target: linux
script:
- echo "$CI_PROJECT_DIR"

Output:

/custom/workdir

If you depend on Loom's default value for a predefined variable, avoid overriding it. Use a different variable name instead — for example, prefix custom variables with your org or team name.

The full merge order is:

  1. Predefined variables (Loom system) — baseline values.
  2. Workflow-level variables / default.variables — override predefined values for matching keys.
  3. Job-level variables — override both predefined and workflow-level values for matching keys.

See Variables for the full precedence model.

Predefined variables reference

Pipeline-scoped variables are resolved once per loom run and then merged into every job environment. Job-scoped and step-scoped variables are resolved per job right before script execution.

Loom pipeline variables

VariableDescriptionAvailabilityExample
LOOM_CIAlways true when Loom is executing a job.Pipelinetrue
LOOM_RUN_IDExecutor run id. Unique per loom run invocation.Pipelineloom-run-local-1772867400012726000
LOOM_PIPELINE_IDExecutor pipeline id.Pipelineloom-local-1772867400012726000
LOOM_WORKFLOW_PATHWorkflow file path used for this run in the snapshot.Pipeline.loom/workflow.yml

Pipeline compatibility variables

VariableDescriptionAvailabilityExample
CIAlways true when Loom is executing a job.Pipelinetrue
CI_RUN_IDCompatibility alias for Loom's run id.Pipelineloom-run-local-1772867400012726000
CI_PIPELINE_IDExecutor pipeline id.Pipelineloom-local-1772867400012726000
CI_PIPELINE_IIDSame value as CI_PIPELINE_ID today.Pipelineloom-local-1772867400012726000
CI_PIPELINE_STARTED_ATRFC 3339 timestamp captured when the run starts.Pipeline2026-03-06T12:00:00Z
CI_PIPELINE_STARTED_AT_SLUGSlug of CI_PIPELINE_STARTED_AT limited to 63 bytes.Pipeline2026-03-06t12-00-00z
CI_PROJECT_NAMEProject name derived from the workspace root or explicit project metadata.Pipelineloom
CI_PROJECT_NAMESPACECurrently resolves to the same value as CI_PROJECT_NAME.Pipelineloom
CI_PROJECT_NAMESPACE_SLUGSlug of CI_PROJECT_NAMESPACE limited to 63 bytes.Pipelineloom
CI_PROJECT_NAMESPACE_IDPlaceholder namespace id.Pipeline0
CI_RUNNER_IDRunner identifier for local Loom execution.Pipelineloom-local
CI_RUNNER_VERSIONRunner version marker for local Loom execution.Pipelinelocal

Pipeline Git variables

VariableDescriptionAvailabilityExample
CI_COMMIT_SHASnapshot HEAD SHA that Loom runs against.Pipeline when Git metadata is knownabcdef1234567890abcdef12
CI_COMMIT_SHORT_SHAFirst 8 characters of CI_COMMIT_SHA.Pipeline when Git metadata is knownabcdef12
CI_COMMIT_BRANCHCurrent branch name when Loom can resolve it.Pipeline when branch is resolvablemain
CI_COMMIT_REF_NAMEAlias of CI_COMMIT_BRANCH for GitLab-compatible scripts.Pipeline when branch is resolvablemain

Job variables

VariableDescriptionAvailabilityExample
LOOM_JOB_NAMEJob name (graph node id).Jobcheck
LOOM_JOB_IDJob id (currently same as job name).Jobcheck
LOOM_JOB_STAGEJob stage name.Jobci
LOOM_JOB_TARGETJob target.Joblinux
LOOM_JOB_IMAGEJob image when image: is set.Job when image: is setnode:20-alpine
LOOM_PROVIDERhost or docker, depending on whether image: is set.Jobdocker
LOOM_PROJECT_DIRWorking directory when the job starts.Job/workspace
CI_BUILDS_DIRTop-level directory where builds or workspaces live.Job/tmp
CI_PROJECT_DIRWorkspace root where the job runs.Job/workspace
CI_JOB_NAMEJob name (graph node id).Jobcheck
CI_JOB_IDJob id (currently same as job name).Jobcheck
CI_JOB_STAGEJob stage name.Jobci
CI_JOB_TARGETJob target.Joblinux
CI_JOB_IMAGEJob image when image: is set.Job when image: is setnode:20-alpine
CI_DEBUG_TRACEDefaults to false; set to true to enable verbose shell tracing.Jobfalse
CI_JOB_STATUSAlways running during script execution.Jobrunning
CI_JOB_TIMEOUTPlaceholder timeout value.Job0
CI_JOB_STARTED_ATRFC 3339 timestamp captured when the job environment is injected.Job2026-03-06T12:01:00Z
CI_JOB_STARTED_AT_SLUGSlug of CI_JOB_STARTED_AT limited to 63 bytes.Job2026-03-06t12-01-00z
CI_STAGE_STARTED_ATRFC 3339 timestamp for the stage start tracked for the current job.Job2026-03-06T12:01:00Z
CI_STAGE_STARTED_AT_SLUGSlug of CI_STAGE_STARTED_AT limited to 63 bytes.Job2026-03-06t12-01-00z

Step variables

VariableDescriptionAvailabilityExample
CI_STEP_IDAlways 1; Loom currently executes a job as a single shell step.Step1
CI_STEP_STARTED_ATRFC 3339 timestamp captured when the current step starts.Step2026-03-06T12:01:00Z
CI_STEP_STARTED_AT_SLUGSlug of CI_STEP_STARTED_AT limited to 63 bytes.Step2026-03-06t12-01-00z

These variables are defined by Loom and do not depend on any external CI provider.

Variables in workflow rules

workflow.rules.if expressions reference variables using $VARIABLE_NAME syntax:

workflow:
rules:
- if: $CI_COMMIT_BRANCH == "main"

Today, Loom validates rule structure (each rule must have a non-empty if string) but does not evaluate expressions at runtime. Which variables are available during rule evaluation — and the expression language itself — is planned. See Rules for current status.

Until expression evaluation is implemented, use workflow.rules for forward-compatible structure and handle gating logic in job scripts or your surrounding CI system.

Running inside another CI system

When you invoke loom run --local from within a GitLab CI job, GitHub Actions step, or other CI runner:

  • Host-provider jobs (no image:) inherit the parent CI environment. Variables like CI_COMMIT_REF_NAME or GITHUB_SHA from the outer CI system are visible alongside Loom's predefined variables.
  • Docker-provider jobs (image: set) receive only workflow/job variables. To forward a value from the outer CI system, declare it explicitly in variables.
check:
stage: ci
target: linux
image: node:20-alpine
variables:
GITHUB_SHA: $GITHUB_SHA
script:
- echo "Outer CI SHA: $GITHUB_SHA"

Migration from other CI platforms

Loom's CI_ variables provide a compatibility layer, not a perfect emulation. Key differences:

AreaWhat Loom providesWhat may be missing
Job identityJob name, id, stage, target, image, status
WorkspaceProject directory, builds directory
Git metadataCommit SHA, short SHA, branch nameTag name, MR/PR metadata, author, labels
PipelinePipeline id, run id, timestampsPipeline source, trigger info, upstream pipeline
RunnerRunner id (loom-local), version (local)Runner description, tags, architecture

If your scripts need values Loom does not provide (merge request metadata, actor names, tags), pass them explicitly via workflow or job variables, or rely on the host environment when running Loom inside another CI system.

When writing portable scripts, prefer LOOM_ variables inside Loom workflows and map to provider-specific names at the boundary:

check:
stage: ci
target: linux
script:
- echo "Project dir: $LOOM_PROJECT_DIR"
- echo "Provider: $LOOM_PROVIDER"

Not yet supported

Loom does not currently derive Git metadata beyond commit SHA and branch name. Tag names, merge request details, author information, and similar context are not automatically populated. Pass these explicitly via variables if your workflow needs them.

Security considerations

Some predefined variables can expose sensitive information even when they do not look like secrets:

  • Paths (CI_PROJECT_DIR, CI_BUILDS_DIR, LOOM_PROJECT_DIR) can reveal usernames, internal mount paths, or repository layout.
  • Identifiers (CI_COMMIT_SHA, CI_PIPELINE_ID, LOOM_RUN_ID) can be used to correlate runs and access logs.
  • Image references (CI_JOB_IMAGE) may reveal base images or private registries.

Sharing variable names is safe. Sharing values may not be — redact path segments and internal hostnames when asking for help. If you need to share debugging context, provide the run_id and structured log pointers instead of raw environment dumps. See What to share.

Troubleshooting

Print all predefined variables available in a job:

script:
- env | grep -E '^CI_|^LOOM_' | sort

Enable verbose shell tracing for detailed execution output:

variables:
CI_DEBUG_TRACE: "true"

Validate your workflow before running:

loom check

Next steps