Use when the user runs /jira [verb] [...args]. Supported verbs: create, status. Example: /jira create, /jira create bug, /jira status, /jira status me.
Dispatches to a Jira action based on the verb argument.
Arguments: /jira [verb] [...rest]
verb: the action to perform. Supported values: create, statusCreates a Jira issue for the current project, auto-detecting the project key from git history.
Arguments after create: /jira create [type] [title]
Check memory file jira_config.md for:
JIRA_BASE_URL — e.g. https://company.atlassian.netJIRA_EMAIL — e.g. [email protected]If not found, ask the user for both values via AskUserQuestion, then save to memory:
/Users/larryhsiao/.claude/projects/-Users-larryhsiao-skadi/memory/jira_config.mdMEMORY.mdRequire JIRA_API_TOKEN env var. If not set, tell the user:
Set
JIRA_API_TOKENin your environment (e.g. in~/.zshrc) with an Atlassian API token from https://id.atlassian.com/manage-profile/security/api-tokens
type: task, bug, or epic — default to task if not provided or not one of those valuestitle: everything after the type (if the second word is not a valid type, treat the entire argument as the title with type defaulting to task)task → Task, bug → Bug, epic → EpicSearch git history and branches for Jira ticket patterns ([A-Z]+-[0-9]+):
# Try git log first
git log --oneline -100 2>/dev/null | grep -oE '[A-Z]+-[0-9]+' | head -1
# Fall back to branch names
git branch -a 2>/dev/null | grep -oE '[A-Z]+-[0-9]+' | head -1
Extract the project key (e.g. PROJ from PROJ-123) and use it silently — do NOT ask the user to confirm.
If no ticket is found anywhere:
jira_project.md for a saved project key/Users/larryhsiao/.claude/projects/-Users-larryhsiao-skadi/memory/jira_project.mdMEMORY.mdIf a title was provided as an argument, use it directly — do NOT ask the user.
Otherwise, use AskUserQuestion to get the issue title/summary. Keep it concise.
a. Get the board ID for the project:
curl -s -u "$JIRA_EMAIL:$JIRA_API_TOKEN" \
"$JIRA_BASE_URL/rest/agile/1.0/board?projectKeyOrId=PROJECT_KEY" \
| python3 -c "import sys,json; d=json.load(sys.stdin); print(d['values'][0]['id']) if d.get('values') else print('')"
If no board is found, skip sprint selection entirely.
b. Get active and future sprints:
curl -s -u "$JIRA_EMAIL:$JIRA_API_TOKEN" \
"$JIRA_BASE_URL/rest/agile/1.0/board/BOARD_ID/sprint?state=active,future" \
| python3 -c "
import sys, json
d = json.load(sys.stdin)
for s in d.get('values', []):
print(s['id'], s['name'], s.get('state',''))
"
c. Present sprint options via AskUserQuestion:
List each sprint as an option (name + state), plus a "No sprint (backlog)" option.
If the user picks a sprint, record the sprint ID for the issue creation payload.
Build the payload and POST to Jira:
python3 -c "
import json, subprocess, os, sys
payload = {
'fields': {
'project': {'key': 'PROJECT_KEY'},
'summary': 'SUMMARY',
'issuetype': {'name': 'ISSUE_TYPE'}
}
}
# Add sprint if selected (classic boards use customfield_10020)
# payload['fields']['customfield_10020'] = SPRINT_ID
data = json.dumps(payload)
result = subprocess.run([
'curl', '-s', '-X', 'POST',
'-u', f\"{os.environ['JIRA_EMAIL']}:{os.environ['JIRA_API_TOKEN']}\",
'-H', 'Content-Type: application/json',
'-d', data,
f\"{os.environ['JIRA_BASE_URL']}/rest/api/3/issue\"
], capture_output=True, text=True)
print(result.stdout)
"
Use the sprint field customfield_10020 (integer sprint ID) for classic Jira boards. If it returns a field error for that field, retry without the sprint field and note that the user should assign the sprint manually.
For next-gen (team-managed) projects, sprint assignment is done via the agile API after creation:
curl -s -X POST -u "$JIRA_EMAIL:$JIRA_API_TOKEN" \
-H "Content-Type: application/json" \
"$JIRA_BASE_URL/rest/agile/1.0/sprint/SPRINT_ID/issue" \
-d '{"issues": ["ISSUE_KEY"]}'
Parse the response and show:
Created: PROJECT-123
URL: https://company.atlassian.net/browse/PROJECT-123
Then ask via AskUserQuestion: "Start working on PROJECT-123 now?" (yes → chain to /working PROJECT-123).
Shows a sprint board overview grouped by status, sorted by priority. Acts as a secretary: tells you what the team is doing and what you should focus on next.
Arguments after status: /jira status [filter]
me: show only issues assigned to the current userCheck memory file jira_config.md for:
JIRA_BASE_URLJIRA_EMAILIf not found, ask the user and save to memory (same as create verb).
Require JIRA_API_TOKEN env var. If not set, tell the user to set it and stop.
Same as create verb: git history → jira_project.md memory → ask user.
me → use JIRA_EMAIL from memory as the assignee valuea. Get board ID:
curl -s -u "$JIRA_EMAIL:$JIRA_API_TOKEN" \
"$JIRA_BASE_URL/rest/agile/1.0/board?projectKeyOrId=PROJECT_KEY" \
| python3 -c "import sys,json; d=json.load(sys.stdin); print(d['values'][0]['id']) if d.get('values') else print('')"
b. Get active sprint (only if board found):
curl -s -u "$JIRA_EMAIL:$JIRA_API_TOKEN" \
"$JIRA_BASE_URL/rest/agile/1.0/board/BOARD_ID/sprint?state=active" \
| python3 -c "
import sys,json
d=json.load(sys.stdin)
sprints=d.get('values',[])
if sprints:
s=sprints[0]
print(s['name'] + '|' + s.get('startDate','') + '|' + s.get('endDate',''))