From jira
Finds suitable JIRA tickets from the backlog by analyzing priority and activity, selecting unassigned or bot-assigned tickets across Critical, High, Normal, and Low priorities.
How this command is triggered — by the user, by Claude, or both
Slash command
/jira:backlog [project-key] [--assignee username] [--days-inactive N]The summary Claude sees in its command listing — used to decide when to auto-load this command
## Name jira:backlog ## Synopsis ## Description The `jira:backlog` command helps identify suitable tickets from the JIRA backlog to work on by **intelligently analyzing** unassigned tickets and bot-assigned tickets. Unlike simple filtering, this command reads ticket descriptions, comments, and activity patterns to recommend the best candidates for work. **Key Feature:** The command selects **2 tickets from each priority level** (Critical, High, Normal, Low) that are **actually available to pick up** (unassigned or assigned to bots only), giving you a balanced view across all priorities...
jira:backlog
/jira:backlog [project-key] [--assignee username] [--days-inactive N]
The jira:backlog command helps identify suitable tickets from the JIRA backlog to work on by intelligently analyzing unassigned tickets and bot-assigned tickets. Unlike simple filtering, this command reads ticket descriptions, comments, and activity patterns to recommend the best candidates for work.
Key Feature: The command selects 2 tickets from each priority level (Critical, High, Normal, Low) that are actually available to pick up (unassigned or assigned to bots only), giving you a balanced view across all priorities so you can choose based on your expertise and preference.
Important: This command only recommends tickets that are unassigned or assigned to bots (like "OCP DocsBot"). Tickets assigned to real people are excluded, even if they have no recent activity, because they may already be claimed by someone.
This command is particularly useful for:
How it works:
This command uses direct REST API calls (via curl) instead of MCP tools because MCP has performance issues when fetching large datasets — tool result size limits cause 413 errors, and processing hundreds of tickets through MCP commands creates excessive context usage.
JIRA credentials must be set as environment variables:
| Variable | Description |
|---|---|
JIRA_URL | Jira instance URL (e.g., https://redhat.atlassian.net) |
JIRA_USERNAME | Atlassian account email address |
JIRA_API_TOKEN | Atlassian API token from Atlassian API tokens |
To verify your credentials work, test with a curl call (the same auth method this command uses):
curl -s -o /dev/null -w "%{http_code}" -H "Authorization: Basic $(printf '%s:%s' "$JIRA_USERNAME" "$JIRA_API_TOKEN" | base64 | tr -d '\n')" "$JIRA_URL/rest/api/3/myself"
JIRA_API_TOKEN and JIRA_USERNAME are correct. To regenerate your token, visit Atlassian API tokens.JIRA_URL: Verify all three environment variables are set.The command executes the following workflow:
Check Required Environment Variables
JIRA_URL, JIRA_USERNAME, and JIRA_API_TOKEN are set:
: "${JIRA_URL:?Error: JIRA_URL not set}"
: "${JIRA_USERNAME:?Error: JIRA_USERNAME not set}"
: "${JIRA_API_TOKEN:?Error: JIRA_API_TOKEN not set}"
AUTH_TOKEN="$JIRA_API_TOKEN"
Error: JIRA credentials not configured.
This command requires environment variables: JIRA_URL, JIRA_USERNAME, JIRA_API_TOKEN.
See Prerequisites section for setup instructions.
Parse Arguments and Set Defaults
mkdir -p .work/jira-backlog/{project-key}/Construct JQL Query
project = {project-key}
AND status NOT IN (Closed, Resolved, Done, Verified, Release Pending, ON_QA)
AND (
assignee IS EMPTY
OR updated <= -{days-inactive}d
)
ORDER BY priority DESC, updated ASC
AND assignee = {username} AND updated <= -{days-inactive}dFetch All Backlog Tickets Using curl with Pagination
Fetch Strategy:
maxResults value)startAt parameter) to fetch all ticketsAuthentication:
JIRA_USERNAME:JIRA_API_TOKEN (base64-encoded) for Atlassian CloudImportant API Details:
/rest/api/3/search/jql endpoint with a JSON body containing jql, fields, and maxResultsAuthorization: Basic <base64(username:token)> header for authenticationBatch Processing Loop:
START_AT=0
BATCH_NUM=0
TOTAL_FETCHED=0
while true; do
# Construct API URL for POST search
API_URL="${JIRA_URL}/rest/api/3/search/jql"
# Build JSON body for POST request
JSON_BODY=$(jq -n \
--arg jql "$JQL" \
--argjson startAt "$START_AT" \
--argjson maxResults 1000 \
'{jql: $jql, startAt: $startAt, maxResults: $maxResults, fields: ["summary","status","priority","assignee","reporter","created","updated","description","labels","components","watches","comment"]}')
# Fetch batch using curl with Basic authentication (POST)
AUTH_HEADER=$(printf '%s:%s' "$JIRA_USERNAME" "$AUTH_TOKEN" | base64 | tr -d '\n')
HTTP_CODE=$(curl -s -w "%{http_code}" \
-X POST \
-o "batch-${BATCH_NUM}.json" \
-H "Authorization: Basic ${AUTH_HEADER}" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d "$JSON_BODY" \
"${API_URL}")
# Check HTTP response code
if [ "$HTTP_CODE" -ne 200 ]; then
echo "Error: HTTP $HTTP_CODE received"
cat "batch-${BATCH_NUM}.json"
exit 1
fi
# Parse response to check if more results exist
BATCH_SIZE=$(jq '.issues | length' "batch-${BATCH_NUM}.json")
TOTAL=$(jq '.total' "batch-${BATCH_NUM}.json")
TOTAL_FETCHED=$((TOTAL_FETCHED + BATCH_SIZE))
echo "✓ Fetched ${BATCH_SIZE} tickets (${TOTAL_FETCHED}/${TOTAL} total)"
# Check if done
if [ ${TOTAL_FETCHED} -ge ${TOTAL} ] || [ ${BATCH_SIZE} -eq 0 ]; then
break
fi
# Move to next batch
START_AT=$((START_AT + 1000))
BATCH_NUM=$((BATCH_NUM + 1))
done
echo ""
echo "✓ Fetching complete: ${TOTAL_FETCHED} tickets downloaded in $((BATCH_NUM + 1)) batch(es)"
Why curl instead of MCP:
Process Batches with Python to Filter and Group by Priority
Create a Python script (.work/jira-backlog/{project-key}/process_batches.py) that:
Inputs:
.work/jira-backlog/{project-key}/batch-*.jsonProcessing Logic:
import json
import glob
from collections import defaultdict
# Load all batches
all_tickets = []
for batch_file in sorted(glob.glob('.work/jira-backlog/{project-key}/batch-*.json')):
with open(batch_file) as f:
data = json.load(f)
all_tickets.extend(data['issues'])
# Filter for available tickets
available_tickets = []
for ticket in all_tickets:
assignee = ticket['fields'].get('assignee')
# Include if unassigned
if assignee is None:
available_tickets.append(ticket)
continue
# Include if assigned to a bot
assignee_name = assignee.get('displayName', '').lower()
if 'bot' in assignee_name:
available_tickets.append(ticket)
continue
# Otherwise exclude (assigned to real person)
# Group by priority
priority_buckets = defaultdict(list)
for ticket in available_tickets:
priority_name = ticket['fields']['priority']['name']
# Normalize priority names
if priority_name in ['Critical', 'Blocker']:
priority_buckets['Critical'].append(ticket)
elif priority_name in ['High', 'Major']:
priority_buckets['High'].append(ticket)
elif priority_name in ['Normal', 'Medium']:
priority_buckets['Normal'].append(ticket)
elif priority_name in ['Low', 'Minor', 'Trivial']:
priority_buckets['Low'].append(ticket)
# Save filtered results
with open('.work/jira-backlog/{project-key}/filtered.json', 'w') as f:
json.dump(priority_buckets, f, indent=2)
# Save statistics
stats = {p: len(tickets) for p, tickets in priority_buckets.items()}
with open('.work/jira-backlog/{project-key}/stats.json', 'w') as f:
json.dump(stats, f, indent=2)
print(f"Filtered {len(available_tickets)} available tickets from {len(all_tickets)} total")
print(f"Priority distribution: {stats}")
Outputs:
.work/jira-backlog/{project-key}/filtered.json - All filtered tickets grouped by priority
.work/jira-backlog/{project-key}/stats.json - Priority distribution statistics
Run the script:
python .work/jira-backlog/${PROJECT_KEY}/process_batches.py
Intelligently Analyze and Select Best Tickets from Each Priority
CRITICAL: This is NOT a mechanical selection process. You must read and analyze ticket content to make intelligent decisions.
Load Filtered Data:
.work/jira-backlog/{project-key}/filtered.jsonFor each priority level (Critical, High, Normal, Low):
Step 6a: Extract Tickets for Human-Readable Analysis
Step 6b: Analyze Ticket Suitability Read the formatted data and evaluate each ticket for:
Age Classifications (consider when prioritizing):
Disqualifying Factors (skip these tickets):
Positive Indicators (prioritize these):
Step 6c: Select Best 2 from Each Priority
Format Output Report Generate a formatted report organized by priority:
# Backlog Tickets for {project-key}
## Search Criteria
- Project: {project-key}
- Assignee: {assignee or "Unassigned"}
- Days Inactive: {days-inactive}+
- Total Tickets Found: {count}
---
## Critical Priority ({count} tickets)
### 1. {ISSUE-KEY}: {Summary}
**Status:** {status} | **Updated:** {days} days ago | **Reporter:** {name}
**Components:** {components} | **Labels:** {labels}
**Watchers:** {count} | **Comments:** {count}
**Context:**
{2-3 sentence summary of the ticket}
**Recent Activity:**
- {Most recent comment summary or "No recent comments"}
- {Status change or "No status changes"}
- {Blocker/Question if identified}
**Recommendation:** {Why this ticket is suitable to work on or what's needed before starting}
---
### 2. {ISSUE-KEY}: {Summary}
...
---
## High Priority ({count} tickets)
...
## Normal Priority ({count} tickets)
...
## Low Priority ({count} tickets)
...
---
## Summary
- Critical: {count} tickets available
- High: {count} tickets available
- Normal: {count} tickets available
- Low: {count} tickets available
**Suggested Next Steps:**
1. Review the tickets above and select one that matches your expertise
2. Check if the ticket has clear acceptance criteria - if not, consider grooming it first using `/jira:grooming {issue-key}`
3. Use `/jira:solve {issue-key} {remote}` to start working on the ticket
Display Report to User
/jira:grooming for tickets lacking clarity/jira:solve to start working on selected ticketSave Report (Optional)
.work/jira-backlog/{project-key}-{timestamp}.mdError Handling:
JIRA_URL, JIRA_USERNAME, or JIRA_API_TOKEN are not set, display:
Error: JIRA credentials not configured.
This command requires environment variables: JIRA_URL, JIRA_USERNAME, JIRA_API_TOKEN.
See Prerequisites section for setup instructions.
Error: JIRA authentication failed (HTTP 401/403)
Please verify your JIRA credentials:
1. Check that JIRA_API_TOKEN is correct and not expired
2. Verify JIRA_USERNAME matches your Atlassian account email
3. Ensure JIRA_URL is correct (e.g., https://redhat.atlassian.net)
4. Test authentication: curl -H "Authorization: Basic $(printf '%s:%s' "$JIRA_USERNAME" "$JIRA_API_TOKEN" | base64 | tr -d '\n')" $JIRA_URL/rest/api/3/myself
To regenerate your token, visit:
https://id.atlassian.com/manage-profile/security/api-tokens
brew install jq on macOS, apt-get install jq on Linux)Performance Considerations:
.work/jira-backlog/{project-key}/batch-*.json - Raw JIRA API responses (one per 1000 tickets).work/jira-backlog/{project-key}/process_batches.py - Python script for filtering.work/jira-backlog/{project-key}/filtered.json - All filtered tickets grouped by priority.work/jira-backlog/{project-key}/stats.json - Priority distribution statistics.work/jira-backlog/{project-key}-{timestamp}.md containing the full reportNote: All examples require JIRA_URL, JIRA_USERNAME, and JIRA_API_TOKEN environment variables to be set (see Prerequisites section). The command uses curl to fetch data directly from JIRA's REST API, bypassing MCP commands to avoid 413 errors with large datasets.
Find unassigned tickets in OCPBUGS project:
/jira:backlog OCPBUGS
Output: Intelligently analyzes tickets and shows 2 recommended tickets from each priority level (Critical, High, Normal, Low)
Example performance (tested October 31, 2025):
Find stale tickets with custom inactivity threshold:
/jira:backlog OCPBUGS --days-inactive 14
Output: Report showing tickets with no activity for 14+ days, 2 per priority level
Find tickets assigned to a specific user that are stale:
/jira:backlog OCPBUGS --assignee jsmith --days-inactive 30
Output: Report showing tickets assigned to jsmith with 30+ days of inactivity, 2 per priority level
Find tickets in Hypershift project:
/jira:backlog HYPE
Output: Analyzes backlog and shows best 2 tickets from each priority in HYPE project
Find tickets in CNV project:
/jira:backlog CNV
Output: Report showing available backlog tickets across all priorities in CNV project
Performance Note: The curl-based approach can handle large backlogs efficiently. In testing with OCPBUGS (2,535 tickets), the command successfully fetched and processed all tickets without hitting Claude's token limits or encountering 413 errors.
--assignee (optional): Filter by assignee username
--assignee jsmith finds jsmith's stale tickets--days-inactive (optional): Number of days of inactivity to consider a ticket stale
--days-inactive 14 finds tickets with 14+ days of no activitynpx claudepluginhub p/fsgreco-jira-plugins-jira/backlogFinds suitable JIRA tickets from the backlog by analyzing priority and activity, selecting unassigned or bot-assigned tickets across Critical, High, Normal, and Low priorities.
/issue-listLists and filters tickets from supported backends (GitHub, Jira, Linear, Gitea) or local files, with status, label, assignee filters and table/JSON/markdown output.
/list-jirasQueries JIRA bug data for a project with optional filters (--component, --status, --include-closed, --limit). Returns raw issue data without summarization.
/jiraInteracts with Jira tickets — fetches and analyzes tickets, adds comments, transitions status, and searches via JQL.
/backlogConverts ArcKit requirements into a prioritized product backlog with GDS-compliant user stories, organized into sprints with multi-factor scoring.