Skip to main content
The script.run action executes an inline bash script as a deterministic workflow step inside the workflow execution container. Use it when you need repeatable shell automation that does not require an AI agent or model tokens.

Overview

Run Script is designed for workflow steps where the command path is already known. The script runs in bash, can read environment variables, can run inside a cloned repository, and can return structured JSON for later steps.

Deterministic execution

Run the script exactly as written without asking an AI agent to decide what to do.

Workflow data in

Pass trigger data and previous step outputs through environment variables.

Structured data out

Write JSON to $OC_OUTPUT_FILE and reference parsed fields in downstream steps.

Failure-aware

Exit code 0 succeeds. Non-zero exits, including timeouts, fail the step.

When to use Run Script

Use Run Script when the work is deterministic and shell-based.
Use this actionWhen your workflow needs
script.runA known bash script, file inspection, validation command, formatting check, artifact preparation, or data transformation that should run the same way every time.
agent.runA single AI agent to reason about a task, choose tools, write text, inspect code, or make judgment calls.
agent.sessionMultiple AI agents, an interactive session, or a task that benefits from agent coordination and iteration.
git.cloneRepository checkout before another step needs files from the codebase. Use git.clone before Run Script when the script should run inside a repository.
ci.executeWorkflowAn external CI/CD pipeline, such as a GitHub Actions workflow, should run outside Overcut.
Run Script is a good fit for steps like:
  • Check whether generated files changed after a previous step.
  • Extract metadata from a cloned repository.
  • Convert trigger or agent output into a normalized JSON shape.
  • Run a lightweight command before deciding whether a later agent step should run.

Add a Run Script step in Workflow Builder

Open Workflow Builder

Open or create a workflow in Workflow Builder.

Add the action

Add an action step and choose Run Script.

Configure General fields

Set Step ID, Step Name, and Step Timeout (minutes).

Enter the script

Add your shell commands in Bash Script. The script body is not template-interpolated, so pass dynamic values through Environment Variables instead.

Connect downstream steps

Connect later steps and reference the Run Script result with {{outputs.<stepId>...}} expressions.

Configuration fields

General

Step ID
string
required
Unique identifier for this step. Use a stable ID because later steps reference outputs with this value, for example {{outputs.run-script.exitCode}}.
Step Name
string
required
Display name shown in Workflow Builder and workflow run details.
Step Timeout (minutes)
number
Maximum time the whole step can run before Overcut stops it. Defaults to 30 minutes. This remains the outer bound even when Timeout Seconds (optional) is set.

Script

Bash Script
string
required
Inline bash script to execute. The script is required and must not be empty.
Working Directory (optional)
string
Relative path inside the workflow workspace. Use this to run a script inside a repository cloned by an earlier git.clone step. This field can use workflow expressions, for example {{outputs.clone-repo.workspacePath}}.
Timeout Seconds (optional)
integer
Maximum script runtime in seconds. Defaults to 1800. The effective limit is bounded by Step Timeout (minutes).

Environment Variables

Environment Variables
object
Key-value pairs exposed to the script as environment variables. Names must be valid shell identifiers, such as TICKET_TITLE or BUILD_ID. Values can use dynamic workflow expressions such as {{trigger.title}} and {{outputs.previous-step.field}}.

Pass data into scripts

Do not template-interpolate dynamic workflow data directly into Bash Script. Trigger titles, comments, and agent output can contain characters that have special meaning in bash. Instead, put dynamic values in Environment Variables and read them in the script.
steps:
  - id: "summarize-title"
    name: "Summarize Trigger Title"
    action: "script.run"
    params:
      script: |
        echo "Title: $TRIGGER_TITLE"
        printf '{"titleLength": %d}\n' "${#TRIGGER_TITLE}" > "$OC_OUTPUT_FILE"
      env:
        TRIGGER_TITLE: "{{trigger.title}}"
Use standard double braces for escaped values and triple braces for raw values. Triple braces are useful when passing agent prose or other text that should arrive without escaping.
steps:
  - id: "inspect-agent-summary"
    name: "Inspect Agent Summary"
    action: "script.run"
    params:
      script: |
        echo "Agent summary length: ${#AGENT_SUMMARY}"
      env:
        ISSUE_TITLE: "{{trigger.title}}"
        PREVIOUS_FIELD: "{{outputs.previous-step.field}}"
        AGENT_SUMMARY: "{{{outputs.agent-step.message}}}"
Inside the script, quote environment variables like "$ISSUE_TITLE" so bash treats the value as data.

Use secrets safely

Project secrets attached to the workflow are available to Run Script as environment variables. Use them for API tokens, package registry credentials, or other sensitive values needed by deterministic commands.
Do not print secrets. Run Script captures stdout and stderr in workflow run logs and stores captured output in the step result.
A safer pattern is to test that a secret is present without echoing the value:
if [ -z "$PACKAGE_TOKEN" ]; then
  echo "PACKAGE_TOKEN is missing"
  exit 1
