tfc-run-logs
Retrieve plan and apply logs from Terraform Cloud runs. Use when debugging failed plans/applies or reviewing TFC run output. Requires TFE_TOKEN.
Works with
---
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.
license: MIT
---
# 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
```bash
# Required environment variables
export TFE_TOKEN="your-api-token" # User or team token (not organization token)
export TFE_ADDRESS="app.terraform.io" # Optional, defaults to app.terraform.io
```
## Core Workflow
### Get Both Plan and Apply Logs
```bash
#!/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>}"
# Get run with plan and apply relationships
RUN_DATA=$(curl -sf --header "Authorization: Bearer $TOKEN" \
"$BASE_URL/runs/$RUN_ID?include=plan,apply")
# Extract IDs
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')
# Get and display plan logs
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' # Strip ANSI codes
# Get apply logs if exists
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"')
echo ""
echo "=== APPLY OUTPUT ==="
curl -sf "$APPLY_LOG_URL" | sed 's/\x1b\[[0-9;]*m//g'
fi
```
### Get Plan Logs Only
```bash
TOKEN="${TFE_TOKEN:?TFE_TOKEN not set}"
BASE_URL="https://${TFE_ADDRESS:-app.terraform.io}/api/v2"
RUN_ID="run-abc123"
# Get plan ID from run
PLAN_ID=$(curl -sf --header "Authorization: Bearer $TOKEN" \
"$BASE_URL/runs/$RUN_ID" | jq -r '.data.relationships.plan.data.id')
# Get log URL and fetch logs
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
```bash
TOKEN="${TFE_TOKEN:?TFE_TOKEN not set}"
BASE_URL="https://${TFE_ADDRESS:-app.terraform.io}/api/v2"
RUN_ID="run-abc123"
# Get apply ID from run
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
# Get log URL and fetch logs
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)
```bash
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)
```bash
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 outputMore Debugging skills
diagnosing-bugs
mattpocock/skills
Diagnosis loop for hard bugs and performance regressions. Use when the user says "diagnose"/"debug this", or reports something broken/throwing/failing/slow.
explore-code
lllllllama/rigorpilot-skills
Rigor Improve implementation leaf skill for auditable candidate implementation in deep learning research repositories. Use when the researcher explicitly authorizes exploratory work on an isolated branch or worktree to transplant modules, adapt a backbone, add LoRA or adapter layers, replace a head, or stitch together meaningful low-risk migration ideas with rollback-aware records in `explore_outputs/`. Do not use for end-to-end exploration orchestration on top of `current_research`, trusted baseline reproduction, conservative debugging, environment setup, verified contribution claims, or default repository analysis.
safe-debug
lllllllama/rigorpilot-skills
Rigor Debug / Rigor Audit skill for deep learning research work. Use when the user pastes a traceback, terminal error, CUDA OOM, checkpoint load failure, shape mismatch, NaN loss symptom, or training failure and wants conservative diagnosis before any patching, with debug fixes clearly separated from research contributions. Do not use for broad refactoring, speculative adaptation, automatic exploratory patching, or general repository familiarization.

