Skip to content

Step Configuration

Steps are the building blocks of Bivvy workflows. Each step represents a task to be executed during setup.

Basic Step

steps:
install_deps:
command: npm install
title: Install dependencies
description: Install Node.js dependencies from package.json

title is the short label shown in CLI output and progress indicators; description is a longer human-readable explanation shown in bivvy list and other reflective commands.

Sensitive Steps

Mark steps that handle sensitive data:

steps:
fetch-secrets:
command: vault read secret/myapp
sensitive: true
description: Fetch secrets from Vault

Sensitive steps receive special treatment:

  1. Confirmation prompt: In interactive mode, Bivvy asks for confirmation before running sensitive steps

  2. Hidden in dry-run: The actual command is not shown during --dry-run, displaying [SENSITIVE - command hidden] instead

  3. Suppressed output: Command output is not logged to prevent accidental exposure of sensitive data

  4. No history: Sensitive commands are not recorded in execution history

Auto-Run Behavior

By default, steps that need to run execute automatically. Steps that are already satisfied (via checks, satisfied_when, or recent execution history) prompt you before re-running. You can control this per-step:

steps:
install_deps:
command: npm install
auto_run: true # run without asking (default)
confirm: false # always prompt before running (default: false)
prompt_on_rerun: false # skip silently if already satisfied
rerun_window: "24h" # trust a successful run for 24 hours

Setting confirm: true forces the step to always prompt before running, regardless of auto_run. This is useful for destructive or irreversible operations.

See Auto-Run and the Decision Engine for the full explanation of how Bivvy decides whether to run, skip, or prompt for each step.

Always Re-run a Step

Mark a step force: true to always re-run it, bypassing its check, checks, and satisfied_when evaluation. Equivalent to listing the step in --force on every run:

steps:
migrate:
command: "bin/rails db:migrate"
force: true

Preconditions still apply — they are never bypassed by force. See Forcing Re-run for the related CLI flags.

Continuing After Failure

Set allow_failure: true to let a step fail without aborting the workflow. The run continues with the next step, and the failure is reported in the summary.

steps:
optional_lint:
command: "yarn lint"
allow_failure: true

Use this for non-critical steps where the workflow should still finish even if the step exits non-zero.

Retries

Re-attempt a step if its command exits non-zero. retry is the number of additional attempts after the first failure (so retry: 2 runs the command up to three times total before reporting failure):

steps:
flaky_test:
command: "yarn test:e2e"
retry: 2

Elevated Permissions

Mark steps that require sudo so Bivvy can warn ahead of time and avoid mid-run password prompts in unexpected places.

steps:
install_system_pkg:
command: "sudo apt-get install -y postgresql-client"
requires_sudo: true

Completed Checks

Determine if a step is already complete:

steps:
node_modules:
command: npm install
check:
type: presence
target: node_modules
bundle:
command: bundle install
check:
type: execution
command: bundle check
validation: success

Check Types

  • presence: Check if a file, directory, or binary exists
  • execution: Check if a command exits with code 0
  • change: Detect if a target has changed from baseline
  • all: All sub-checks must pass
  • any: At least one sub-check must pass

Satisfaction Conditions

Use satisfied_when to declare when a step’s purpose is already fulfilled, based on multiple conditions or checks from other steps. All conditions must pass for the step to be skipped.

steps:
build:
command: "yarn build"
depends_on: [install_deps]
satisfied_when:
- ref: install_deps.deps_present
- type: presence
target: "dist"

When satisfied_when is present, it takes priority over check — if the conditions fail, the step runs even if check alone would have passed. See Checks for the full syntax and evaluation rules.

Preconditions

A precondition is a gate that must pass before a step runs. If the precondition fails, the step fails immediately with a hard error.

steps:
release:
command: "git tag v1.0.0 && git push --tags"
precondition:
type: execution
command: "test $(git branch --show-current) = main"
validation: success

Preconditions use the same check types as check (execution, presence, all, any, etc.) but with opposite semantics:

checkprecondition
When check passesStep is skipped (already done)Step proceeds normally
When check failsStep runsStep fails (hard stop)
--force / --force-all behaviorBypasses the checkNo effect (never bypassed)

Combining with Completed Checks

When a step has both check and precondition, the completed check is evaluated first. If the step is already complete, it is skipped and the precondition is never evaluated.

steps:
release:
command: "git tag v1.0.0 && git push --tags"
check:
type: execution
command: "git tag -l v1.0.0 | grep -q v1.0.0"
validation: success
precondition:
type: all
checks:
- type: execution
command: "test $(git branch --show-current) = main"
validation: success
- type: execution
command: "git diff --quiet"
validation: success

Dependencies

Specify step dependencies:

steps:
database:
command: rails db:setup
depends_on: [deps, migrations]

Environment Variables

Set step-specific environment variables:

steps:
test:
command: npm test
env:
NODE_ENV: test
CI: "true"
env_file: .env.test
env_file_optional: false # default: fail if env_file is missing

Set env_file_optional: true to silently skip a missing env file instead of failing — useful when the file may exist on developer machines but not in CI:

steps:
dev_only:
command: bin/dev
env_file: .env.local
env_file_optional: true

Required Environment Variables

required_env lists environment variable names that must be present (non-empty) when the step runs. If any are missing, the step fails before its command executes:

steps:
deploy:
command: bin/deploy
required_env:
- DEPLOY_KEY
- TARGET_HOST

Environment Variable Precedence

Bivvy layers env vars from broadest scope to narrowest, then lets the shell win on top. Lowest priority first:

  1. settings.env_file — global file declared in project settings
  2. settings.env — global inline values
  3. workflow.env_file — file declared on the active workflow
  4. workflow.env — inline values declared on the active workflow
  5. step.env_file — file declared on the step
  6. step.env — inline values on the step (per-environment overrides are merged into this layer; see Per-Environment Overrides)
  7. Parent process environment — variables exported in your shell

The parent process env wins last, so DATABASE_URL=postgres://override bivvy run will override any DATABASE_URL declared in YAML. This matches how Make, npm scripts, and docker run -e handle command-line env overrides.

Hooks

Run commands before and after the step:

steps:
database:
command: rails db:setup
before:
- echo "Starting database setup..."
after:
- echo "Database ready!"

Requirements

Declare system-level prerequisites that must be available before a step runs. The canonical field name is tools; the old name requires is accepted as an alias for backward compatibility.

steps:
bundle_install:
command: bundle install
tools:
- ruby
- postgres-server

When a requirement is missing, Bivvy offers to install it before running the step. See Requirements for the full list of built-in requirement names and custom requirement definitions.

Environment Filtering

Restrict a step to specific environments with only_environments:

steps:
seed_data:
command: rails db:seed
only_environments:
- development
- staging

Steps with an empty list (the default) run in all environments.

Per-Environment Overrides

Override step fields for specific environments:

steps:
database_setup:
command: rails db:setup
env:
RAILS_ENV: development
environments:
ci:
command: rails db:schema:load
env:
RAILS_ENV: test
docker:
env:
DATABASE_HOST: db
RAILS_ENV: null # Removes RAILS_ENV in Docker

Only the fields you specify are overridden; everything else inherits from the base step. Set an env var to null to remove it for that environment.

See Environments for all overridable fields and detection configuration.