Skip to main content

jiracommandkit

A Jira REST API toolkit for querying, creating, and managing tickets — usable as a Python library or as a jiracommandkit command-line tool.

Supports Jira Cloud's v3 issues API and the Service Desk API: JQL search, ticket creation (service-desk and regular projects), comments, attachments, label management, and mandatory-field discovery for projects with required custom fields.

Installation

pip install jiracommandkit

For local development, install from a clone in editable mode:

pip install -e ".[dev]"

Configuration

jiracommandkit reads credentials and settings in this order:

  1. A JIRACOMMANDKIT_<KEY> environment variable
  2. A value saved in ~/.config/jiracommandkit/jiracommandkit.json
  3. A caller-supplied default (None if not given)
Key Required Description
JIRA_USERNAME yes Jira account email/username.
JIRA_API_KEY yes Jira API token.
JIRA_BASE_URL yes Base URL, e.g. https://yourcompany.atlassian.net.
JIRA_SERVICE_DESK_ID no Default service desk ID used by create_ticket.
JIRA_REQUEST_TYPE_ID no Default request type ID used by create_ticket.
JIRA_SECURITY_LABELS no Comma-separated labels applied by create_security_ticket.
JIRA_MANDATORY_FIELDS_FILE no Path to a JSON file of per-project required fields (see below).

Setting credentials via environment variables

export JIRACOMMANDKIT_JIRA_USERNAME="you@example.com"
export JIRACOMMANDKIT_JIRA_API_KEY="your-api-token"
export JIRACOMMANDKIT_JIRA_BASE_URL="https://yourcompany.atlassian.net"

Setting credentials via the CLI (writes to ~/.config/jiracommandkit/jiracommandkit.json)

jiracommandkit config set JIRA_USERNAME you@example.com
jiracommandkit config set JIRA_API_KEY your-api-token
jiracommandkit config set JIRA_BASE_URL https://yourcompany.atlassian.net

jiracommandkit config list        # list saved keys
jiracommandkit config get JIRA_USERNAME

CLI usage

Search tickets with JQL

jiracommandkit search "project = ENG AND status = Open"
jiracommandkit search "project = ENG" --format json
jiracommandkit search "project = ENG" --fields summary status assignee --max-results 50

Get a single ticket

jiracommandkit get ENG-123
jiracommandkit get ENG-123 --format json

Comments

jiracommandkit comment add ENG-123 "Investigating now."
jiracommandkit comment add ENG-123 "Internal note" --internal
jiracommandkit comment list ENG-123

Labels

jiracommandkit label ENG-123 security backend        # overwrite the labels field
jiracommandkit label ENG-123 security --merge         # merge into existing labels

Update a field

jiracommandkit set-field ENG-123 summary "Updated summary text"
jiracommandkit set-field ENG-123 priority '{"id": "2"}'

Attachments

jiracommandkit attach ENG-123 ./screenshot.png

Create a ticket

# Service desk ticket, using JIRACOMMANDKIT_JIRA_SERVICE_DESK_ID / JIRACOMMANDKIT_JIRA_REQUEST_TYPE_ID
jiracommandkit create --summary "Printer on fire" --description "Send help" --priority 2

# Regular (non-service-desk) project ticket
jiracommandkit create --project ENG --issue-type Bug \
    --summary "Null pointer on checkout" \
    --description "Crashes when cart is empty" \
    --field customfield_10005='"Backend"'

# Override the service desk / request type for one call
jiracommandkit create --service-desk-id 4 --request-type-id 12 \
    --summary "New laptop" --description "Onboarding request"

Create a security ticket

Creates a ticket and applies JIRACOMMANDKIT_JIRA_SECURITY_LABELS to it:

jiracommandkit create-security \
    --summary "Suspicious login activity" \
    --description "Multiple failed logins from unfamiliar IP" \
    --priority 1 \
    --attachment ./evidence.log

Discover required fields for your Jira instance

Queries every service desk and project you have access to, and writes a starter JSON file listing required custom fields and their selectable values:

jiracommandkit discover-fields ~/.config/jiracommandkit/mandatory_fields.json
jiracommandkit config set JIRA_MANDATORY_FIELDS_FILE ~/.config/jiracommandkit/mandatory_fields.json

Edit the generated file to pick one requestTypeId (service desk projects) or issueType (regular projects) per project, and a single value for each required custom field. Once configured, create_ticket/create-security calls with a matching --project automatically include those fields:

{
    "SEC": {
        "serviceDeskId": 2,
        "requestTypeId": 36,
        "customfield_10001": {"value": "Security"}
    },
    "ENG": {
        "issueType": "Bug",
        "customfield_10005": "Backend"
    }
}

