Install
$ agentstack add skill-air-gapped-skills-jira-cli ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ● Shell / process execution Used
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
jira-cli — Atlassian Jira from the terminal
Target audience: an operator or agent driving Jira non-interactively — creating and transitioning tickets, running JQL, exporting issues, and scripting bulk changes — against any Jira deployment (Cloud, Server, or Data Center). This skill is instance-agnostic: it never assumes the target's project keys, workflows, or field schemes — it shows how to discover them and then act safely.
jira is ankitpokhrel/jira-cli, a single static Go binary inspired by GitHub's gh. It is not an official Atlassian tool.
Why this matters
Three things make jira-cli easy to get wrong, and all three are what this skill exists to prevent:
- It is interactive by default.
create,edit,assign,move,comment add, andworklog addopen a TUI or prompt for missing fields. A script (or an agent) that forgets--no-input— or omits a required flag — hangs forever waiting on a prompt that no one will answer. Reads (list,view,epic list,sprint list) default to an interactive pager/table UI; without--plain/--raw/--csvthe output is terminal-control gibberish, not parseable data. The automation contract is non-negotiable: writes get--no-input+ every required flag; reads get a plain/raw/csv format flag.
- Almost every value is instance-defined and case-sensitive. Issue types, statuses, priorities, resolutions, link types, components, and custom fields are configured per-project on the Jira side — the CLI invents none of them.
-tBugfails on a project that calls itDefect;move ISSUE-1 "Done"fails if the workflow's state isClosedordone(lowercase). Discover before acting (see below). Hardcoding values from memory is the most common cause of confusing failures.
- Descriptions/comments are converted to Atlassian Document Format (ADF). Markdown is not stored verbatim — it's translated. Some constructs (Jira
{code}blocks, strikethrough,@mentions, emoji shortcodes, raw HTML) translate imperfectly or are dropped. Seereferences/markdown-adf.md.
Version & source of truth
- Pinned at v1.7.0 (released 2025-08-31, the current latest). Verify locally:
jira version. --helpis the authoritative flag reference, always.jira --helpprints flags, arguments, aliases, and examples. If this skill ever disagrees with--helpon a flag, trust--help(and update the skill). Generate full man pages withjira man --generate --output.- This skill's exhaustive flag/argument tables live in
references/commands.md, captured from the v1.7.0 binary.
Cloud vs Server / Data Center — know which backend you're on
The CLI talks to two different Jira APIs and the behavior diverges in ways that change real commands. Check with jira serverinfo (Deployment Type: Cloud vs Server). The command surface is identical; these semantics are not:
| Aspect | Jira Cloud | Jira Server / Data Center | |---|---|---| | REST API | v3 | v2 | | Description/comment format | GFM/Jira markdown → ADF (auto-converted) | Jira wiki markup — create/comment convert GFM→wiki, but edit sends it verbatim (#935); prefer h2., *bold*, {code} | | Auth | email + API token | password (basic), or PAT (JIRA_AUTH_TYPE=bearer), or mTLS | | User identity for -a/-r | accountId (GDPR strict mode, #342) — email/display name may not resolve | username (or display name) | | --paginate : offset | ignored — can't page past the first 100 (#898) | works — old search API still honors startAt | | SSO in front of the instance | rare | API must be reachable directly with a PAT; basic-auth/email hits the SSO HTML login → 401 / invalid character ' interactively once to see the offered states, then script the exact string with --no-input-style full args. Full discovery recipes: references/config-auth.md.
Command map
| Goal | Command | Notes | |---|---|---| | Who am I / is auth working | jira me, jira serverinfo | $(jira me) is the self-reference idiom | | List/search issues | jira issue list (aliases ls, search) | Filters + JQL; see references/jql-and-filters.md | | View one issue | jira issue view KEY | --comments N, --raw for JSON | | Create issue | jira issue create -t -s"..." --no-input | -P parent (epic link / required for sub-task) | | Edit issue | jira issue edit KEY ... --no-input | --label appends, --component replaces (asymmetric!) | | Transition | jira issue move KEY "State" (aliases transition, mv) | --comment/-a/-R inline; state is workflow-defined | | Assign | jira issue assign KEY | x = unassign; user must be exact email/display name | | Comment | jira issue comment add KEY "body" | --internal for service-desk-internal; markdown→ADF | | Worklog | jira issue worklog add KEY "2d 1h 30m" --no-input | --started, --timezone, --new-estimate | | Link / unlink | jira issue link IN OUT / unlink / link remote | ` is instance-defined (Blocks, Duplicates, …) | | Clone | jira issue clone KEY -H"find:replace" | copy + tweak fields | | Delete (permanent) | jira issue delete KEY [--cascade] | irreversible; --cascade also deletes subtasks | | Epics | jira epic list [KEY] / create -n"Name" / add / remove | create needs -n/--name; add/remove ≤50 at once | | Sprints | jira sprint list [ID] / add / close | --current/--prev/--next/--state; get IDs from --table | | Releases (versions) | jira release list [-p PROJ] | requires Releases/Versions enabled on the instance | | Open in browser | jira open [KEY] | --no-browser prints the URL instead | | Projects / boards | jira project list, jira board list` | discovery |
Full flag tables, arguments, and aliases for every command: references/commands.md.
The automation contract (read this before scripting)
Output flags (reads) — bare list/view open an interactive UI, so any piping needs one of:
--plain(+--no-headers,--no-truncate,--columns key,summary,status,--delimiter "|") — tabular text; column names come from--help.--raw— Jira REST JSON (parse withjq; shape.[].fields.*).--csv— CSV with headers.--paginate— cap result count (max 100). Jira Cloud, v1.7.0: the:offset is silently ignored — Atlassian's new JQL search API droppedstartAt, so there is no way to page past the first 100 issues (#898). Narrow with JQL/filters instead. Server/Data Center (older API) still honors:.
Write flags:
--no-input— the load-bearing flag. Disables prompting for non-required fields. Pair with every required flag so the command runs unattended.--web— open the result in a browser after the write (skip in headless/CI).
Idioms:
# Self-reference
ME=$(jira me)
# Create → capture key → act on it
KEY=$(jira issue create -tTask -s"Automated task" --no-input --raw | jq -r '.key')
jira issue assign "$KEY" "$ME"
jira issue move "$KEY" "In Progress"
# Bulk: list keys, then loop
for k in $(jira issue list -q'assignee = currentUser() AND status = "To Do"' --plain --columns key --no-headers); do
jira issue move "$k" "In Progress" --comment "Picking up"
done
More patterns (CSV/JSON pipelines, dashboards, safe bulk edits): references/scripting.md.
Critical pitfalls
- Forgetting
--no-inputon a write hangs the process. In a non-interactive context (CI, agent,&&chain) this looks like the command "froze". Everycreate/edit/assign/move/comment add/worklog addin a script needs--no-inputplus all required positional/flag values. Known bug: even with--no-input, the body-reading writes (create,edit,comment add,epic create) can still block on stdin when it's a socket/subprocess pipe — jira-cli treats "stdin is not a TTY" as "read the body from stdin" and waits for EOF (#948/#984). Append `). To capture the new key as JSON, usejira issue create -tEpic -s"…" --no-input --rawinstead (Epic is an issue type), then attach children with-P/--parent EPIC-KEY(the flag is "parent" because next-gen reuses the parent relationship). The? Epic Keyprompt comes fromepic addwhen itsEPIC-KEY` arg is missing — not from create.
- Sub-tasks require
-P/--parent, and the parent must be a type that allows sub-tasks. "Given parent work item does not belong to appropriate hierarchy" means-Ppoints at something (e.g. an epic, or another sub-task) that can't hold sub-tasks.
deleteis irreversible and--cascadedeletes subtasks too. Never run it speculatively on someone's behalf — confirm the key and intent first. There is no undo.
- Markdown → ADF is lossy. Prefer GitHub fenced code blocks (```
```) over Jira{code}(which can leak escape characters).~~strike~~renders as-text-;@usermentions need Jira's[~accountid]form; emoji shortcodes (:rocket:) and raw HTML are dropped. For anything structured, use--template file.mdand test on one issue first. Details:references/markdown-adf.md`.
- Assignee/watcher must match exactly. Pass an exact email or display name. On many Jira Cloud instances, GDPR strict mode means assignment resolves by accountId — if
assign KEY "Jane Doe"fails, try the email, or look up the accountId viajira issue view ... --raw.xunassigns;defaultuses the project's default assignee.
- **
-q/--jqlruns within the configured project's context.** To query across all projects, add a project clause yourself:-q'project IS NOT EMPTY'or name projects in the JQL. Plain filter flags (-s,-y,-l, …) and a-qJQL can combine.
- Auth is via the
JIRA_API_TOKENenvironment variable, not the config file. The token never lives in.config.yml. Cloud wants an API token (not the account password); on-prem basic wants the password; PAT wants the token plusJIRA_AUTH_TYPE=bearer. A 401 is nearly always a missing/wrongJIRA_API_TOKENor the wrong auth type. Seereferences/config-auth.md.
- Cloud vs Server/Data Center differ. Some features and
--rawJSON fields vary by backend; non-English on-prem instances may need manualepic.name/epic.link/issue.types.*.handleentries in the config. Don't assume Cloud behavior on Server.
What to read next
| File | Read when… | |---|---| | references/commands.md | Looking up exact flags, arguments, aliases for any command. Full v1.7.0 surface. | | references/jql-and-filters.md | Building a list/epic list/sprint list query — filter flags, the date syntax (week, -7d, 2025-09-15), ~ negation, x unassigned, JQL examples. | | references/markdown-adf.md | Writing a description/comment with formatting — GFM vs Jira markup, ADF conversion limits, templates, here-docs, $'...' newlines. | | references/scripting.md | Automating — non-interactive recipes, --raw+jq and --csv pipelines, safe bulk edits, capturing created keys, dashboards. | | references/config-auth.md | First-time setup, multi-instance configs, every auth type (Cloud/basic/PAT/mTLS), env vars, and the full instance-discovery recipes. | | references/troubleshooting.md | A specific error or symptom — hangs, 401s, "valid issue type", parent-hierarchy errors, empty output, pager weirdness. | | references/known-issues.md | Tracking an upstream bug the skill works around — (#NNN) tags in the body map to this table (status, what it affects). | | references/sources.md | Verifying or freshening external claims; per-row Last verified dates. |
Quick recipes
# Smoke test: am I connected and what can I see?
jira me && jira project list
# List my open issues, parseable
jira issue list -q'assignee = currentUser() AND statusCategory != Done' \
--plain --no-headers --columns key,status,summary
# Create a bug, non-interactively, and print its key
jira issue create -tBug -s"Login 500 on submit" -yHigh -lregression \
-b$'## Steps\n1. ...\n\n## Expected\n...' --no-input --raw | jq -r '.key'
# Transition with a comment and resolution
jira issue move PROJ-42 "Done" -RFixed --comment "Shipped in 1.2.3"
# Export everything in a project to CSV
jira issue list -p PROJ --csv --paginate 0:100 > issues.csv
# Add a sub-task under a story
jira issue create -t"Sub-task" -P PROJ-100 -s"Write tests" --no-input
For anything beyond these, drill into the references/ files — they carry the exhaustive flag tables, JQL grammar, ADF rules, and auth matrix.
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: air-gapped
- Source: air-gapped/skills
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.