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.
Metadata
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 | Provenance | Actions |
|---|---|---|---|---|
| jiracommandkit-1.0.0.tar.gz | 23.7 kB | Without provenance | Details for jiracommandkit-1.0.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| jiracommandkit-1.0.0-py3-none-any.whl | Python 3 | none | any | Details for jiracommandkit-1.0.0-py3-none-any.whl |
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
|
Security for jiracommandkit 1.0.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.