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:
- A
JIRACOMMANDKIT_<KEY>environment variable - A value saved in
~/.config/jiracommandkit/jiracommandkit.json - A caller-supplied default (
Noneif 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
Search
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)
| File | Size | Uploaded | |
|---|---|---|---|
| jiracommandkit-1.0.0.tar.gz | 23.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| 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
|