Library usage

Every CLI command has a corresponding method on jiracommandkit.JiraClient, so you can use jiracommandkit directly in other Python projects without shelling out.

from jiracommandkit import JiraClient

client = JiraClient()  # reads JIRACOMMANDKIT_JIRA_* env vars / jiracommandkit.json
issues = client.query_jql("project = ENG AND status = Open", max_results=100)

tickets_by_project = client.format_tickets(issues)
for ticket in tickets_by_project["ENG"]:
    print(ticket.key, ticket.status, ticket.summary)

Get a ticket

issue = client.get_jira_by_id("ENG-123")

Comments

client.add_comment_to_ticket("ENG-123", "Investigating now.", public=True)
comments = client.get_comments_for_ticket("ENG-123")

Labels

client.set_custom_labels("ENG-123", "labels", ["security", "backend"])   # overwrite
client.add_labels("ENG-123", ["security"])                                # merge

Update a field

client.edit_ticket_field("ENG-123", "summary", "Updated summary text")

Attachments

client.add_attachment_to_ticket("ENG-123", "./screenshot.png")

Create a ticket

ticket_key, ticket_id = client.create_ticket(
    summary="Null pointer on checkout",
    desc="Crashes when cart is empty",
    project_key="ENG",
    issue_type="Bug",
    extra_fields={"customfield_10005": "Backend"},
)

Create a security ticket

ticket_key, ticket_id = client.create_security_ticket(
    summary="Suspicious login activity",
    desc="Multiple failed logins from unfamiliar IP",
    priority=1,
    attachment_path="./evidence.log",
)

Discover mandatory fields

mapping = client.discover_mandatory_fields("~/.config/jiracommandkit/mandatory_fields.json")

Working with configuration directly

from jiracommandkit import JiraConfig

config = JiraConfig()
config.save_api_key("JIRA_USERNAME", "you@example.com")
username = config.get_api_key("JIRA_USERNAME")

Handling errors

from jiracommandkit import JiraClient, JiraConfigError, JiraAPIError

try:
    client = JiraClient()
    issues = client.query_jql("project = ENG")
except JiraConfigError as e:
    print(f"Missing configuration: {e}")
except JiraAPIError as e:
    print(f"Jira API request failed: {e}")

Data models

JiraTicket and JiraComment (in jiracommandkit.models) are plain dataclasses returned by JiraClient.format_tickets() / JiraTicket.from_api():

from jiracommandkit import JiraTicket

ticket = JiraTicket.from_api(issue)  # issue: a raw dict from the Jira API
ticket.key            # "ENG-123"
ticket.project         # "ENG"
ticket.summary
ticket.priority
ticket.assignee
ticket.status
ticket.description      # HTML-escaped, newlines converted to <br>
ticket.comments         # list[JiraComment], newest first, capped at 5
ticket.comments_as_html()
ticket.to_dict()

Development

pip install -e ".[dev]"
pytest

Building and publishing to PyPI

python -m pip install --upgrade build twine
python -m build                       # produces dist/*.whl and dist/*.tar.gz
python -m twine upload --repository testpypi dist/*   # verify on TestPyPI first
python -m twine upload dist/*                          # publish to PyPI
git tag v<version>
git push origin v<version>

License

BSD-3-Clause. See LICENSE.

Release files for jiracommandkit 1.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for jiracommandkit 1.0.0
File Size Uploaded
jiracommandkit-1.0.0.tar.gz 23.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for jiracommandkit 1.0.0
File Interpreter ABI Platform
jiracommandkit-1.0.0-py3-none-any.whl Python 3 none any Details

Total release size: 46.2 kB

Release files / jiracommandkit-1.0.0.tar.gz

Download URL jiracommandkit-1.0.0.tar.gz
Size 23.7 kB
Tags Source
SHA-256 checksum
How to use checksums
d9f15df19362a4cc676d1102621e8b0345eadd9fb39073776a2cab3eabff9829
BLAKE2b-256 checksum
How to use checksums
60887c570ecfc690ebbb142f72cba2d25ce91eb8faa9769cf6c65f040200eadc
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.4

Release files / jiracommandkit-1.0.0-py3-none-any.whl

Download URL jiracommandkit-1.0.0-py3-none-any.whl
Size 22.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
7bc9361b27619ce302d74bfc032bab2a55ebbaf383966dd047bb8a7702040183
BLAKE2b-256 checksum
How to use checksums
cb4381d050e153fed2c36bfd3ddb1138cb2d6e67dab984ef341e3eb60eeb3721
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.4

Release history Release notifications | RSS feed

This release

1.0.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page