From jira-cli
Use when the user mentions Jira tickets, issues, tasks, stories, bugs, sprints, epics, boards, or any project management activity involving Jira. Also trigger when users say "my tickets", "what am I working on", "create a bug", "move this to done", "assign this to me", "log time", "sprint progress", or "what's in the backlog". Trigger even without explicit "Jira" mention if context involves issue tracking or agile project management.
How this skill is triggered — by the user, by Claude, or both
Slash command
/jira-cli:jira-cliThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Use `jira-cli` to interact with Jira from the terminal. This skill teaches you
Use jira-cli to interact with Jira from the terminal. This skill teaches you
how to pick the right commands, avoid interactive prompts that will hang, and
parse output reliably.
jira-cli is not installed or initialized (jira serverinfo fails) — set up prerequisites firstBefore using jira-cli commands, verify your setup:
brew install ankitpokhrel/jira-cli/jira-cli (or see
install docs)jira init and follow prompts (server URL, auth type, project)JIRA_API_TOKEN in your shell profilejira serverinfo --plain — should print your Jira server versionIf jira serverinfo fails, check:
echo $JIRA_API_TOKENcat ~/.config/.jira/.config.ymlThese rules prevent common failures when running jira-cli in a non-interactive agent context:
Always use --plain for list/view commands. The default TUI output is
interactive and unparseable. Add --plain to every jira issue list,
jira sprint list, jira epic list, and jira issue view call.
Always use --no-input for create/edit/comment/worklog commands. Without
it, jira-cli opens an interactive editor which hangs indefinitely. Add
--no-input to: issue create, issue edit, epic create,
issue comment add, issue worklog add. Do NOT use it on link, move,
assign, or delete — those commands don't support it.
Capture the current user early. Run jira me at the start of any
session that involves user-specific queries. Store the result and use it
with -a flags instead of calling jira me inline with $() which can
fail silently.
Use -p PROJECT explicitly when the user mentions a specific project,
rather than relying on the default config.
-p (project) vs -P (parent/epic link): These are DIFFERENT flags.
Use lowercase -p PROJ for project. Uppercase -P PARENT-KEY links to a
parent issue or epic. Confusing them causes Epic with key 'X' does not exist.
-b - does NOT read stdin. It literally sets the body to the string "-",
wiping the description. To pipe a description from stdin, omit -b entirely:
# WRONG — wipes description to "-"
cat description.txt | jira issue edit ISSUE-123 --no-input -b -
# CORRECT — reads body from stdin automatically
cat description.txt | jira issue edit ISSUE-123 --no-input
--no-input only works on create/edit/comment/worklog commands. Do NOT add
it to jira issue link, jira issue move, jira issue assign, or
jira issue delete — those commands don't support it and will error with
unknown flag: --no-input.
--body only works on create/edit commands. For comments, pass the body as
a positional argument or pipe to stdin with --template -:
# Positional argument
jira issue comment add ISSUE-123 "Comment text" --no-input
# Pipe from stdin
cat comment.txt | jira issue comment add ISSUE-123 --template - --no-input
jira-cli supports two filtering styles. Pick the right one:
Use flags when filtering on a single dimension or simple combinations:
jira issue list -a"[email protected]" -s"In Progress" --plain
Use JQL (-q) when you need complex logic, cross-project queries, OR
conditions, functions, or fields not covered by flags:
jira issue list -q "assignee = currentUser() AND status WAS 'In Progress' BEFORE '2024-01-01'" --plain
Common JQL patterns:
-q "project IN (PROJ1, PROJ2) AND assignee = currentUser()"-q "priority = High OR priority = Highest"-q "summary ~ 'login bug'"-q "updated >= -7d AND assignee = currentUser()"-q "assignee IS EMPTY AND project = PROJ"-q "parent = STORY-123"-q "'Epic Link' = EPIC-123"-q "issue in linkedIssues('ISSUE-123')"-q "issue in linkedIssues('ISSUE-123', 'is a parent of')"Plain output (--plain) is tab-delimited with default columns:
TYPE, KEY, SUMMARY, STATUS, ASSIGNEE. Use --no-headers when parsing
programmatically. Use --raw for full JSON when you need fields not available
in plain mode. See references/commands.md for all output flags (--columns,
--csv, --delimiter, etc.).
Plain output is tab-delimited. Extract specific fields with awk:
# Extract just issue keys (column 2)
jira issue list -a"$ME" --plain --no-headers | awk -F'\t' '{print $2}'
# Extract key and status (columns 2 and 4)
jira issue list --plain --no-headers | awk -F'\t' '{print $2, $4}'
# Filter rows by status
jira issue list --plain --no-headers | awk -F'\t' '$4 == "In Progress"'
Use --raw with jq for structured data:
# Get issue description
jira issue view ISSUE-123 --raw | jq -r '.fields.description'
# Extract custom field value
jira issue view ISSUE-123 --raw | jq -r '.fields.customfield_10001'
# Get all issue keys from a list as JSON array
jira issue list -a"$ME" --raw | jq '[.[].key]'
Summaries and descriptions may contain tabs, quotes, or newlines. When using
plain output for programmatic processing, prefer --raw (JSON) for fields that
may contain freeform text.
jira issue list returns at most 100 results by default. For larger result
sets, paginate explicitly:
# First 50 results
jira issue list -pPROJ --paginate 0:50 --plain
# Next 50
jira issue list -pPROJ --paginate 50:50 --plain
Stop paginating when the returned row count is less than the requested limit.
Jira Cloud enforces API rate limits. When you receive a 429 response:
sleep 1 between calls.jira epic add EPIC-1 ISSUE-1 ISSUE-2 ISSUE-3 instead of three separate epic add calls.Network timeouts and 5xx errors are transient. Retry up to 2 times with increasing delay:
# Simple retry pattern
for i in 1 2 3; do
jira issue view ISSUE-123 --plain && break
sleep "$((i * 2))"
done
Do not retry 4xx errors (except 429) — they indicate a permanent problem.
Before running commands, you often need to discover IDs and names. Use these patterns to find what you need.
# List available projects with keys
jira project list --plain --no-headers | awk -F'\t' '{print $1, $2}'
If the user says "my project" without a key, list projects and ask which one.
Sprint commands need numeric IDs. Extract from the sprint list:
# Get active sprint ID
SPRINT_ID=$(jira sprint list --state active --table --plain --no-headers | awk -F'\t' '{print $1}' | head -1)
if [ -z "$SPRINT_ID" ]; then
echo "No active sprint found" >&2
exit 1
fi
Status names are instance-specific and case-sensitive. When jira issue move
fails with "No transition found", check the current status first:
# Get current status
jira issue view ISSUE-123 --raw | jq -r '.fields.status.name'
Note: The standard --raw response may not include a transitions array
(it requires ?expand=transitions in the Jira REST API). If you cannot
discover transitions programmatically, try common status names like "To Do",
"In Progress", "In Review", "Done", or check your Jira board for the workflow.
Custom fields use IDs like customfield_10001. Discover them from any issue:
# List all custom field IDs on an issue
jira issue view ISSUE-123 --raw | jq -r '.fields | keys[] | select(startswith("customfield"))'
# Get a specific custom field value
jira issue view ISSUE-123 --raw | jq -r '.fields.customfield_10001'
Issue types vary by project. Common safe defaults: Task, Bug, Story.
To discover types used in a project, sample from existing issues:
# List distinct issue types used in a project
jira issue list -pPROJ --plain --columns type --no-headers | sort -u
# Check a specific issue's type
jira issue view ISSUE-123 --raw | jq -r '.fields.issuetype.name'
For complete multi-command workflows (Start of Day, Batch Create, Batch
Transition, Sprint Planning, Triage Backlog, and more), read
references/workflows.md in this skill's directory.
One example per operation. See references/commands.md for all flags.
# My open issues
jira issue list -a"$ME" --plain
# Filter by status, type, and project
jira issue list -pPROJ -s"In Progress" -tBug --plain
# Search by text
jira issue list "login crash" --plain
# Plain text view with comments
jira issue view ISSUE-123 --plain --comments 5
# Full JSON for detailed inspection
jira issue view ISSUE-123 --raw
# Create a bug (minimum: -t, -s, --no-input)
jira issue create -tBug -s"Login fails on mobile" -yHigh \
-b"Steps to reproduce..." --no-input
# Capture the created issue key
KEY=$(jira issue create -tTask -s"New task" --no-input --raw | jq -r '.key')
# Update fields
jira issue edit ISSUE-123 -s"Updated title" -yHigh --no-input
# Pipe multi-line description
echo "New detailed description" | jira issue edit ISSUE-123 --no-input
When creating or editing descriptions via the CLI, use Jira wiki markup — NOT Markdown. Markdown will appear as unformatted plain text in Jira.
| Markdown | Jira Wiki Markup |
|---|---|
## Heading | h2. Heading |
**bold** | *bold* |
`code` | {{code}} |
- item | * item |
1. item | # item |
| col1 | col2 | | || col1 || col2 || (headers) |
cat <<'DESC' | jira issue edit ISSUE-123 --no-input
h2. Summary
This is *bold* and {{inline code}}.
h3. Steps
# First step
# Second step
|| Header 1 || Header 2 ||
| value 1 | value 2 |
DESC
# Move to a status (name must match exactly, case-sensitive)
jira issue move ISSUE-123 "In Progress"
# Complete with comment and resolution
jira issue move ISSUE-123 "Done" --comment "Completed" -RFixed
jira issue assign ISSUE-123 "$ME" # Assign to self
jira issue assign ISSUE-123 x # Unassign
jira issue comment add ISSUE-123 "Root cause identified" --no-input
jira issue worklog add ISSUE-123 "2h 30m" --comment "Implementation" --no-input
# Syntax: jira issue link INWARD_KEY OUTWARD_KEY LINK_TYPE
# Use the link TYPE NAME (e.g., "Composition", "Blocks"), NOT the
# directional phrase (e.g., "is child of").
# Make PARENT-1 the parent of CHILD-2 via Composition:
jira issue link CHILD-2 PARENT-1 Composition
# (CHILD-2 = inward = "is a child of", PARENT-1 = outward = "is a parent of")
# ISSUE-A blocks ISSUE-B:
jira issue link ISSUE-A ISSUE-B Blocks
# Add a remote web link to an issue:
jira issue link remote ISSUE-123 "https://example.com/doc" "Design Doc"
# Discover available link types on your instance:
jira issue view ANY-ISSUE --raw | jq -r '.fields.issuelinks[].type.name' | sort -u
Direction rule: The first key gets the inward relationship. For Composition: inward = "is a child of", outward = "is a parent of". For Blocks: inward = "is blocked by", outward = "blocks".
jira issue clone ISSUE-123 -s"Cloned: New summary"
Jira has multiple parent-child relationship types. Each uses different JQL:
| Relationship | JQL | Example |
|---|---|---|
| Native subtask | parent = KEY | parent = STORY-123 |
| Epic children | "Epic Link" = KEY | "Epic Link" = EPIC-42 |
| Issue links (all types) | issue in linkedIssues(KEY) | issue in linkedIssues('PROJ-100') |
| Issue links (filtered) | issue in linkedIssues(KEY, 'phrase') | issue in linkedIssues('PROJ-100', 'is a parent of') |
Important: --parent, parent = KEY, and childIssuesOf() only work for
Jira's native subtask hierarchy. Custom link types (e.g., Composition,
"is parent of") are NOT subtasks — they are issue links. JQL functions like
linkedIssues() may also fail if the link name doesn't match exactly.
Gotcha: The linkedIssues() type filter uses the inward/outward phrase
(e.g., 'is a parent of'), NOT the link type name (e.g., 'Composition').
To find the exact phrase, inspect the raw JSON:
jira issue view ISSUE-123 --raw | jq '.fields.issuelinks[].type'
Recommended fallback: When JQL link queries return no results, view the
parent issue directly and parse issuelinks — this always works regardless
of link type configuration:
# List all linked issues with their link type, status, and summary
jira issue view PARENT-123 --raw | jq -r '
.fields.issuelinks[] |
(.inwardIssue // .outwardIssue) as $issue |
"\(.type.inward // .type.outward)\t\($issue.key)\t\($issue.fields.status.name)\t\($issue.fields.summary)"'
jira epic list --table --plain # List all epics
jira epic list EPIC-42 --plain # Issues in an epic
jira epic create -n"Q1 Auth" -s"Summary" --no-input # Create
jira epic add EPIC-42 ISSUE-123 ISSUE-456 # Add issues to epic
See references/commands.md for epic remove and all epic flags.
jira sprint list --state active --table --plain # Active sprints
jira issue list -q "sprint IN openSprints() AND assignee = currentUser()" --plain # My current sprint issues
jira sprint add SPRINT_ID ISSUE-123 ISSUE-456 # Add issues to sprint
See references/commands.md for sprint close, --prev, --next, and all
sprint flags.
jira project list --plain # List projects
jira board list --plain # List boards
jira open ISSUE-123 # Open in browser
"Issue does not exist": Double-check the issue key. Keys are case-sensitive and project-prefixed (e.g., PROJ-123, not just 123).
"No transition found": The status name doesn't match available transitions.
Check the current status with:
jira issue view ISSUE-123 --raw | jq -r '.fields.status.name'
Then try common status names ("To Do", "In Progress", "In Review", "Done") or
check your Jira board for the workflow.
Command hangs: You likely forgot --no-input on a create/edit command, or
--plain on a list command. Kill the process and retry with the correct flags.
Also avoid piping --raw output from jira issue create through other commands
(e.g., | python3 ...) — this can hang. Instead, capture to a variable:
OUTPUT=$(jira issue create -tTask -s"Title" --no-input --raw)
KEY=$(echo "$OUTPUT" | jq -r '.key')
"401 Unauthorized": The JIRA_API_TOKEN is missing or expired. Check with
echo $JIRA_API_TOKEN and verify it's set.
Rate limiting (429): Wait at least 5 seconds before retrying. See the Defensive Patterns section for spacing and retry guidance.
Custom field errors: The field ID doesn't match. Use the discovery pattern:
jira issue view ISSUE-123 --raw | jq -r '.fields | keys[] | select(startswith("customfield"))'
Partial batch failure: When a batch loop has mixed results, collect failures
and report both lists. See the "Batch Transition Issues" pattern in
references/workflows.md for a full example with SUCCEEDED/FAILED arrays and
selective retry.
For complete flag documentation on every command — including flags not shown
above (--fix-version, --original-estimate, --skip-notify, --internal,
--delimiter, --csv, and more) — read references/commands.md in this
skill's directory.
npx claudepluginhub gchiam/claude-code-plugins --plugin jira-cliReferences Atlassian CLI (acli) commands for Jira: authenticate, create/view/edit issues, JQL searches, bulk operations, project/board/sprint management.
Manages Jira Cloud issues via jira CLI with JSON output: create, view, update, search issues, fetch hierarchies, manage sprints.
Interacts with Jira issues via CLI scripts: search, create, update, transition, comment, log work, manage sprints/boards/attachments/links. Auto-triggers on Jira URLs and issue keys.