fi

echo "Package token is configured"
See Vault for project secret configuration and assignment.

Return structured output with $OC_OUTPUT_FILE

Run Script always captures exitCode and stdout. To pass structured values to later steps, write valid JSON to the file path stored in $OC_OUTPUT_FILE.
steps:
  - id: "collect-build-info"
    name: "Collect Build Info"
    action: "script.run"
    params:
      script: |
        BUILD_ID="build-$(date +%s)"
        printf '{"buildId": "%s", "ready": true}\n' "$BUILD_ID" > "$OC_OUTPUT_FILE"
Later steps can reference parsed fields under output:
steps:
  - id: "use-build-info"
    name: "Use Build Info"
    action: "agent.run"
    instruction: |
      The build ID is {{outputs.collect-build-info.output.buildId}}.
Use {{outputs.<stepId>.output.<field>}} for values written to $OC_OUTPUT_FILE. Use {{outputs.<stepId>.exitCode}}, {{outputs.<stepId>.stdout}}, or {{outputs.<stepId>.truncated}} for the standard result fields.

Execution results and failure behavior

Run Script stores the step result under outputs.<stepId>.
exitCode
number
required
Script exit code. 0 means the step succeeded. Non-zero values fail the step and workflow run. A timeout reports exit code 124.
stdout
string
required
Captured stdout and stderr from the script. The stored value may be truncated.
truncated
boolean
required
Whether captured stdout and stderr were truncated before being stored.
output
object
Parsed JSON object written to $OC_OUTPUT_FILE. Omitted when the output file is missing or empty.
outputParseError
string
Error recorded when $OC_OUTPUT_FILE exists but contains invalid JSON or JSON that is too large. This does not fail an otherwise successful script.
Behavior summary:
BehaviorResult
Script exits 0Step succeeds.
Script exits non-zeroStep fails and the workflow run fails.
Script exceeds its timeoutStep fails with exitCode 124.
Script writes to stdout or stderrOutput is captured in stdout and may be truncated.
$OC_OUTPUT_FILE is missing or emptyStep can still succeed. output is omitted.
$OC_OUTPUT_FILE contains invalid or too-large JSONStep can still succeed if exitCode is 0. outputParseError is recorded.

Validation rules

Overcut validates Run Script configuration when you save the workflow.
FieldRule
Bash ScriptRequired and non-empty.
Working Directory (optional)Must be a relative path inside the workspace. It cannot start with /, use a Windows drive prefix, or include .. path segments.
Variable NameMust be a valid shell identifier matching letters, numbers, and underscores, and cannot start with a number.
Variable Name with OC_ prefixNot allowed. OC_ is reserved for Overcut runtime variables such as OC_OUTPUT_FILE.
Timeout Seconds (optional)Must be a positive integer with a maximum of 21600 seconds.

Examples

Run inside a cloned repository

Use git.clone first, then set Working Directory (optional) to the cloned repository folder.
steps:
  - id: "clone-repo"
    name: "Clone Repository"
    action: "git.clone"
    params:
      repoFullName: "{{trigger.repository.fullName}}"
      branch: "{{trigger.pullRequest.headBranch}}"

  - id: "inspect-repo"
    name: "Inspect Repository"
    action: "script.run"
    params:
      cwd: "{{outputs.clone-repo.workspacePath}}"
      script: |
        SHA=$(git log -1 --format=%H)
        BRANCH=$(git rev-parse --abbrev-ref HEAD)
        printf '{"sha": "%s", "branch": "%s"}\n' "$SHA" "$BRANCH" > "$OC_OUTPUT_FILE"

Chain script output into another script

steps:
  - id: "produce-output"
    name: "Produce Output"
    action: "script.run"
    params:
      script: |
        echo '{"buildId": "build-7788", "color": "blue"}' > "$OC_OUTPUT_FILE"

  - id: "consume-output"
    name: "Consume Output"
    action: "script.run"
    params:
      script: |
        echo "Received build $BUILD_ID with color $COLOR"
        printf '{"label": "%s-%s"}\n' "$BUILD_ID" "$COLOR" > "$OC_OUTPUT_FILE"
      env:
        BUILD_ID: "{{outputs.produce-output.output.buildId}}"
        COLOR: "{{outputs.produce-output.output.color}}"

Fail fast on a validation command

steps:
  - id: "check-package"
    name: "Check Package Metadata"
    action: "script.run"
    params:
      script: |
        test -f package.json || { echo "package.json not found"; exit 2; }
        node -e 'JSON.parse(require("fs").readFileSync("package.json", "utf8"))'
If package.json is missing or invalid, the script exits non-zero and the step fails.