From jiragenius
This skill covers batch create, update, delete, and transition operations for the Jira Cloud REST API.
How this skill is triggered — by the user, by Claude, or both
Slash command
/jiragenius:bulk-operationsThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
This skill covers batch create, update, delete, and transition operations for the Jira Cloud REST API.
This skill covers batch create, update, delete, and transition operations for the Jira Cloud REST API.
POST /rest/api/3/issue/bulk
Create up to 50 issues in a single request:
curl -X POST \
-H "Authorization: Basic $(echo -n '$JIRA_USER_EMAIL:$JIRA_API_TOKEN' | base64)" \
-H "Content-Type: application/json" \
"https://{domain}.atlassian.net/rest/api/3/issue/bulk" \
-d '{
"issueUpdates": [
{
"fields": {
"project": { "key": "PROJ" },
"issuetype": { "name": "Task" },
"summary": "Task 1",
"description": {
"type": "doc",
"version": 1,
"content": [
{
"type": "paragraph",
"content": [
{ "type": "text", "text": "Description for task 1" }
]
}
]
}
}
},
{
"fields": {
"project": { "key": "PROJ" },
"issuetype": { "name": "Task" },
"summary": "Task 2"
}
},
{
"fields": {
"project": { "key": "PROJ" },
"issuetype": { "name": "Bug" },
"summary": "Bug 1",
"priority": { "name": "High" }
}
}
]
}'
Response:
{
"issues": [
{ "id": "10001", "key": "PROJ-101", "self": "https://..." },
{ "id": "10002", "key": "PROJ-102", "self": "https://..." },
{ "id": "10003", "key": "PROJ-103", "self": "https://..." }
],
"errors": []
}
Partial failures are possible — check the errors array.
Jira Cloud does not have a single "bulk update" endpoint. Use a loop pattern:
#!/bin/bash
# Bulk update issues matching a JQL query
JQL="project = PROJ AND status = 'Open' AND labels = 'needs-triage'"
START_AT=0
MAX_RESULTS=50
TOTAL=1
while [ $START_AT -lt $TOTAL ]; do
RESPONSE=$(curl -s -X POST \
-u "$JIRA_USER_EMAIL:$JIRA_API_TOKEN" \
-H "Content-Type: application/json" \
"$JIRA_BASE_URL/rest/api/3/search/jql" \
-d "{
\"jql\": \"$JQL\",
\"startAt\": $START_AT,
\"maxResults\": $MAX_RESULTS,
\"fields\": [\"key\"]
}")
TOTAL=$(echo "$RESPONSE" | jq '.total')
KEYS=$(echo "$RESPONSE" | jq -r '.issues[].key')
for KEY in $KEYS; do
echo "Updating $KEY..."
curl -s -X PUT \
-u "$JIRA_USER_EMAIL:$JIRA_API_TOKEN" \
-H "Content-Type: application/json" \
"$JIRA_BASE_URL/rest/api/3/issue/$KEY" \
-d '{
"fields": {
"labels": ["triaged"],
"priority": { "name": "Medium" }
}
}'
# Rate limiting: wait between requests
sleep 0.2
done
START_AT=$((START_AT + MAX_RESULTS))
done
echo "Bulk update complete."
import requests
import time
base_url = "https://your-domain.atlassian.net"
auth = ("[email protected]", "api-token")
jql = 'project = PROJ AND status = "Open"'
start_at = 0
max_results = 50
updated = 0
while True:
response = requests.post(
f"{base_url}/rest/api/3/search/jql",
auth=auth,
json={
"jql": jql,
"startAt": start_at,
"maxResults": max_results,
"fields": ["key"]
}
)
data = response.json()
for issue in data["issues"]:
key = issue["key"]
update_response = requests.put(
f"{base_url}/rest/api/3/issue/{key}",
auth=auth,
json={
"fields": {
"priority": {"name": "Medium"}
}
}
)
if update_response.status_code == 204:
updated += 1
print(f"Updated {key}")
else:
print(f"Failed to update {key}: {update_response.status_code}")
time.sleep(0.2) # Rate limiting
if start_at + max_results >= data["total"]:
break
start_at += max_results
print(f"Updated {updated} issues")
Transition multiple issues through a workflow step:
#!/bin/bash
# Bulk transition issues to "Done"
# First, find the transition ID
TRANSITION_ID=$(curl -s \
-u "$JIRA_USER_EMAIL:$JIRA_API_TOKEN" \
"$JIRA_BASE_URL/rest/api/3/issue/PROJ-1/transitions" \
| jq -r '.transitions[] | select(.name == "Done") | .id')
echo "Using transition ID: $TRANSITION_ID"
# Search for issues to transition
RESPONSE=$(curl -s -X POST \
-u "$JIRA_USER_EMAIL:$JIRA_API_TOKEN" \
-H "Content-Type: application/json" \
"$JIRA_BASE_URL/rest/api/3/search/jql" \
-d '{
"jql": "project = PROJ AND status = \"In Review\" AND fixVersion = \"v1.0.0\"",
"fields": ["key"]
}')
KEYS=$(echo "$RESPONSE" | jq -r '.issues[].key')
for KEY in $KEYS; do
echo "Transitioning $KEY to Done..."
curl -s -X POST \
-u "$JIRA_USER_EMAIL:$JIRA_API_TOKEN" \
-H "Content-Type: application/json" \
"$JIRA_BASE_URL/rest/api/3/issue/$KEY/transitions" \
-d "{
\"transition\": { \"id\": \"$TRANSITION_ID\" },
\"fields\": {
\"resolution\": { \"name\": \"Done\" }
}
}"
sleep 0.2
done
#!/bin/bash
# Bulk delete issues (use with caution!)
RESPONSE=$(curl -s -X POST \
-u "$JIRA_USER_EMAIL:$JIRA_API_TOKEN" \
-H "Content-Type: application/json" \
"$JIRA_BASE_URL/rest/api/3/search/jql" \
-d '{
"jql": "project = TEST AND issuetype = \"Test Issue\"",
"fields": ["key"]
}')
KEYS=$(echo "$RESPONSE" | jq -r '.issues[].key')
echo "About to delete $(echo "$KEYS" | wc -w) issues. Press Enter to continue or Ctrl+C to cancel."
read
for KEY in $KEYS; do
echo "Deleting $KEY..."
curl -s -X DELETE \
-u "$JIRA_USER_EMAIL:$JIRA_API_TOKEN" \
"$JIRA_BASE_URL/rest/api/3/issue/$KEY?deleteSubtasks=true"
sleep 0.2
done
echo "Bulk delete complete."
curl -X POST \
-H "Authorization: Basic $(echo -n '$JIRA_USER_EMAIL:$JIRA_API_TOKEN' | base64)" \
-H "Content-Type: application/json" \
"https://{domain}.atlassian.net/rest/agile/1.0/sprint/{sprintId}/issue" \
-d '{
"issues": ["PROJ-1", "PROJ-2", "PROJ-3", "PROJ-4", "PROJ-5"]
}'
#!/bin/bash
# Add a label to all issues matching a query
RESPONSE=$(curl -s -X POST \
-u "$JIRA_USER_EMAIL:$JIRA_API_TOKEN" \
-H "Content-Type: application/json" \
"$JIRA_BASE_URL/rest/api/3/search/jql" \
-d '{
"jql": "project = PROJ AND component = \"Legacy API\"",
"fields": ["key", "labels"]
}')
echo "$RESPONSE" | jq -c '.issues[]' | while read -r ISSUE; do
KEY=$(echo "$ISSUE" | jq -r '.key')
echo "Adding label to $KEY..."
curl -s -X PUT \
-u "$JIRA_USER_EMAIL:$JIRA_API_TOKEN" \
-H "Content-Type: application/json" \
"$JIRA_BASE_URL/rest/api/3/issue/$KEY" \
-d '{
"update": {
"labels": [
{ "add": "deprecated" }
]
}
}'
sleep 0.2
done
npx claudepluginhub promptclickrun/jiragenius --plugin jirageniusBulk operations for multiple issues at scale. TRIGGERS: 'bulk update', 'bulk close', 'bulk transition', 'bulk assign', 'transition N issues' (N >= 10), 'update all bugs', 'close 50 issues', 'mass transition', 'update multiple issues', quantities like '50 issues', '100 bugs', '20+ tickets'. Use for operations on 10+ issues. NOT FOR: single issue transitions (use jira-lifecycle), searching only without modifications (use jira-search), single issue field updates (use jira-issue).
Bulk transitions multiple Jira issues matching a JQL filter to a target status using the jirac CLI, extracting project, filter, and options from requests.
Manages Jira Cloud issues via jira CLI with JSON output: create, view, update, search issues, fetch hierarchies, manage sprints.