A comprehensive, production-ready command-line interface for the Jira REST API v2, written in Go.
jcli supports both Jira Cloud (https://yourorg.atlassian.net) and
Jira Server / Data Center (self-hosted) instances.
- Features
- Installation
- Configuration
- Global Flags
- Command Reference
- Output Formats
- Authentication
- Examples
- AI Agent Skill
- API Reference
- Contributing
| Category | Operations |
|---|---|
| Issues | get, create, update, delete, search (JQL) |
| Comments | list, add, update, delete |
| Transitions | list, apply |
| Assignments | assign / unassign |
| Work Logs | list, add, delete |
| Votes | get, add, remove |
| Watchers | list, add, remove |
| Attachments | upload, delete |
| Issue Links | list types, create, delete |
| Projects | list, get, create, update, delete |
| Versions | list, create, update, delete |
| Components | list, create, update, delete |
| Boards | list |
| Sprints | list, create, update, list issues |
| Users | get, myself, search |
| Metadata | issue types, priorities, statuses, fields |
Additional capabilities:
- Three output formats:
table(default),json,plain(tab-separated) - Cascading configuration: properties file → environment variables → CLI flags
- Verbose mode: full HTTP request/response tracing to stderr
- TLS skip verification: for self-hosted instances with self-signed certificates
- Comprehensive help: every command documents its API mapping, parameters and examples
Because this repository is named jcli rather than homebrew-jcli, you need
to add the tap explicitly before installing:
brew tap steveohara/jcli https://github.com/steveohara/jcli
brew install steveohara/jcli/jcliAfter installation, Homebrew will display a message showing how to activate the bundled Jira agent skill for AI tools. To do it manually:
mkdir -p ~/.agents/skills/jira
ln -sf "$(brew --prefix)/share/jcli/SKILL.md" ~/.agents/skills/jira/SKILL.mdThis symlinks the skill into the global discovery path used by
OpenCode and other compatible AI agent tools. Once
linked, any agent session — regardless of which project you are working in —
can use the skill to interact with Jira via jcli.
To update to the latest release:
brew upgrade steveohara/jcli/jcliThe symlink points to the Homebrew-managed file, so upgrading automatically picks up the updated skill without relinking.
Download the latest jcli-vX.Y.Z-windows-amd64.exe from the
Releases page, rename it
to jcli.exe, and move it to a directory on your PATH (e.g.
C:\Users\<you>\bin\).
To verify the installation, open a new Command Prompt or PowerShell window and run:
jcli --versionIf you use Scoop:
scoop bucket add steveohara https://github.com/steveohara/jcli
scoop install jcliTo update:
scoop update jcliAfter placing jcli.exe on your PATH, activate the skill for AI agent tools
by copying SKILL.md from the release archive into the global discovery path.
Using PowerShell:
# Extract SKILL.md from the release zip/tarball, then:
New-Item -ItemType Directory -Force -Path "$env:USERPROFILE\.agents\skills\jira"
Copy-Item "SKILL.md" "$env:USERPROFILE\.agents\skills\jira\SKILL.md"Note: Windows does not support the
~/.agents/skills/symlink approach used on macOS/Linux. Copy the file instead, and re-copy it after each upgrade.
git clone https://github.com/steveohara/jcli.git
cd jcli
go build -o jcli .
# Optional: install to $GOPATH/bin
go install .On Windows, the output binary will be jcli.exe. Use go build -o jcli.exe .
to make this explicit.
- Go 1.21 or later
jcli resolves its configuration from three sources, with the later sources
overriding earlier ones:
| Priority | Source | Key names |
|---|---|---|
| 1 (lowest) | Config file | server, project, token, output |
| 2 | Environment variables | JIRA_SERVER, JIRA_PROJECT, JIRA_API_TOKEN |
| 3 (highest) | CLI flags | --server, --project, --token, --output |
The default config file location is ~/.config/jcli/config.properties.
On systems that set $XDG_CONFIG_HOME, the file is looked for at
$XDG_CONFIG_HOME/jcli/config.properties instead.
Use the --config flag to load a config file from any other path:
jcli --config /path/to/my-config.properties issue listWhen --config is specified and the file does not exist, jcli exits with an
error. When the default path is used and the file is absent, jcli silently
continues and relies on environment variables and CLI flags.
The file uses Java-style key=value syntax; lines beginning with # or !
are comments.
# ~/.config/jcli/config.properties
# Jira server URL (required)
server=https://myorg.atlassian.net
# Default project key (optional)
project=PROJ
# API token – omit if using JIRA_API_TOKEN env var
token=my-personal-access-token
# Default output format: table, json, or plain (optional, default: table)
output=table
# HTTP request timeout in seconds (optional, default: 30)
# timeout=30| Variable | Description |
|---|---|
JIRA_SERVER |
Jira base URL |
JIRA_PROJECT |
Default project key |
JIRA_API_TOKEN |
Bearer / Personal Access Token |
These flags are available on every command:
| Flag | Short | Description |
|---|---|---|
--config |
Path to config file (default: ~/.config/jcli/config.properties) |
|
--server |
Jira server base URL | |
--token |
Personal Access Token | |
--project |
Default project key | |
--output |
-o |
Output format: table, json, plain |
--insecure |
Skip TLS certificate verification | |
--verbose |
-v |
Print HTTP request/response to stderr |
--timeout |
HTTP request timeout in seconds (default: 30) | |
--help |
-h |
Show help for any command |
Run jcli <command> --help or jcli <command> <subcommand> --help at any time
for full flag documentation with API references.
API reference: https://developer.atlassian.com/cloud/jira/platform/rest/v2/api-group-issues/
Retrieve a single issue by key or numeric ID.
API: GET /rest/api/2/issue/{issueIdOrKey}
| Flag | Description |
|---|---|
--fields |
Comma-separated field IDs to include (default: all) |
--all-fields |
Include fields with empty or null values in JSON output (default omits them) |
jcli issue get PROJ-42
jcli issue get PROJ-42 --fields summary,status,assignee --output json
jcli issue get PROJ-42 --all-fields --output jsonCreate a new issue in a project.
API: POST /rest/api/2/issue
The convenience flags cover the most common fields. Use --fields for anything
else, including custom fields. --fields values override the convenience flags
when both name the same field.
| Flag | Short | Required | Description |
|---|---|---|---|
--summary |
-s |
✓ | Issue title |
--type |
-t |
Issue type (default: Task) |
|
--description |
-d |
Description body | |
--project |
Project key (overrides default) | ||
--priority |
Priority name (e.g. High, Medium) |
||
--assignee |
Assignee account ID | ||
--labels |
Comma-separated labels | ||
--components |
Comma-separated component IDs | ||
--fix-versions |
Comma-separated version IDs | ||
--due-date |
Due date (YYYY-MM-DD) |
||
--parent |
Parent issue key (for sub-tasks; Jira Server/DC only) | ||
--fields |
JSON object of field IDs to values (see below) | ||
--properties |
JSON array of entity property objects (see below) | ||
--history |
JSON object of change history metadata (see below) |
Epic Link vs Parent: On Jira Server/Data Center, use
--parentonly for sub-tasks. To link a Story (or other issue type) to an Epic, use thecustomfield_10200(Epic Link) field via--fields:jcli issue create --summary "My story" --type Story \ --fields '{"customfield_10200": "PROJ-123"}'Jira Cloud replaces Epic Link with a
parentrelationship and does not usecustomfield_10200. Check your instance type withjcli meta server-info.
--fields accepts any field the Jira REST API recognises, keyed by field ID.
Value format depends on the field type:
| Field type | Example value |
|---|---|
| Text | {"summary": "New title"} |
| Named object (priority, issuetype) | {"priority": {"name": "High"}} |
| ID object (assignee, components) | {"assignee": {"accountId": "abc123"}} |
| Select custom field | {"customfield_31004": {"id": "50628"}} |
| Multi-select custom field | {"customfield_10030": [{"id": "10100"}]} |
| Number custom field | {"customfield_10014": 5} |
| Date | {"duedate": "2024-06-01"} |
Use jcli meta fields to list all field IDs. Use jcli meta field-allowed-values <fieldId> --issue <KEY> to find option IDs for select fields.
--properties sets entity properties on the issue (key/value pairs indexed by Jira but not shown in the UI):
[{"key": "myapp.context", "value": {"buildNumber": 42}}]--history records context in the issue change history. Useful for automated changes:
{"activityDescription": "Deployed by CI", "actor": {"id": "ci-bot", "type": "automation"}}jcli issue create --summary "Login page broken" --type Bug --priority High
jcli issue create --summary "New API endpoint" --type Story --project MYPROJ \
--description "Implement /api/v2/users endpoint" --labels backend,api
jcli issue create --summary "Write unit tests" --type Sub-task --parent PROJ-10
# Set custom fields alongside convenience flags
jcli issue create --summary "Voice outage" --type Bug --priority High \
--fields '{"customfield_31004":{"id":"50628"},"customfield_23824":{"id":"36274"}}'
# Attach an entity property
jcli issue create --summary "Deploy task" \
--properties '[{"key":"pipeline.id","value":"build-42"}]'Update one or more fields of an existing issue. Only the flags you provide are sent to the API; all other fields are left unchanged.
API: PUT /rest/api/2/issue/{issueIdOrKey}
| Flag | Short | Description |
|---|---|---|
--summary |
-s |
New summary |
--description |
-d |
New description |
--priority |
New priority name | |
--assignee |
New assignee account ID | |
--due-date |
New due date (YYYY-MM-DD) |
|
--labels |
Replace labels (comma-separated) | |
--fields |
JSON object of field IDs to values (same format as issue create) |
|
--properties |
JSON array of entity property objects | |
--history |
JSON object of change history metadata |
jcli issue update PROJ-42 --summary "Updated title"
jcli issue update PROJ-42 --priority High --assignee "5f0d3aef12345678"
# Set a custom field
jcli issue update PROJ-42 --fields '{"customfield_31004":{"id":"50628"}}'
# Mix convenience flags and --fields
jcli issue update PROJ-42 --priority High \
--fields '{"customfield_23824":{"id":"36274"}}'
# Record change history context
jcli issue update PROJ-42 --summary "Auto-resolved" \
--history '{"activityDescription":"Resolved by CI","actor":{"id":"ci-bot","type":"automation"}}'Permanently delete an issue. This action cannot be undone.
API: DELETE /rest/api/2/issue/{issueIdOrKey}
| Flag | Description |
|---|---|
--delete-subtasks |
Also delete all child sub-tasks |
jcli issue delete PROJ-42
jcli issue delete PROJ-42 --delete-subtasksSearch for issues using Jira Query Language (JQL).
API: GET /rest/api/2/search
| Flag | Description |
|---|---|
--jql |
JQL query string |
--fields |
Comma-separated fields to return |
--all-fields |
Include fields with empty or null values in JSON output (default omits them) |
--start-at |
Pagination offset (default: 0) |
--max-results |
Page size (default: 50) |
--page |
Page number to fetch (1-based; computes startAt from --max-results) |
--all |
Fetch all pages automatically (overrides --page and --start-at) |
JQL documentation: https://developer.atlassian.com/cloud/jira/platform/rest/v2/api-group-jql/
jcli issue search --jql "project = PROJ AND status = 'In Progress'"
jcli issue search --jql "assignee = currentUser() ORDER BY updated DESC"
jcli issue search --jql "sprint in openSprints() AND priority = High"
jcli issue search --jql "project = PROJ" --max-results 100 --output json
jcli issue search --jql "project = PROJ" --all --output json
jcli issue search --jql "project = PROJ" --page 2 --max-results 25
jcli issue search --jql "project = PROJ" --all-fields --output jsonManage comments on issues.
API reference: https://developer.atlassian.com/cloud/jira/platform/rest/v2/api-group-issue-comments/
| Subcommand | API | Description |
|---|---|---|
list <issue-key> |
GET /comment |
List all comments |
add <issue-key> |
POST /comment |
Add a comment |
update <issue-key> |
PUT /comment/{id} |
Update a comment |
delete <issue-key> |
DELETE /comment/{id} |
Delete a comment |
jcli issue comment list PROJ-42
jcli issue comment add PROJ-42 --body "Looking into this now."
jcli issue comment update PROJ-42 --comment-id 10001 --body "Fixed in commit abc123"
jcli issue comment delete PROJ-42 --comment-id 10001Manage issue workflow transitions.
API reference: https://developer.atlassian.com/cloud/jira/platform/rest/v2/api-group-issues/
| Subcommand | API | Description |
|---|---|---|
list <issue-key> |
GET /transitions |
List available transitions |
apply <issue-key> |
POST /transitions |
Apply a transition |
jcli issue transition list PROJ-42
jcli issue transition apply PROJ-42 --id 31
jcli issue transition apply PROJ-42 --id 5 --resolution "Fixed"Assign or unassign an issue.
API: PUT /rest/api/2/issue/{issueIdOrKey}/assignee
jcli issue assign PROJ-42 --account-id "5f0d3aef12345678"
jcli issue assign PROJ-42 --account-id "" # unassignManage work log entries (time tracking).
API reference: https://developer.atlassian.com/cloud/jira/platform/rest/v2/api-group-issue-worklogs/
Time notation examples: 2h, 30m, 1d, 2h 30m
jcli issue worklog list PROJ-42
jcli issue worklog add PROJ-42 --time-spent "2h" \
--started "2024-01-15T09:00:00.000+0000" --comment "Bug investigation"
jcli issue worklog delete PROJ-42 --worklog-id 10050Manage votes on issues.
API reference: https://developer.atlassian.com/cloud/jira/platform/rest/v2/api-group-issue-votes/
jcli issue vote get PROJ-42
jcli issue vote add PROJ-42
jcli issue vote remove PROJ-42Manage watchers on issues.
API reference: https://developer.atlassian.com/cloud/jira/platform/rest/v2/api-group-issue-watchers/
jcli issue watch list PROJ-42
jcli issue watch add PROJ-42 --account-id "5f0d3aef12345678"
jcli issue watch remove PROJ-42 --account-id "5f0d3aef12345678"Manage links between issues.
API reference: https://developer.atlassian.com/cloud/jira/platform/rest/v2/api-group-issue-links/
jcli issue link types
jcli issue link create --type "blocks" --inward PROJ-42 --outward PROJ-50
jcli issue link create --type "relates to" --inward PROJ-1 --outward PROJ-2
jcli issue link delete --link-id 10000Manage file attachments on issues.
API reference: https://developer.atlassian.com/cloud/jira/platform/rest/v2/api-group-issue-attachments/
jcli issue attach add PROJ-42 --file /path/to/screenshot.png
jcli issue attach delete --attachment-id 10100API reference: https://developer.atlassian.com/cloud/jira/platform/rest/v2/api-group-projects/
List all visible projects.
API: GET /rest/api/2/project
jcli project list
jcli project list --output jsonGet details of a single project.
API: GET /rest/api/2/project/{projectIdOrKey}
jcli project get PROJCreate a new project.
API: POST /rest/api/2/project
Project type keys: software, service_desk, business
jcli project create --key MYPROJ --name "My Project" --type software
jcli project create --key DEMO --name "Demo Project" --type business \
--description "A demo project" --lead "accountId"Update project name, description or lead.
API: PUT /rest/api/2/project/{projectIdOrKey}
jcli project update PROJ --name "New Project Name"
jcli project update PROJ --description "Updated description"Delete a project and all its issues. This action cannot be undone.
API: DELETE /rest/api/2/project/{projectIdOrKey}
Manage project versions (releases).
API reference: https://developer.atlassian.com/cloud/jira/platform/rest/v2/api-group-project-versions/
jcli project version list PROJ
jcli project version create PROJ --name "v1.0" --release-date "2024-03-01"
jcli project version update --id 10010 --released
jcli project version delete --id 10010Manage project components.
API reference: https://developer.atlassian.com/cloud/jira/platform/rest/v2/api-group-project-components/
jcli project component list PROJ
jcli project component create PROJ --name "Backend" --description "Backend services"
jcli project component update --id 10020 --name "API Layer"
jcli project component delete --id 10020API reference: https://developer.atlassian.com/cloud/jira/software/rest/api-group-board/
The board commands use the Jira Agile REST API (/rest/agile/1.0).
List all Agile boards.
API: GET /rest/agile/1.0/board
jcli board list
jcli board list --project PROJ
jcli board list --max-results 100List sprints on a board.
API: GET /rest/agile/1.0/board/{boardId}/sprint
Sprint states: active, future, closed
jcli board sprint list --board-id 1
jcli board sprint list --board-id 1 --state activeCreate a new sprint on a board.
API: POST /rest/agile/1.0/sprint
jcli board sprint create --board-id 1 --name "Sprint 5"
jcli board sprint create --board-id 1 --name "Sprint 6" \
--start "2024-02-01T00:00:00.000Z" \
--end "2024-02-14T00:00:00.000Z" \
--goal "Complete the authentication module"Update a sprint's name, dates, goal or state.
API: PUT /rest/agile/1.0/sprint/{sprintId}
Valid state transitions: future → active, active → closed
jcli board sprint update --id 5 --name "Sprint 5 (extended)"
jcli board sprint update --id 5 --state active
jcli board sprint update --id 5 --state closedList all issues in a sprint.
API: GET /rest/agile/1.0/sprint/{sprintId}/issue
jcli board sprint issues --id 5
jcli board sprint issues --id 5 --output jsonAPI reference: https://developer.atlassian.com/cloud/jira/platform/rest/v2/api-group-users/
Get the currently authenticated user.
API: GET /rest/api/2/myself
jcli user myself
jcli user myself --output jsonGet a user by account ID.
API: GET /rest/api/2/user?accountId={accountId}
jcli user get --account-id "5f0d3aef12345678"Search for users by name or email.
API: GET /rest/api/2/user/search?query={query}
jcli user search --query "john"
jcli user search --query "smith" --max-results 20These commands list metadata useful for discovering valid values for other flags.
List all issue types. Use the NAME column for --type in jcli issue create.
API: GET /rest/api/2/issuetype
jcli meta issue-typesList all priorities. Use the NAME column for --priority.
API: GET /rest/api/2/priority
jcli meta prioritiesList all workflow statuses.
API: GET /rest/api/2/status
jcli meta statusesList all field definitions (system and custom).
API: GET /rest/api/2/field
jcli meta fields
jcli meta fields --output jsonSearch field definitions with filtering and pagination. Returns richer metadata
than meta fields including description, searcher key, and usage counts.
Note: Uses
GET /rest/api/2/field/searchwhich is not available on Jira Server / Data Center (returns HTTP 404). Usejcli meta fieldsinstead.
API: GET /rest/api/2/field/search (Cloud only)
| Flag | Description |
|---|---|
--id |
Filter by field ID (repeatable) |
--query |
Filter by name/description substring |
--type |
Filter by type: system or custom |
--order-by |
Order by: name, screensCount, contextsCount, projectsCount, lastUsed |
--expand |
Include extra data (comma-separated): screensCount, contextsCount, lastUsed |
--project-ids |
Filter to fields used in specific project IDs |
--start-at |
Pagination offset (default: 0) |
--max-results |
Page size (default: 50) |
jcli meta field-search
jcli meta field-search --type custom
jcli meta field-search --query "sprint" --output json
jcli meta field-search --id customfield_10014 --expand screensCount,contextsCount
jcli meta field-search --order-by name --max-results 100List the contexts a custom field is configured in. Contexts determine which projects and issue types the field applies to.
Note: Uses
GET /rest/api/2/field/{fieldId}/contextwhich is not available on Jira Server / Data Center (returns HTTP 404).
API: GET /rest/api/2/field/{fieldId}/context (Cloud only)
| Flag | Description |
|---|---|
--global |
Show only global (all-project) contexts |
--any-issue-type |
Show only contexts that apply to all issue types |
--context-id |
Filter by specific context IDs (repeatable) |
--start-at |
Pagination offset (default: 0) |
--max-results |
Page size (default: 50) |
jcli meta field-contexts customfield_10014
jcli meta field-contexts customfield_10014 --global
jcli meta field-contexts customfield_10014 --output jsonList the allowed option values for a custom select, radio, or checkbox field. This is the primary way to discover valid values before setting a custom field.
Note: Uses
GET /rest/api/2/field/{fieldId}/context/optionwhich is not available on Jira Server / Data Center. Usejcli meta field-allowed-values --issue <key>instead.
API: GET /rest/api/2/field/{fieldId}/context/option (Cloud only)
| Flag | Description |
|---|---|
--context-id |
Limit options to a specific context ID |
--only-options |
Exclude cascading sub-options |
--start-at |
Pagination offset (default: 0) |
--max-results |
Page size (default: 100) |
jcli meta field-options customfield_10014
jcli meta field-options customfield_10014 --context-id 10025
jcli meta field-options customfield_10014 --only-options --output jsonList the allowed values for a field using issue edit metadata. Works on both Jira Cloud and Jira Server / Data Center. Requires an existing issue key as context (Jira derives allowed values per-issue from its workflow state).
API: GET /rest/api/2/issue/{issueKey}/editmeta
| Flag | Description |
|---|---|
--issue |
Issue key to read edit metadata from (required) |
jcli meta field-allowed-values assignee --issue PROJ-123
jcli meta field-allowed-values customfield_10014 --issue PROJ-123 --output jsonList all resolution values. Use the NAME column for --resolution in
jcli issue transition apply.
API: GET /rest/api/2/resolution
jcli meta resolutions
jcli meta resolutions --output jsonShow version and build information for the connected Jira instance, including
deploymentType (Cloud vs Server).
API: GET /rest/api/2/serverInfo
jcli meta server-info
jcli meta server-info --output jsonList workflow statuses available in a project, grouped by issue type. More
precise than jcli meta statuses which lists all instance-level statuses.
API: GET /rest/api/2/project/{projectIdOrKey}/statuses
| Flag | Description |
|---|---|
--issue-type |
Filter output to a specific issue type name |
jcli meta project-statuses PROJ
jcli meta project-statuses PROJ --issue-type Bug
jcli meta project-statuses PROJ --output jsonList all issue link type definitions. Use the NAME column for
--type in jcli issue link create.
API: GET /rest/api/2/issueLinkType
jcli meta link-types
jcli meta link-types --output jsonShow instance-level feature flags (voting, watching, issue linking, sub-tasks, attachments, time tracking) and time-tracking unit settings.
API: GET /rest/api/2/configuration
jcli meta configuration
jcli meta configuration --output jsonAll commands support three output formats controlled by the --output / -o flag
or the output= property in ~/.config/jcli/config.properties:
| Format | Description |
|---|---|
table |
ASCII table (default) |
json |
Pretty-printed JSON – full API response |
plain |
Tab-separated values, suitable for awk, cut, etc. |
jcli issue search --jql "project = PROJ" --output json
jcli project list --output plain | cut -f1 # extract keys onlyGenerate a Personal Access Token (API token) from your Atlassian account:
- Visit https://id.atlassian.com/manage-profile/security/api-tokens
- Click Create API token
- Copy the token and set it in
~/.config/jcli/config.propertiesorJIRA_API_TOKEN
The token is sent as a Bearer token in the Authorization HTTP header.
Generate a Personal Access Token in Jira Server:
- Click your profile avatar → Profile
- Select Personal Access Tokens in the left sidebar
- Click Create token, give it a name and optional expiry
Alternatively, for older Jira Server versions that do not support PATs, you can
base64-encode username:password and set it as the token value after modifying
the client to use Basic auth (not supported out of the box – PAT is recommended).
For on-premise installations using self-signed certificates, use --insecure to
skip TLS verification:
jcli --server https://jira.internal --insecure project listOr add insecure=true to ~/.config/jcli/config.properties.
# See what's assigned to you
jcli issue search --jql "assignee = currentUser() AND status != Done ORDER BY priority DESC"
# View an issue
jcli issue get PROJ-42
# Add a comment
jcli issue comment add PROJ-42 --body "Fixed in PR #123. Ready for review."
# Move to Code Review
jcli issue transition list PROJ-42 # find the transition ID
jcli issue transition apply PROJ-42 --id 31
# Log time
jcli issue worklog add PROJ-42 --time-spent "3h" \
--started "2024-01-15T14:00:00.000+0000" \
--comment "Implementation and unit tests"# Create multiple issues from a file
while IFS=, read -r summary type; do
jcli issue create --summary "$summary" --type "$type"
done < issues.csv
# Export all open issues to JSON
jcli issue search \
--jql "project = PROJ AND status != Done" \
--max-results 500 \
--output json > open-issues.json
# Get your account ID
jcli user myself --output json | jq -r '.accountId'A skill definition for OpenCode and compatible AI agent
tools is bundled with jcli at
.agents/skills/jira/SKILL.md.
The skill is a structured reference document that teaches an AI agent how to
use jcli effectively. Once loaded, the agent can:
- Find and inspect projects — list all visible projects, retrieve full project details, and manage versions and components.
- Search issues with JQL — construct and execute Jira Query Language
queries with pagination, field selection, and full-page fetches; covering
common patterns like open sprints, assignee filters, date ranges, and custom
field expressions (
cf[<id>]). - Full issue CRUD — create issues with all supported fields (type, priority, labels, components, fix versions, parent, due date); update individual fields without touching others; delete issues with or without sub-tasks.
- View and control issue detail — fetch a single issue with selective field projection or a full JSON dump including empty/null values; understand how to surface custom field values and map their IDs to human-readable names.
- Workflow transitions — list the available transitions for any issue and apply them by ID, optionally setting a resolution.
- Sprint board interactions — list boards, view active/future/closed
sprints, inspect all issues in a sprint, create new sprints with goals and
dates, and advance sprint state (
future → active → closed). - Collaboration features — add, update and delete comments; assign and unassign issues; manage watchers; cast and remove votes; create and delete issue links; upload and delete attachments.
- Time tracking — list, add and delete work log entries using Jira's time
notation (
2h,30m,1d 4h). - Metadata discovery — enumerate all issue types, priorities, workflow statuses, and field definitions (system and custom) so the agent always uses valid values in commands.
- Common workflow recipes — daily standup queries, triage searches,
multi-page JSON exports, bulk scripting patterns, and custom field
inspection pipelines using
--output json.
The skill is picked up automatically based on where it lives:
| Location | When it is active |
|---|---|
~/.agents/skills/jira/SKILL.md |
All agent sessions on the machine (global) |
.agents/skills/jira/SKILL.md |
Agent sessions inside this repository only |
When installed via Homebrew, the skill file is placed at
$(brew --prefix)/share/jcli/SKILL.md. Symlinking it into
~/.agents/skills/jira/ makes it globally available:
mkdir -p ~/.agents/skills/jira
ln -sf "$(brew --prefix)/share/jcli/SKILL.md" ~/.agents/skills/jira/SKILL.mdWhen cloning the repository directly, the skill is already present at
.agents/skills/jira/SKILL.md and will be discovered automatically by any
compatible agent tool running inside the project directory.
jcli maps directly to the following Atlassian REST APIs:
| API | Documentation |
|---|---|
| Jira REST API v2 (core) | https://developer.atlassian.com/cloud/jira/platform/rest/v2/intro/ |
| Jira Agile REST API | https://developer.atlassian.com/cloud/jira/software/rest/intro/ |
| Jira Software (boards/sprints) | https://developer.atlassian.com/cloud/jira/software/rest/api-group-board/ |
| Issue fields reference | https://developer.atlassian.com/cloud/jira/platform/rest/v2/api-group-issue-fields/ |
| JQL reference | https://developer.atlassian.com/cloud/jira/platform/rest/v2/api-group-jql/ |
| API tokens (Cloud) | https://support.atlassian.com/atlassian-account/docs/manage-api-tokens-for-your-atlassian-account/ |
| Personal Access Tokens (Server) | https://confluence.atlassian.com/enterprise/using-personal-access-tokens-1026032365.html |
- Fork the repository
- Create a feature branch:
git checkout -b feature/my-feature - Make changes and add tests
- Run
go test ./...to verify - Submit a pull request
go test ./...
go test -race ./...
go test -coverprofile=coverage.out ./... && go tool cover -html=coverage.outmake build # builds bin/jcli for the current platform
make run # builds and runs bin/jcli
go build -o jcli . # build directly with goThe make release target handles the full release lifecycle:
- Compiles cross-platform tarballs (macOS amd64/arm64, Linux amd64/arm64) and a Windows binary into
dist/ - Computes SHA256 checksums and regenerates
Formula/jcli.rb - Commits the updated formula, creates the git tag, and pushes both
- Creates the GitHub release and uploads all assets
make release VERSION=v1.2.0You can also run the stages individually:
make dist VERSION=v1.2.0 # build tarballs only (into dist/)
make formula VERSION=v1.2.0 # dist + update Formula/jcli.rbThe formula is regenerated by scripts/update-formula.sh — do not edit
Formula/jcli.rb by hand.
jcli/
├── main.go # Entry point
├── Makefile # Build, test, release targets
├── Formula/
│ └── jcli.rb # Homebrew formula (generated — do not edit)
├── scripts/
│ └── update-formula.sh # Regenerates Formula/jcli.rb from dist/ checksums
├── cmd/
│ ├── root.go # Root command, global flags, config loading
│ ├── issue/issue.go # All issue sub-commands
│ ├── project/project.go # All project sub-commands
│ ├── board/board.go # Board and sprint sub-commands
│ ├── user/user.go # User sub-commands
│ └── meta/meta.go # Metadata sub-commands
└── internal/
├── config/
│ ├── config.go # Configuration loading logic
│ └── config_test.go # Config tests
├── client/
│ ├── client.go # Jira HTTP client and all API methods
│ └── client_test.go # Client tests
└── output/
└── output.go # Table/JSON/plain output formatting