About tfc-list-runs
A skill for listing and filtering Terraform Cloud runs in workspaces or across an organization. It supports searches by status, operation, source, commit, or user, with formatted output for review or further processing.
Key features
- 01List workspace or organization runs
- 02Filter by status, operation, and source
- 03Search by commit or user
- 04Format results as tables or JSON
- 05Paginate through run results
Use cases
- 01Review recent workspace runs
- 02Find runs with errors or a given status
- 03Locate runs associated with a commit or user
- 04Process run data in scripts
Install
Copy the command and run it in a terminal.
npx skills add https:/ / github.com/ laurigates/ claude-plugins --skill tfc-list-runsAfter installing, type/tfc-list-runsin Claude Code to confirm it loaded.
Details
From the project READMETerraform Cloud List Runs
List and filter runs from Terraform Cloud workspaces with formatted output.
When to Use
| Scenario | Use this skill | Alternative |
|---|---|---|
| List recent runs for any TFC workspace | tfc-list-runs | - |
| Filter runs by status, operation, or source | tfc-list-runs | - |
| List runs across an entire org | tfc-list-runs | - |
| Search runs by commit SHA or user | tfc-list-runs | - |
| Quick status of a single known run ID | tfc-run-status | Use run-status for one run's details |
| View plan/apply log output for a run | tfc-run-logs | Use run-logs for log content |
| Analyze structured plan JSON | tfc-plan-json | Use plan-json for resource change details |
| List runs for known Forum Virium workspaces | tfc-workspace-runs | Use workspace-runs for shorthand access |
Prerequisites
export TFE_TOKEN="your-api-token" # User or team token
export TFE_ADDRESS="app.terraform.io" # Optional
Core Commands
List Recent Runs for a Workspace
#!/bin/bash
set -euo pipefail
TOKEN="${TFE_TOKEN:?TFE_TOKEN not set}"
BASE_URL="https://${TFE_ADDRESS:-app.terraform.io}/api/v2"
WORKSPACE_ID="${1:?Usage: $0 <workspace-id> [limit]}"
LIMIT="${2:-10}"
curl -sf --header "Authorization: Bearer $TOKEN" \
"$BASE_URL/workspaces/$WORKSPACE_ID/runs?page[size]=$LIMIT" | \
jq -r '.data[] | [
.id,
.attributes.status,
.attributes."created-at"[0:19],
(.attributes.message // "No message")[0:50]
] | @tsv' | \
column -t -s $'\t'
List Runs by Workspace Name (requires org)
TOKEN="${TFE_TOKEN:?TFE_TOKEN not set}"
BASE_URL="https://${TFE_ADDRESS:-app.terraform.io}/api/v2"
ORG="ForumViriumHelsinki"
WORKSPACE="infrastructure-gcp"
# Get workspace ID first
WS_ID=$(curl -sf --header "Authorization: Bearer $TOKEN" \
"$BASE_URL/organizations/$ORG/workspaces/$WORKSPACE" | \
jq -r '.data.id')
# List runs
curl -sf --header "Authorization: Bearer $TOKEN" \
"$BASE_URL/workspaces/$WS_ID/runs?page[size]=10" | \
jq -r '.data[] | "\(.id) | \(.attributes.status) | \(.attributes."created-at"[0:19]) | \(.attributes.message // "No message")"'
Filter by Status
TOKEN="${TFE_TOKEN:?TFE_TOKEN not set}"
BASE_URL="https://${TFE_ADDRESS:-app.terraform.io}/api/v2"
WORKSPACE_ID="ws-abc123"
# Filter by single status
curl -sf --header "Authorization: Bearer $TOKEN" \
"$BASE_URL/workspaces/$WORKSPACE_ID/runs?filter[status]=errored" | \
jq -r '.data[] | "\(.id) | \(.attributes.status) | \(.attributes."created-at")"'
# Filter by multiple statuses
curl -sf --header "Authorization: Bearer $TOKEN" \
"$BASE_URL/workspaces/$WORKSPACE_ID/runs?filter[status]=errored,canceled" | \
jq -r '.data[] | "\(.id) | \(.attributes.status)"'
Filter by Status Group
# Non-final runs (in progress)
curl -sf --header "Authorization: Bearer $TOKEN" \
"$BASE_URL/workspaces/$WORKSPACE_ID/runs?filter[status_group]=non_final"
# Final runs (completed)
curl -sf --header "Authorization: Bearer $TOKEN" \
"$BASE_URL/workspaces/$WORKSPACE_ID/runs?filter[status_group]=final"
# Discardable runs
curl -sf --header "Authorization: Bearer $TOKEN" \
"$BASE_URL/workspaces/$WORKSPACE_ID/runs?filter[status_group]=discardable"
Include Plan-Only Runs
By default, plan-only runs are excluded. To include them:
curl -sf --header "Authorization: Bearer $TOKEN" \
"$BASE_URL/workspaces/$WORKSPACE_ID/runs?filter[operation]=plan_and_apply,plan_only,save_plan,refresh_only,destroy"
List Runs Across Organization
TOKEN="${TFE_TOKEN:?TFE_TOKEN not set}"
BASE_URL="https://${TFE_ADDRESS:-app.terraform.io}/api/v2"
ORG="ForumViriumHelsinki"
# All runs in org (limited info, no total count)
curl -sf --header "Authorization: Bearer $TOKEN" \
"$BASE_URL/organizations/$ORG/runs?page[size]=20" | \
jq -r '.data[] | "\(.id) | \(.attributes.status)"'
# Filter by workspace names
curl -sf --header "Authorization: Bearer $TOKEN" \
"$BASE_URL/organizations/$ORG/runs?filter[workspace_names]=infrastructure-gcp,infrastructure-github"
Formatted Output Examples
Table Format with Resource Changes
curl -sf --header "Authorization: Bearer $TOKEN" \
"$BASE_URL/workspaces/$WORKSPACE_ID/runs?page[size]=10&include=plan" | \
jq -r '
["RUN_ID", "STATUS", "ADD", "CHG", "DEL", "CREATED"],
(.data[] | [
.id,
.attributes.status,
(.relationships.plan.data.id as $pid |
(.included[] | select(.id == $pid) | .attributes."resource-additions" // 0)),
(.relationships.plan.data.id as $pid |
(.included[] | select(.id == $pid) | .attributes."resource-changes" // 0)),
(.relationships.plan.data.id as $pid |
(.included[] | select(.id == $pid) | .attributes."resource-destructions" // 0)),
.attributes."created-at"[0:19]
]) | @tsv' | column -t
JSON Output for Further Processing
curl -sf --header "Authorization: Bearer $TOKEN" \
"$BASE_URL/workspaces/$WORKSPACE_ID/runs?page[size]=5" | \
jq '[.data[] | {
id: .id,
status: .attributes.status,
created: .attributes."created-at",
message: .attributes.message,
has_changes: .attributes."has-changes",
auto_apply: .attributes."auto-apply"
}]'
Available Filter Parameters
| Parameter | Description | Example Values |
|---|---|---|
filter[status] | Run status | applied, errored, planned, canceled |
filter[status_group] | Status group | non_final, final, discardable |
filter[operation] | Operation type | plan_and_apply, plan_only, destroy |
filter[source] | Run source | tfe-api, tfe-ui, tfe-configuration-version |
filter[timeframe] | Time period | 2024, year, month |
search[user] | VCS username | Username string |
search[commit] | Commit SHA | SHA string |
search[basic] | Combined search | Search term |
Run Statuses
Final States: applied, planned_and_finished, discarded, errored, canceled, force_canceled, policy_soft_failed
Non-Final States: pending, planning, planned, cost_estimating, policy_checking, confirmed, applying, and others
Pagination
# Page 2 with 20 items per page
curl -sf --header "Authorization: Bearer $TOKEN" \
"$BASE_URL/workspaces/$WORKSPACE_ID/runs?page[number]=2&page[size]=20"
# Check pagination info
curl -sf --header "Authorization: Bearer $TOKEN" \
"$BASE_URL/workspaces/$WORKSPACE_ID/runs" | \
jq '.meta.pagination'
Rate Limiting
The /runs endpoint has a special rate limit of 30 requests/minute (not 30/second like most endpoints). Plan accordingly when scripting.
See Also
tfc-run-logs: Get plan/apply logs for a runtfc-run-status: Quick status check for a runtfc-workspace-runs: Convenience wrapper for known workspaces