home / skills / vm0-ai / vm0-skills / jira

jira skill

/jira

This skill automates Jira Cloud REST API tasks via curl, enabling rapid issue creation, updates, searches, and comments.

npx playbooks add skill vm0-ai/vm0-skills --skill jira

Review the files below or copy the command above to add this skill to your agents.

Files (1)
SKILL.md
10.9 KB
---
name: jira
description: Jira Cloud REST API via curl. Use this skill to create, update, search, and manage issues, projects, and workflows in Jira.
vm0_secrets:
  - JIRA_API_TOKEN
vm0_vars:
  - JIRA_DOMAIN
  - JIRA_EMAIL
---

# Jira API

Use the Jira Cloud REST API via direct `curl` calls to manage **issues, projects, and workflows**.

> Official docs: `https://developer.atlassian.com/cloud/jira/platform/rest/v3/`

---

## When to Use

Use this skill when you need to:

- **Create issues** in Jira projects
- **Search issues** using JQL (Jira Query Language)
- **Update issues** (status, assignee, priority, etc.)
- **Get issue details** and comments
- **List projects** and their metadata
- **Transition issues** through workflow states
- **Add comments** to issues

---

## Prerequisites

1. Go to [Atlassian Account Settings](https://id.atlassian.com/manage-profile/security/api-tokens)
2. Click **Create API token**
3. Copy the generated token (you won't see it again)

```bash
export JIRA_DOMAIN="mycompany" # e.g., "mycompany" or "mycompany.atlassian.net"
export JIRA_EMAIL="[email protected]" # Your Atlassian account email
export JIRA_API_TOKEN="your-api-token" # API token from step 2
```

### Rate Limits

Jira Cloud has rate limits that vary by endpoint. For most REST API calls, expect limits around 100-500 requests per minute.

---


> **Important:** When using `$VAR` in a command that pipes to another command, wrap the command containing `$VAR` in `bash -c '...'`. Due to a Claude Code bug, environment variables are silently cleared when pipes are used directly.
> ```bash
> bash -c 'curl -s "https://api.example.com" -H "Authorization: Bearer $API_KEY"' | jq '.field'
> ```

## How to Use

All examples below assume `JIRA_DOMAIN`, `JIRA_EMAIL`, and `JIRA_API_TOKEN` are set.

Base URL: `https://${JIRA_DOMAIN%.atlassian.net}.atlassian.net/rest/api/3`

> Note: `${JIRA_DOMAIN%.atlassian.net}` strips the suffix if present, so both `mycompany` and `mycompany.atlassian.net` work.

---

### 1. Get Current User

Verify your authentication:

```bash
bash -c 'curl -s -X GET "https://${JIRA_DOMAIN%.atlassian.net}.atlassian.net/rest/api/3/myself" -u "${JIRA_EMAIL}:${JIRA_API_TOKEN}" --header "Accept: application/json"'
```

---

### 2. List Projects

Get all projects you have access to:

```bash
bash -c 'curl -s -X GET "https://${JIRA_DOMAIN%.atlassian.net}.atlassian.net/rest/api/3/project" -u "${JIRA_EMAIL}:${JIRA_API_TOKEN}" --header "Accept: application/json"'
```

---

### 3. Get Project Details

Get details for a specific project:

```bash
PROJECT_KEY="PROJ"

bash -c 'curl -s -X GET "https://${JIRA_DOMAIN%.atlassian.net}.atlassian.net/rest/api/3/project/${PROJECT_KEY}" -u "${JIRA_EMAIL}:${JIRA_API_TOKEN}" --header "Accept: application/json"'
```

---

### 4. Get Issue Types for Project

List available issue types (Task, Bug, Story, etc.):

```bash
PROJECT_KEY="PROJ"

bash -c 'curl -s -X GET "https://${JIRA_DOMAIN%.atlassian.net}.atlassian.net/rest/api/3/project/${PROJECT_KEY}" -u "${JIRA_EMAIL}:${JIRA_API_TOKEN}" --header "Accept: application/json"'
```

---

### 5. Search Issues with JQL

Search issues using Jira Query Language:

Write to `/tmp/jira_request.json`:

```json
{
  "jql": "project = PROJ AND status NOT IN (Done) ORDER BY created DESC",
  "maxResults": 10,
  "fields": ["key", "summary", "status", "assignee", "priority"]
}
```

Then run:

```bash
bash -c 'curl -s -X POST "https://${JIRA_DOMAIN%.atlassian.net}.atlassian.net/rest/api/3/search/jql" -u "${JIRA_EMAIL}:${JIRA_API_TOKEN}" --header "Accept: application/json" --header "Content-Type: application/json" -d @/tmp/jira_request.json' | jq '.issues[] | {key, summary: .fields.summary, status: .fields.status.name, assignee: .fields.assignee.displayName, priority: .fields.priority.name}''
```

Common JQL examples:
- `project = PROJ` - Issues in project
- `assignee = currentUser()` - Your issues
- `status = "In Progress"` - By status
- `status NOT IN (Done, Closed)` - Exclude statuses
- `created >= -7d` - Created in last 7 days
- `labels = bug` - By label
- `priority = High` - By priority

---

### 6. Get Issue Details

Get full details of an issue:

```bash
ISSUE_KEY="PROJ-123"

bash -c 'curl -s -X GET "https://${JIRA_DOMAIN%.atlassian.net}.atlassian.net/rest/api/3/issue/${ISSUE_KEY}" -u "${JIRA_EMAIL}:${JIRA_API_TOKEN}" --header "Accept: application/json"'
```

---

### 7. Create Issue

Create a new issue (API v3 uses Atlassian Document Format for description):

Write to `/tmp/jira_request.json`:

```json
{
  "fields": {
    "project": {"key": "PROJ"},
    "summary": "Bug: Login button not responding",
    "description": {
      "type": "doc",
      "version": 1,
      "content": [
        {
          "type": "paragraph",
          "content": [
            {"type": "text", "text": "The login button on the mobile app is not responding when tapped."}
          ]
        }
      ]
    },
    "issuetype": {"name": "Bug"}
  }
}
```

Then run:

```bash
bash -c 'curl -s -X POST "https://${JIRA_DOMAIN%.atlassian.net}.atlassian.net/rest/api/3/issue" -u "${JIRA_EMAIL}:${JIRA_API_TOKEN}" --header "Accept: application/json" --header "Content-Type: application/json" -d @/tmp/jira_request.json'
```

---

### 8. Create Issue with Priority and Labels

Create issue with additional fields:

Write to `/tmp/jira_request.json`:

```json
{
  "fields": {
    "project": {"key": "PROJ"},
    "summary": "Implement user authentication",
    "description": {
      "type": "doc",
      "version": 1,
      "content": [
        {
          "type": "paragraph",
          "content": [
            {"type": "text", "text": "Add OAuth2 authentication flow for the mobile app."}
          ]
        }
      ]
    },
    "issuetype": {"name": "Story"},
    "priority": {"name": "High"},
    "labels": ["backend", "security"]
  }
}
```

Then run:

```bash
bash -c 'curl -s -X POST "https://${JIRA_DOMAIN%.atlassian.net}.atlassian.net/rest/api/3/issue" -u "${JIRA_EMAIL}:${JIRA_API_TOKEN}" --header "Accept: application/json" --header "Content-Type: application/json" -d @/tmp/jira_request.json'
```

---

### 9. Update Issue

Update an existing issue:

```bash
ISSUE_KEY="PROJ-123"
```

Write to `/tmp/jira_request.json`:

```json
{
  "fields": {
    "summary": "Updated: Login button not responding on iOS",
    "priority": {"name": "Highest"},
    "labels": ["bug", "ios", "urgent"]
  }
}
```

Then run:

```bash
bash -c 'curl -s -X PUT "https://${JIRA_DOMAIN%.atlassian.net}.atlassian.net/rest/api/3/issue/${ISSUE_KEY}" -u "${JIRA_EMAIL}:${JIRA_API_TOKEN}" --header "Accept: application/json" --header "Content-Type: application/json" -d @/tmp/jira_request.json'
```

Returns 204 No Content on success.

---

### 10. Get Available Transitions

Get possible status transitions for an issue:

```bash
ISSUE_KEY="PROJ-123"

bash -c 'curl -s -X GET "https://${JIRA_DOMAIN%.atlassian.net}.atlassian.net/rest/api/3/issue/${ISSUE_KEY}/transitions" -u "${JIRA_EMAIL}:${JIRA_API_TOKEN}" --header "Accept: application/json"'
```

---

### 11. Transition Issue (Change Status)

Move issue to a different status:

```bash
ISSUE_KEY="PROJ-123"
TRANSITION_ID="31" # Get from transitions endpoint
```

Write to `/tmp/jira_request.json`:

```json
{
  "transition": {
    "id": "<your-transition-id>"
  }
}
```

Then run:

```bash
bash -c 'curl -s -X POST "https://${JIRA_DOMAIN%.atlassian.net}.atlassian.net/rest/api/3/issue/${ISSUE_KEY}/transitions" -u "${JIRA_EMAIL}:${JIRA_API_TOKEN}" --header "Accept: application/json" --header "Content-Type: application/json" -d @/tmp/jira_request.json'
```

Returns 204 No Content on success.

---

### 12. Add Comment

Add a comment to an issue:

```bash
ISSUE_KEY="PROJ-123"
```

Write to `/tmp/jira_request.json`:

```json
{
  "body": {
    "type": "doc",
    "version": 1,
    "content": [
      {
        "type": "paragraph",
        "content": [
          {"type": "text", "text": "Investigated and found the root cause. Working on a fix."}
        ]
      }
    ]
  }
}
```

Then run:

```bash
bash -c 'curl -s -X POST "https://${JIRA_DOMAIN%.atlassian.net}.atlassian.net/rest/api/3/issue/${ISSUE_KEY}/comment" -u "${JIRA_EMAIL}:${JIRA_API_TOKEN}" --header "Accept: application/json" --header "Content-Type: application/json" -d @/tmp/jira_request.json'
```

---

### 13. Get Issue Comments

List all comments on an issue:

```bash
ISSUE_KEY="PROJ-123"

bash -c 'curl -s -X GET "https://${JIRA_DOMAIN%.atlassian.net}.atlassian.net/rest/api/3/issue/${ISSUE_KEY}/comment" -u "${JIRA_EMAIL}:${JIRA_API_TOKEN}" --header "Accept: application/json"'
```

---

### 14. Assign Issue

Assign an issue to a user:

```bash
ISSUE_KEY="PROJ-123"
ACCOUNT_ID="5b10ac8d82e05b22cc7d4ef5" # Get from /rest/api/3/user/search
```

Write to `/tmp/jira_request.json`:

```json
{
  "accountId": "<your-account-id>"
}
```

Then run:

```bash
bash -c 'curl -s -X PUT "https://${JIRA_DOMAIN%.atlassian.net}.atlassian.net/rest/api/3/issue/${ISSUE_KEY}/assignee" -u "${JIRA_EMAIL}:${JIRA_API_TOKEN}" --header "Accept: application/json" --header "Content-Type: application/json" -d @/tmp/jira_request.json'
```

---

### 15. Search Users

Find users by email or name:

Write to `/tmp/jira_search.txt`:

```
john
```

```bash
bash -c 'curl -s -G "https://${JIRA_DOMAIN%.atlassian.net}.atlassian.net/rest/api/3/user/search" -u "${JIRA_EMAIL}:${JIRA_API_TOKEN}" --header "Accept: application/json" --data-urlencode "query@/tmp/jira_search.txt"'
```

---

### 16. Delete Issue

Delete an issue (use with caution):

```bash
ISSUE_KEY="PROJ-123"

bash -c 'curl -s -X DELETE "https://${JIRA_DOMAIN%.atlassian.net}.atlassian.net/rest/api/3/issue/${ISSUE_KEY}" -u "${JIRA_EMAIL}:${JIRA_API_TOKEN}"'
```

Returns 204 No Content on success.

---

## Atlassian Document Format (ADF)

Jira API v3 uses ADF for rich text fields like `description` and `comment.body`. Basic structure:

```json
{
  "type": "doc",
  "version": 1,
  "content": [
  {
  "type": "paragraph",
  "content": [
  {"type": "text", "text": "Plain text"},
  {"type": "text", "text": "Bold text", "marks": [{"type": "strong"}]},
  {"type": "text", "text": "Code", "marks": [{"type": "code"}]}
  ]
  },
  {
  "type": "bulletList",
  "content": [
  {"type": "listItem", "content": [{"type": "paragraph", "content": [{"type": "text", "text": "Item 1"}]}]},
  {"type": "listItem", "content": [{"type": "paragraph", "content": [{"type": "text", "text": "Item 2"}]}]}
  ]
  },
  {
  "type": "codeBlock",
  "attrs": {"language": "python"},
  "content": [{"type": "text", "text": "print('hello')"}]
  }
  ]
}
```

---

## Guidelines

1. **Use JQL for complex queries**: JQL is powerful for filtering issues by any field combination
2. **Check transitions first**: Before changing status, get available transitions for the issue
3. **Handle pagination**: Use `startAt` and `maxResults` for large result sets
4. **Use account IDs**: Jira Cloud uses account IDs (not usernames) for user references
5. **ADF for rich text**: API v3 requires Atlassian Document Format for description and comments
6. **Rate limiting**: Implement exponential backoff if you receive 429 responses

Overview

This skill provides a collection of curl-based examples and patterns for interacting with the Jira Cloud REST API (v3). It focuses on creating, searching, updating, transitioning, commenting, and managing issues, plus listing projects and users. Examples include authentication, JQL searches, Atlassian Document Format (ADF) payloads, and practical tips for pagination and rate limits.

How this skill works

The skill shows direct curl commands that call Jira Cloud endpoints using basic auth with an email and API token. It demonstrates constructing JSON payloads (including ADF for rich text), calling search endpoints with JQL, inspecting available transitions, and posting updates, comments, and assignments. Commands are designed to be run from a shell with environment variables for domain, email, and token.

When to use it

  • Create new issues or migrate tasks into Jira programmatically
  • Search and filter issues using JQL for reports or scripts
  • Automate status transitions and bulk updates in CI/CD or maintenance workflows
  • Add comments, attachments, or update fields from external tools
  • List projects, discover issue types, or search users for automation or integrations

Best practices

  • Set JIRA_DOMAIN, JIRA_EMAIL, and JIRA_API_TOKEN as environment variables and reuse them
  • Use JQL and the search endpoint for complex queries and pagination (startAt, maxResults)
  • Request available transitions before changing status to avoid invalid transitions
  • Build description and comment bodies using Atlassian Document Format (ADF) required by API v3
  • Handle rate limits: detect 429 responses and apply exponential backoff

Example use cases

  • Create a bug or story with priority and labels from a CI/CD pipeline
  • Run nightly scripts that search for stale issues and notify owners via comments
  • Automate triage: assign, set priority, and transition new issues based on rules
  • Fetch project metadata and issue types to populate a custom frontend or import tool
  • Delete or bulk-update issues during cleanup operations (use with caution)

FAQ

How do I authenticate requests?

Use basic auth with your Atlassian account email and an API token. Export variables and use curl -u "${JIRA_EMAIL}:${JIRA_API_TOKEN}".

How do I include rich text in descriptions or comments?

Compose the body using Atlassian Document Format (ADF) JSON. The skill includes ADF examples for paragraphs, lists, and code blocks.

What if I hit rate limits?

Jira Cloud enforces rate limits per endpoint. Detect 429 responses and implement exponential backoff with retries.