Managing log output
Organize Buildkite Pipelines logs to find failures faster. Save complete command output while filtering or truncating noisy logs.
- Organize output into collapsible groups.
- Manage large logs without losing the original command output.
- Protect sensitive values with log redaction.
- Summarize failures with a build annotation so readers don't need to search the full log.
Grouping log output
Print a grouping marker at the start of a line to create a log heading. Output belongs to that group until the next heading.
| Marker | Behavior |
|---|---|
--- |
Starts a collapsed group |
+++ |
Starts an expanded group |
~~~ |
Starts a collapsed, de-emphasized group |
^^^ +++ |
Expands the previous group, optionally updating its title |
Collapsed groups
Use --- for output that readers can expand when needed:
echo "--- A section of the build"
Expanded groups
Use +++ for output that should be open by default:
echo "+++ A section of the build"
If no group is explicitly expanded (+++), the last regular collapsed group (---) opens instead. To prevent that fallback, add this empty-looking expanded group at the end of your output:
echo -e "+++ \032"
# The \032 escape emits ASCII SUB (0x1A), not a space
De-emphasized groups
Use ~~~ for less important output. These groups start collapsed and use non-bold titles:
echo "~~~ An unimportant section of the build"
The controls in this section are available to organizations where de-emphasized job log groups are enabled in the new build experience.
On the Buildkite Pipelines build page, consecutive de-emphasized groups are folded into inline expander rows. Folding hides the group headings as well as their output. Expanding a group opens its output without revealing other folded groups.
- Select an expander row to reveal those groups temporarily.
- Select Show system groups in the log toolbar to reveal all folded groups. Its tooltip shows the hidden group count. Select Hide system groups to fold them again.
- Select Configure view > Show all system groups to keep de-emphasized groups visible on future visits. This menu also controls the log theme and timestamps.
- Select Expand groups or Collapse groups to open or close all visible groups without revealing folded groups.
The default group that reports the running script, commands, or command hooks, such as Running commands, stays visible. Groups explicitly expanded with ^^^ +++ also stay visible. While a job runs, its active group stays visible until the job finishes.
Opening a link to a line inside a folded group reveals that group temporarily. Other groups remain folded. These actions don't change your saved Show all system groups preference.
Advanced grouping techniques
Use these techniques to highlight failures and separate stages in long logs.
Opening previous groups
Use ^^^ +++ to open the previous group, for example, when a command fails. Add a title after the marker to rename the group:
echo "--- Bundling"
if bundle; then
echo "Bundling complete"
else
status=$?
echo "^^^ +++ Bundling failed"
exit "$status"
fi
The guarded command allows failure handling even with Bash's -e option enabled. Save the original exit status before printing messages, then return it so the job still fails. See Capturing exit status for more examples.
If the previous group is de-emphasized (~~~), expanding it with ^^^ +++ keeps it visible even when other de-emphasized groups are hidden.
Creating section boundaries
Combine group types to mark stages. Only print completion headings when the corresponding command succeeds:
echo "--- Starting deployment"
if ./scripts/deployment.sh; then
echo "~~~ Deployment complete"
else
status=$?
echo "^^^ +++ Deployment failed"
exit "$status"
fi
echo "--- Running tests"
if ./scripts/tests.sh; then
echo "~~~ Tests succeeded"
else
status=$?
echo "^^^ +++ Tests failed"
exit "$status"
fi
Use ANSI escape codes (terminal control codes) for colors and emoji shortcode syntax for group titles:
echo -e "--- Running \033[33mspecs\033[0m :cow::bell:"

Buildkite Pipelines converts :emoji_name: shortcode syntax into emojis only in step labels and group header lines (text following ---, +++, ~~~, or ^^^ +++). Use the actual Unicode character in regular command output.
steps:
- label: ":rocket: Deploy"
command: |
echo "--- :rocket: Running pre-flight checks"
echo "Checking environment..."
echo "+++ :rocket: Running deploy script"
if ./deploy.sh; then
echo "Deployment complete"
else
status=$?
echo "^^^ +++"
echo "🚀 Deploy failed. Check the logs above."
exit "$$status"
fi
The failure message uses the literal 🚀 character because a shortcode there would print as plain text. In pipeline YAML, $$status defers variable expansion until the step runs.
Searching log output
To find text on the Buildkite Pipelines build page:
- Select Search logs above the build log.
- Enter a search term.
- Select Previous or Next to move between matches.
Select Match case sensitivity (Aa) to require an exact-case match.
Search includes text inside folded de-emphasized groups. Matching groups appear for the duration of the search. Closing search folds them again unless they were already visible.
If the same tests fail intermittently, collect their results in Test Engine to track failures across builds instead of comparing individual logs.
ANSI timestamps
Buildkite agent v4 always emits ANSI timestamp codes in job logs. The v3 options to disable them or use plain-text timestamps were removed. See Changes to job logs. To change timestamp visibility on the build page, use Configure view.
Log output limits
Buildkite Pipelines renders only the last two MB of output on the build page. This display limit is separate from the default 1,024 MiB per-job log size limit. Pipelines cancels jobs whose logs exceed the per-job limit. See Pipelines limits for quotas and how to request an increase.
To retrieve an existing job's stored output, download the raw log using the REST API. This cannot recover output filtered out before upload. For future builds, reduce unnecessary tool output or save the original output before filtering or truncating it.
Storing the original log
Use tee to save command output to a file while also sending it to the job log. Merge standard error into standard output with 2>&1 so the file includes both streams:
#!/bin/bash
set -euo pipefail
your_build_command 2>&1 | tee build.log
The pipefail option makes the Bash pipeline fail if any command fails, including the build command or tee. The -e option then stops the script on that failure. Without pipefail, a successful final command can hide an earlier failure.
To upload build.log as a build artifact, add artifact_paths to the command step that runs the script:
steps:
- command: bash ./build.sh
artifact_paths: "build.log"
After the command step finishes, the agent uploads build.log. Download it from the Artifacts tab on the build page.

