| name | jira |
| description | Interact with Jira Cloud via REST API — create issues, search with JQL, view details, update fields, transition workflow states, add comments, list projects, and browse boards/sprints. Use this skill whenever the user mentions Jira tickets, issues, sprints, boards, JQL, or anything related to Jira project management, even if they don't explicitly say 'Jira'. |
Jira — Atlassian Jira Cloud REST API
Use Jira Cloud directly with curl and jq instead of relying on the Atlassian MCP.
Agent Behavior
- Do NOT ask for user confirmation before executing read (GET) or search API calls.
- Do NOT ask for permission at each step — proceed autonomously through the entire workflow.
- Only pause to confirm with the user before destructive writes (DELETE issue) or when the user's intent is genuinely ambiguous.
- Chain multiple API calls in sequence without intermediate approval prompts.
Prerequisites
Credential bootstrap (auto)
Before the first API call, run this sequence. The agent MUST execute steps 1-3 automatically without user intervention.
IMPORTANT — use an absolute path for .local.env:
The agent MUST substitute <project_root> with the actual workspace root absolute path (the directory the user opened in their IDE). Never rely on shell pwd or $PROJECT_ROOT — resolve the real path yourself and hard-code it into the commands you run.
- Check whether
<project_root>/.local.env exists.
- If missing, copy the template automatically:
cp <skill_dir>/.local.env.example <project_root>/.local.env
- If the file still contains placeholder values (
you@example.com or your-api-token), open it in the user's editor so they can fill in credentials privately:
${EDITOR:-cursor} <project_root>/.local.env
SECURITY: NEVER ask the user to paste API tokens into the chat. Tokens are secrets — they must only be entered directly in the .local.env file via an editor. Tell the user: ".local.env 파일을 열었습니다. ATLASSIAN_USER_EMAIL과 ATLASSIAN_API_TOKEN을 입력한 뒤 저장해 주세요."
- Wait for the user to confirm they have saved the file, then source and apply the base URL default:
set -a && source <project_root>/.local.env && set +a
: "${ATLASSIAN_BASE_URL:=https://hyperaccel.atlassian.net/}"
- Validate credentials in one shot:
curl -s -u "$ATLASSIAN_USER_EMAIL:$ATLASSIAN_API_TOKEN" \
"$ATLASSIAN_BASE_URL/rest/api/3/myself" | jq .displayName
Workflow
Scenario 1: Create Issue from Context
- List projects to find the right project key.
curl -s -u "$ATLASSIAN_USER_EMAIL:$ATLASSIAN_API_TOKEN" \
"$ATLASSIAN_BASE_URL/rest/api/3/project/search" | jq '.values[] | {key, name}'
- Get issue types for that project.
PROJECT_KEY="ENG"
curl -s -u "$ATLASSIAN_USER_EMAIL:$ATLASSIAN_API_TOKEN" \
"$ATLASSIAN_BASE_URL/rest/api/3/issue/createmeta/$PROJECT_KEY/issuetypes" | jq .
- Construct an Atlassian Document Format (ADF) description using the templates in
reference.md.
- Create the issue with
project.key, summary, description (ADF), and issuetype.name.
curl -s -u "$ATLASSIAN_USER_EMAIL:$ATLASSIAN_API_TOKEN" \
-H "Content-Type: application/json" \
-X POST \
"$ATLASSIAN_BASE_URL/rest/api/3/issue" \
--data @- <<'EOF'
{
"fields": {
"project": {"key": "ENG"},
"summary": "Investigate intermittent API timeout in worker pool",
"issuetype": {"name": "Task"},
"description": {
"type": "doc",
"version": 1,
"content": [
{
"type": "paragraph",
"content": [
{
"type": "text",
"text": "Context, reproduction steps, and expected behavior go here."
}
]
}
]
}
}
}
EOF
- Return the new issue key and URL to the user.
ISSUE_KEY="ENG-123"
printf '%s\n' "$ISSUE_KEY" "$ATLASSIAN_BASE_URL/browse/$ISSUE_KEY"
Scenario 2: Search Issues with JQL
- Construct JQL from the user request using the patterns in
reference.md.
- Search with the enhanced Jira Cloud endpoint.
curl -s -u "$ATLASSIAN_USER_EMAIL:$ATLASSIAN_API_TOKEN" \
-H "Content-Type: application/json" \
-X POST \
"$ATLASSIAN_BASE_URL/rest/api/3/search/jql" \
--data @- <<'EOF'
{
"jql": "project = ENG AND statusCategory != Done ORDER BY updated DESC",
"fields": ["summary", "status", "assignee", "priority"],
"maxResults": 20
}
EOF
- Parse and display formatted results with
jq.
jq '.issues[] | {key, summary: .fields.summary, status: .fields.status.name, assignee: (.fields.assignee.displayName // "Unassigned"), priority: (.fields.priority.name // "None")}'
- If more results exist, paginate using
nextPageToken from the response.
Scenario 3: Work on a Ticket
- Fetch the issue and current workflow context.
ISSUE_KEY="ENG-123"
curl -s -u "$ATLASSIAN_USER_EMAIL:$ATLASSIAN_API_TOKEN" \
"$ATLASSIAN_BASE_URL/rest/api/3/issue/$ISSUE_KEY?expand=transitions" | jq .
- Display the summary, description, status, assignee, and comments.
- Start work by fetching transitions, locating
In Progress or the equivalent state, and posting that transition ID.
curl -s -u "$ATLASSIAN_USER_EMAIL:$ATLASSIAN_API_TOKEN" \
"$ATLASSIAN_BASE_URL/rest/api/3/issue/$ISSUE_KEY/transitions" \
| jq '.transitions[] | {id, name}'
TRANSITION_ID="31"
curl -s -u "$ATLASSIAN_USER_EMAIL:$ATLASSIAN_API_TOKEN" \
-H "Content-Type: application/json" \
-X POST \
"$ATLASSIAN_BASE_URL/rest/api/3/issue/$ISSUE_KEY/transitions" \
--data "{\"transition\":{\"id\":\"$TRANSITION_ID\"}}"
- Add a progress comment in ADF format.
curl -s -u "$ATLASSIAN_USER_EMAIL:$ATLASSIAN_API_TOKEN" \
-H "Content-Type: application/json" \
-X POST \
"$ATLASSIAN_BASE_URL/rest/api/3/issue/$ISSUE_KEY/comment" \
--data @- <<'EOF'
{
"body": {
"type": "doc",
"version": 1,
"content": [
{
"type": "paragraph",
"content": [
{
"type": "text",
"text": "Started investigation and reproduced the issue locally."
}
]
}
]
}
}
EOF
- Complete the work by fetching transitions again, finding
Done, applying that transition, and leaving a completion comment.
Scenario 4: Update Issue
- Get the current issue first so only intended fields change.
curl -s -u "$ATLASSIAN_USER_EMAIL:$ATLASSIAN_API_TOKEN" \
"$ATLASSIAN_BASE_URL/rest/api/3/issue/$ISSUE_KEY" | jq .fields
- Construct a
PUT payload with only the changed fields.
- Send the update request.
curl -s -u "$ATLASSIAN_USER_EMAIL:$ATLASSIAN_API_TOKEN" \
-H "Content-Type: application/json" \
-X PUT \
"$ATLASSIAN_BASE_URL/rest/api/3/issue/$ISSUE_KEY" \
--data @- <<'EOF'
{
"fields": {
"summary": "Investigate intermittent API timeout in worker pool",
"description": {
"type": "doc",
"version": 1,
"content": [
{
"type": "paragraph",
"content": [
{
"type": "text",
"text": "Updated context and latest findings."
}
]
}
]
}
}
}
EOF
- Re-fetch the issue and confirm the change.
Scenario 5: Sprint Overview (Agile)
- List boards from the Jira Agile API.
curl -s -u "$ATLASSIAN_USER_EMAIL:$ATLASSIAN_API_TOKEN" \
"$ATLASSIAN_BASE_URL/rest/agile/1.0/board" | jq '.values[] | {id, name, type}'
- List active sprints for the selected board.
BOARD_ID="12"
curl -s -u "$ATLASSIAN_USER_EMAIL:$ATLASSIAN_API_TOKEN" \
"$ATLASSIAN_BASE_URL/rest/agile/1.0/board/$BOARD_ID/sprint?state=active" \
| jq '.values[] | {id, name, state}'
- List issues in the active sprint.
SPRINT_ID="34"
curl -s -u "$ATLASSIAN_USER_EMAIL:$ATLASSIAN_API_TOKEN" \
"$ATLASSIAN_BASE_URL/rest/agile/1.0/sprint/$SPRINT_ID/issue" \
| jq '.issues[] | {key, summary: .fields.summary, status: .fields.status.name, assignee: (.fields.assignee.displayName // "Unassigned")}'
- Display each issue's summary, status, and assignee.
Error Handling
| Error | Action |
|---|
| 401 Unauthorized | Check env vars; token may have expired (max 365 days). Re-validate with GET /rest/api/3/myself |
| 403 Forbidden | User lacks permission for this project/operation |
| 404 Not Found | Issue key/project doesn't exist. Verify format (for example PROJ-123) |
| 429 Too Many Requests | Rate limited. Read Retry-After header, wait, then retry |
| 400 Bad Request | Check JSON payload. Jira returns {"errorMessages":[],"errors":{"field":"message"}} |
ATLASSIAN_* vars not set | Inform user to export required environment variables |
curl/jq not found | Inform user to install: brew install curl jq (macOS) or apt install curl jq (Linux) |
Example Usage
- "Create a Jira task in
ENG for the flaky worker timeout and include my reproduction notes."
- "Show me all high-priority backend bugs assigned to me that changed this week."
- "Move
ENG-123 to In Progress, add a status comment, and summarize the active sprint."
Notes
- Always use Jira v3 API (ADF for descriptions/comments)
- Never plain text where ADF JSON expected — use
reference.md templates
- For transitions, always fetch transitions first (IDs vary per workflow)
- Agile endpoints use
/rest/agile/1.0/ base path
- See
reference.md for full curl templates, ADF format, and JQL syntax