| created | "2025-12-16T00:00:00.000Z" |
| modified | "2026-04-25T00:00:00.000Z" |
| reviewed | "2026-04-25T00:00:00.000Z" |
| name | tfc-run-logs |
| description | Retrieve plan and apply logs from Terraform Cloud runs. Use when debugging failed plans/applies or reviewing TFC run output. Requires TFE_TOKEN. |
| user-invocable | false |
| allowed-tools | Bash, Read |
Terraform Cloud Run Logs
Retrieve and display plan and/or apply logs from Terraform Cloud runs directly in the terminal.
When to Use This Skill
| Use this skill when... | Use a sibling instead when... |
|---|
| Reading plan or apply output text for a known TFC run ID | Analyzing resource changes as structured JSON (tfc-plan-json) |
| Debugging a failed plan or apply by inspecting log lines | Checking only the pass/fail status without log content (tfc-run-status) |
| Reviewing infrastructure changes in human-readable form | Searching for the right run ID across history (tfc-list-runs) |
| Capturing logs to share with a teammate or paste into an issue | Browsing latest runs for FVH workspaces by shorthand (tfc-workspace-runs) |
Prerequisites
export TFE_TOKEN="your-api-token"
export TFE_ADDRESS="app.terraform.io"
Core Workflow
Get Both Plan and Apply Logs
#!/bin/bash
set -euo pipefail
TOKEN="${TFE_TOKEN:?TFE_TOKEN not set}"
BASE_URL="https://${TFE_ADDRESS:-app.terraform.io}/api/v2"
RUN_ID="${1:?Usage: $0 <run-id>}"
RUN_DATA=$(curl -sf --header "Authorization: Bearer $TOKEN" \
"$BASE_URL/runs/$RUN_ID?include=plan,apply")
PLAN_ID=$(echo "$RUN_DATA" | jq -r '.data.relationships.plan.data.id')
APPLY_ID=$(echo "$RUN_DATA" | jq -r '.data.relationships.apply.data.id // empty')
PLAN_LOG_URL=$(curl -sf --header "Authorization: Bearer $TOKEN" \
"$BASE_URL/plans/$PLAN_ID" | jq -r '.data.attributes."log-read-url"')
echo "=== PLAN OUTPUT ==="
curl -sf "$PLAN_LOG_URL" | sed 's/\x1b\[[0-9;]*m//g'
if [ -n "$APPLY_ID" ]; then
APPLY_LOG_URL=$(curl -sf --header "Authorization: Bearer $TOKEN" \
"$BASE_URL/applies/$APPLY_ID" | jq -r '.data.attributes."log-read-url"')
curl -sf | sed
Get Plan Logs Only
TOKEN="${TFE_TOKEN:?TFE_TOKEN not set}"
BASE_URL="https://${TFE_ADDRESS:-app.terraform.io}/api/v2"
RUN_ID="run-abc123"
PLAN_ID=$(curl -sf --header "Authorization: Bearer $TOKEN" \
"$BASE_URL/runs/$RUN_ID" | jq -r '.data.relationships.plan.data.id')
PLAN_LOG_URL=$(curl -sf --header "Authorization: Bearer $TOKEN" \
"$BASE_URL/plans/$PLAN_ID" | jq -r '.data.attributes."log-read-url"')
curl -sf "$PLAN_LOG_URL"
Get Apply Logs Only
TOKEN="${TFE_TOKEN:?TFE_TOKEN not set}"
BASE_URL="https://${TFE_ADDRESS:-app.terraform.io}/api/v2"
RUN_ID="run-abc123"
APPLY_ID=$(curl -sf --header "Authorization: Bearer $TOKEN" \
"$BASE_URL/runs/$RUN_ID" | jq -r '.data.relationships.apply.data.id')
if [ -n "$APPLY_ID" ] && [ "$APPLY_ID" != "null" ]; then
APPLY_LOG_URL=$(curl -sf --header "Authorization: Bearer $TOKEN" \
"$BASE_URL/applies/$APPLY_ID" | jq -r '.data.attributes."log-read-url"')
curl -sf "$APPLY_LOG_URL"
else
echo "No apply for this run"
fi
Quick One-Liners
Plan Logs (with ANSI colors)
curl -sf -H "Authorization: Bearer $TFE_TOKEN" \
"https://app.terraform.io/api/v2/runs/run-abc123?include=plan" | \
jq -r '.included[0].attributes."log-read-url"' | xargs curl -sf
Plan Logs (clean text)
curl -sf -H "Authorization: Bearer $TFE_TOKEN" \
"https://app.terraform.io/api/v2/runs/run-abc123?include=plan" | \
jq -r '.included[0].attributes."log-read-url"' | \
xargs curl -sf | sed 's/\x1b\[[0-9;]*m//g'
Important Notes
- Log URLs are secrets: Archivist URLs contain embedded authentication - don't log them
- URLs expire: Log URLs are valid for 25 hours
- No auth needed for logs: Once you have the archivist URL, no bearer token is required
- ANSI codes: Logs contain color codes; use
sed to strip them for clean output
- Rate limits:
/runs endpoint is limited to 30 requests/minute
Common Errors
404 Not Found
- Run ID doesn't exist OR you don't have permission
- TFC returns 404 for both cases (security measure)
401 Unauthorized
- Token is invalid or expired
- Organization tokens cannot access run data - use user/team token
No Apply Logs
- Run may be plan-only, not yet applied, or discarded
- Check run status first
See Also
tfc-run-status: Quick status check for a run
tfc-list-runs: List recent runs in a workspace
tfc-plan-json: Get structured plan JSON output