Review raw logs before uploading
tee saves output before job-log redaction. Do not assume that saved logs or uploaded artifacts are redacted. Avoid printing secrets, and review files before uploading or sharing them.
Filtering with grep
Use grep to show only matching lines in the Buildkite Pipelines job log while saving both output streams in build.log:
#!/bin/bash
set -euo pipefail
your_build_command 2>&1 | tee build.log | (
status=0
grep 'some pattern' || status=$?
if [[ "$status" -eq 1 ]]; then
exit 0
fi
exit "$status"
)
grep returns 1 when no lines match. The parenthesized filter treats that result as success but preserves actual grep errors. With pipefail, failures from the build command or tee still fail the script, even if no lines match.
Truncating with tail
Use tail to send only the last 100,000 bytes of command output to the Buildkite Pipelines job log while saving the full output in build.log:
#!/bin/bash
set -euo pipefail
your_build_command 2>&1 | tee build.log | tail -c 100000
This retains the end of the output, not a live rolling view. tail waits for the command's output to end before printing the retained bytes. Other job output still counts toward the per-job log limit.
Improving Xcode logs with xcpretty
xcpretty reduces, formats, and color-codes Xcode build output. After installing it, pipe xcodebuild output through it. Replace MyApp with your scheme name:
#!/bin/bash
set -euo pipefail
xcodebuild -scheme MyApp build 2>&1 | tee build.log | xcpretty -c
Keep pipefail enabled so an xcodebuild failure fails the script even when xcpretty succeeds.

Encryption and security
Buildkite-managed artifacts are stored in Amazon S3 with encryption at rest. See Artifact storage, encryption, and retention for key management and self-managed storage options.
Your organization controls the credentials and systems builds can access. Agent infrastructure responsibilities depend on whether agents are hosted or self-hosted. Review the shared responsibility model for your setup.
Redacted environment variables
The Buildkite agent redacts matching environment variable values before uploading job logs. Variable names must match a configured pattern.
Values shorter than six bytes are not redacted.
The default environment variable name patterns are:
*_PASSWORD*_SECRET*_TOKEN*_PRIVATE_KEY-
*_SSH_KEY(added in Agent v3.128.0) *_ACCESS_KEY*_SECRET_KEY-
*_CONNECTION_STRING(added in Agent v3.53.0) -
*_API_KEY(added in Agent v3.120.1)
With these defaults, if you have an environment variable MY_SECRET="topsecret" and run a command that outputs This is topsecret info, the log output will be This is [REDACTED] info.
Setting redacted-vars replaces the default patterns. To add FOO while keeping the defaults, include every default pattern you want to retain:
redacted-vars="*_PASSWORD, *_SECRET, *_TOKEN, *_PRIVATE_KEY, *_SSH_KEY, *_ACCESS_KEY, *_SECRET_KEY, *_CONNECTION_STRING, *_API_KEY, FOO"
Defaults differ between agent versions. Listing your patterns explicitly keeps the configuration consistent across your fleet.
Secrets in pipeline definitions
Log redaction does not hide secret values in uploaded pipeline definitions. Do not store secrets directly in pipeline.yml or substitute their values during upload. Follow the guidance for referencing secrets in pipeline YAML to avoid exposing them outside the job log.
Job log archive storage
By default, job logs are stored in encrypted form in Buildkite-managed Amazon S3 buckets. Customers on the Enterprise plan can instead store archived job logs in their own private Amazon S3 bucket.
For setup instructions, including bucket requirements and the required bucket policy, see Job log archiving.
Next steps
- Investigate slow builds: Use the waterfall view to distinguish time waiting for an agent from time running commands.
- Open diagnostics directly: Add clickable links to log output for reports and other saved artifacts.