A universal command-line utility and Python library for managing tickets across multiple ticketing systems. TicketQ provides a unified interface for Zendesk, Jira, ServiceNow, and other platforms through a pluggable adapter architecture.
TicketQ connects to various ticketing systems via their APIs to provide a fast, unified terminal interface for ticket management. It uses pluggable adapters to support multiple platforms, secure credential storage, and provides rich filtering, sorting, and export capabilities.
Key Benefits:
- 🔌 Multi-platform support - Zendesk, Jira, ServiceNow through adapters
- 🚀 Fast ticket overview - See all your tickets at a glance
- 🎯 Smart filtering - Filter by assignee, groups, status, or combinations
- 📊 Flexible sorting - Sort by any column for better organization
- 💾 CSV export - Export filtered results with full descriptions
- 🔒 Secure - API tokens stored safely in system keyring
- 🎨 Beautiful output - Rich terminal tables with color coding
- 📦 Library ready - Use programmatically in your Python applications
- 🔧 Adapter architecture - Easy to extend with new ticketing systems
# Install TicketQ core with CLI dependencies
pip install "ticketq[cli]"
# Or install from GitHub
pip install "git+https://github.com/jamiemills/ticketq.git[cli]"TicketQ requires adapter packages for specific ticketing systems:
# Install Zendesk adapter
pip install ticketq-zendesk
# Install Jira adapter (planned)
pip install ticketq-jira
# Install ServiceNow adapter (planned)
pip install ticketq-servicenow# Install core library without CLI dependencies
pip install ticketq
# Or from GitHub
pip install git+https://github.com/jamiemills/ticketq.git# Clone and install with all dependencies
git clone https://github.com/jamiemills/ticketq.git
cd ticketq
pip install -e ".[cli,dev]"
pip install -e "./src/ticketq-zendesk" # Install Zendesk adapter in dev mode# Install TicketQ with CLI support
pip install "ticketq[cli]"
# Install Zendesk adapter
pip install ticketq-zendesk# Configure Zendesk (or any available adapter)
tq configure --adapter zendesk
# Or let TicketQ auto-detect
tq configureYou'll be prompted for adapter-specific credentials (e.g., for Zendesk):
- Domain (e.g.,
company.zendesk.com) - Email address (your account email)
- API token (generate from platform)
# List all open tickets
tq tickets
# List only your assigned tickets
tq tickets --assignee-only
# List tickets by team/group
tq tickets --group "Support Team"
# View available adapters
tq adapters- Multi-status filtering - Filter by single or multiple statuses (
--status "open,pending") - Team/group filtering - Filter by team names or IDs (
--group "Support Team,Engineering") - Assignee filtering - Show only tickets assigned to you (
--assignee-only) - Column sorting - Sort by any column (
--sort-by days-updated) - CSV export - Export results with full descriptions (
--csv tickets.csv) - Team name resolution - Shows actual team names instead of group IDs
- Secure credential storage - API tokens stored in system keyring
- Rich terminal output - Beautiful colored tables with proper formatting
- By Status:
new,open,pending,hold,solved,closed - By Assignment: Personal tickets, team tickets, or all tickets
- By Groups: Single team, multiple teams, or group IDs
- Multiple Status: Combine statuses like
"hold,closed"for OR logic
- ticket - Sort by ticket number
- status - Sort by ticket status
- team - Sort by team/group name
- description - Sort by description text
- opened - Sort by creation date (newest first)
- days-opened - Sort by age since creation
- updated - Sort by last update date (newest first)
- days-updated - Sort by staleness since last update
- CSV export with full ticket descriptions (not truncated)
- Proper escaping of commas and special characters
- All columns included matching table display format
- UTF-8 encoding for international character support
Basic Usage:
tq tickets [OPTIONS]All Options:
--assignee-only # Show only tickets assigned to you
--group TEXT # Filter by group ID(s) or name(s) (comma-separated)
--status TEXT # Filter by status(es) (comma-separated, default: open)
--sort-by [id|title|status|team|created_at|updated_at|days_created|days_updated]
--csv PATH # Export results to CSV file
--config-path PATH # Use custom configuration directory
--adapter TEXT # Override adapter selectionStatus Values:
new- Newly created ticketsopen- Open and active ticketspending- Waiting for customer responsehold- On hold/paused ticketssolved- Resolved ticketsclosed- Closed and archived tickets
Basic Usage:
tq configure [OPTIONS]Options:
--adapter TEXT # Adapter to configure (zendesk, jira, servicenow)
--config-path PATH # Custom configuration directory path
--test # Test connection after configuration
--list-adapters # List available adapters and exitBasic Usage:
tq adapters [OPTIONS]Options:
--config-path PATH # Use custom configuration directory
--test # Test all configured adapters
--install-guide # Show installation guide for adapters# All open tickets (default)
tq tickets
# Multiple statuses - tickets that are open OR pending
tq tickets --status "open,pending"
# Tickets on hold or closed
tq tickets --status "hold,closed"
# Only your assigned tickets
tq tickets --assignee-only
# Specific team's tickets
tq tickets --group "Support Team"
# Multiple teams
tq tickets --group "Support Team,Engineering,Sales"
# Use specific adapter
tq tickets --adapter zendesk# Sort by oldest tickets first (most urgent)
tq tickets --sort-by days_created
# Sort by most stale (needs attention)
tq tickets --sort-by days_updated
# Sort by team for grouping
tq tickets --sort-by team
# Sort by ticket ID
tq tickets --sort-by id# Export all open tickets
tq tickets --csv tickets.csv
# Export stale tickets sorted by age
tq tickets --status "open,pending" --sort-by days_updated --csv stale.csv
# Export team-specific tickets
tq tickets --group "Support Team" --csv support_tickets.csv
# Export multiple statuses for reporting
tq tickets --status "hold,closed" --csv closed_tickets.csv# Find stale pending tickets for specific teams
tq tickets --status "pending" --group "Support Team,Level 2" --sort-by days_updated --csv stale_pending.csv
# Export all your tickets across all statuses
tq tickets --assignee-only --status "new,open,pending,hold" --sort-by created_at --csv my_tickets.csv
# Get overview of closed tickets by team
tq tickets --status "solved,closed" --sort-by team --csv closed_by_team.csv$ tq tickets --status "open,pending" --sort-by days_updated
📋 Fetching open,pending tickets...
📊 Found 4 open,pending ticket(s):
🎫 Zendesk Tickets
┏━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ Ticket # ┃ Status ┃ Team Name ┃ Description ┃ Opened ┃
┣━━━━━━━━━━╋━━━━━━━━━╋━━━━━━━━━━━━━━━━━╋━━━━━━━━━━━━━━━━━━━━━━━━━━━╋━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
┃ #12345 ┃ Open ┃ Support Team ┃ Login system not work... ┃ 2024-01-15 ┃
┃ #12346 ┃ Pending ┃ Engineering ┃ Database performance i... ┃ 2024-01-18 ┃
┃ #12347 ┃ Open ┃ Support Team ┃ Email notifications no... ┃ 2024-01-20 ┃
┃ #12348 ┃ Pending ┃ Level 2 Support ┃ Complex integration is... ┃ 2024-01-22 ┃
┗━━━━━━━━━━┻━━━━━━━━━┻━━━━━━━━━━━━━━━━━┻━━━━━━━━━━━━━━━━━━━━━━━━━━━┻━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
┏━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ Days Since Opened ┃ Updated ┃ Days Since Updated ┃ Link ┃
┣━━━━━━━━━━━━━━━━━━━━━╋━━━━━━━━━━━━━━━━━━━━━━━━━━━╋━━━━━━━━━━━━━━━━━━━━━━━━━━━╋━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
┃ 13 ┃ 2024-01-20 ┃ 8 ┃ https://company.zendesk.com/agent/... ┃
┃ 10 ┃ 2024-01-22 ┃ 6 ┃ https://company.zendesk.com/agent/... ┃
┃ 8 ┃ 2024-01-24 ┃ 4 ┃ https://company.zendesk.com/agent/... ┃
┃ 6 ┃ 2024-01-26 ┃ 2 ┃ https://company.zendesk.com/agent/... ┃
┗━━━━━━━━━━━━━━━━━━━━━┻━━━━━━━━━━━━━━━━━━━━━━━━━━━┻━━━━━━━━━━━━━━━━━━━━━━━━━━━┻━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
📈 Summary:
Total: 4 tickets
Status: open: 2, pending: 2$ tq tickets --csv tickets.csv
📋 Fetching open tickets...
✅ Exported 4 tickets to tickets.csv
📊 Found 4 open ticket(s):
[table output continues...]CSV Content (tickets.csv):
"Ticket #","Status","Team Name","Description","Opened","Days Since Opened","Updated","Days Since Updated","Link"
"#12345","Open","Support Team","Login system not working for users - customers report authentication failures","2024-01-15","13","2024-01-20","8","https://company.zendesk.com/agent/tickets/12345"
"#12346","Pending","Engineering","Database performance issues causing timeouts","2024-01-18","10","2024-01-22","6","https://company.zendesk.com/agent/tickets/12346"
$ tq configure --adapter zendesk --test
🔧 Configuring Zendesk adapter
Enter your configuration details:
Zendesk domain (e.g., company.zendesk.com): company.zendesk.com
Your email address: [email protected]
Your API token: [hidden]
✅ Configuration saved for zendesk adapter
🔍 Testing connection...
✅ Successfully connected as John Doe ([email protected])
✅ Configuration test successful!
🎉 Setup complete! You can now run 'tq tickets' to list your tickets.$ tq tickets --assignee-only --status closed
📋 Fetching closed tickets...
✅ No closed tickets found!Configuration is stored securely across platforms:
- Linux/Mac:
~/.config/ticketq/config.json - Windows:
%APPDATA%\ticketq\config.json - API Token: Stored securely in system keyring (not in the JSON file)
Configure using command-line flags:
tq configure --adapter zendesk --test
# Interactive prompts will guide you through configurationtq tickets --config-path ./custom-config/- Log into your Zendesk instance as an administrator
- Go to Admin Center → Apps and integrations → APIs → Zendesk API
- Enable "Token access" if not already enabled
- Click "+ Add API token"
- Enter a description (e.g., "CLI Tool Access")
- Copy the generated token (save it securely - you won't see it again)
- Use this token when running
tq configure --adapter zendesk
Reference: Zendesk API Token Documentation
"No configuration found"
# Solution: Run configuration first
tq configure --adapter zendesk --test"Authentication failed"
# Solution: Check credentials and reconfigure
tq configure --adapter zendesk --test
# List configured adapters
tq adapters"Permission denied"
- Ensure your Zendesk user has API access enabled
- Verify your user role has ticket viewing permissions
- Check that your API token hasn't expired
"Group 'Team Name' not found"
- Verify the team name exists in your Zendesk instance
- Try using the group ID instead:
--group 12345 - Check you have access to view that group's tickets
Enable verbose logging for troubleshooting:
tq --verbose tickets
tq --log-file debug.log tickets# Clone and setup
git clone https://github.com/jamiemills/ticketq.git
cd ticketq
# Create virtual environment
python -m venv venv
source venv/bin/activate # Windows: venv\Scripts\activate
# Install with development dependencies
pip install -e ".[dev]"
# Install pre-commit hooks
pre-commit install# All tests
pytest
# With coverage
pytest --cov=src --cov-report=html
# Specific test category
pytest tests/unit/
pytest tests/integration/# Format code
black src/ tests/
# Sort imports
isort src/ tests/
# Lint
ruff check src/ tests/
# Type checking
mypy src/- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Write tests for your changes
- Ensure all tests pass (
pytest) - Ensure code quality checks pass (
black,ruff,mypy) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
TicketQ can be used as a Python library in your own applications. This is useful for automation, integration with web applications, or building custom reporting tools across multiple ticketing platforms.
from ticketq import TicketQLibrary
# Initialize with auto-detected adapter
tq = TicketQLibrary.from_config()
# Or initialize with specific adapter
tq = TicketQLibrary.from_config(adapter_name="zendesk")
# Test connection
if tq.test_connection():
print("✅ Connected successfully")
# Get tickets with filtering
tickets = tq.get_tickets(
status=["open", "pending"],
assignee_only=True,
sort_by="days_updated"
)
print(f"Found {len(tickets)} tickets")
# Export to CSV
tq.export_to_csv(tickets, "my_tickets.csv")
# Get adapter information
adapter_info = tq.get_adapter_info()
print(f"Using {adapter_info['display_name']} adapter")from flask import Flask, jsonify
from ticketq import TicketQLibrary
app = Flask(__name__)
tq = TicketQLibrary.from_config()
@app.route('/api/tickets')
def get_tickets_api():
try:
tickets = tq.get_tickets(status=["open", "pending"])
adapter_info = tq.get_adapter_info()
return jsonify({
'success': True,
'count': len(tickets),
'adapter': adapter_info['name'],
'tickets': [ticket.dict() for ticket in tickets]
})
except Exception as e:
return jsonify({'success': False, 'error': str(e)}), 500from ticketq import TicketQLibrary
from datetime import datetime
def daily_stale_tickets_report():
tq = TicketQLibrary.from_config()
# Get stale tickets (not updated in 3+ days)
all_tickets = tq.get_tickets(status=["open", "pending"])
stale_tickets = [t for t in all_tickets if t.days_since_updated >= 3]
# Export with timestamp
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
adapter_name = tq.get_adapter_info()['name']
tq.export_to_csv(stale_tickets, f"reports/{adapter_name}_stale_tickets_{timestamp}.csv")
return len(stale_tickets)from ticketq import TicketQLibrary
def progress_callback(message):
print(f"[INFO] {message}")
tq = TicketQLibrary.from_config(
adapter_name="zendesk",
progress_callback=progress_callback
)
# Operations will now report progress:
# [INFO] Fetching tickets...
# [INFO] Found 25 ticket(s)
tickets = tq.get_tickets()from ticketq import (
TicketQLibrary,
AuthenticationError,
NetworkError,
ConfigurationError,
PluginError
)
try:
tq = TicketQLibrary.from_config()
tickets = tq.get_tickets()
except AuthenticationError:
print("❌ Invalid credentials")
except NetworkError:
print("❌ Network connection failed")
except ConfigurationError:
print("❌ Configuration missing or invalid")
except PluginError:
print("❌ Adapter not found or failed to load")
except Exception as e:
print(f"❌ Unexpected error: {e}")from ticketq import TicketQLibrary
# Use different adapters for different operations
zendesk_tq = TicketQLibrary.from_config(adapter_name="zendesk")
jira_tq = TicketQLibrary.from_config(adapter_name="jira")
# Combine tickets from multiple systems
all_tickets = []
all_tickets.extend(zendesk_tq.get_tickets(status=["open"]))
all_tickets.extend(jira_tq.get_tickets(status=["in progress"]))
print(f"Total tickets across all systems: {len(all_tickets)}")The library provides these main classes:
TicketQLibrary- Main interface for all operationsLibraryTicket- Ticket data model with JSON serializationLibraryUser- User data modelLibraryGroup- Group/team data model
Key methods on TicketQLibrary:
get_tickets()- Retrieve tickets with filtering and sortingget_ticket()- Get a specific ticket by IDget_current_user()- Get current authenticated user infoget_groups()- Get all available groups/teamssearch_tickets()- Search tickets with system-specific queriesexport_to_csv()- Export tickets to CSV formattest_connection()- Verify API connectionget_adapter_info()- Get information about current adapter
For complete examples, see the comprehensive example files:
examples/library_usage.py- Complete library API examplesexamples/automation_scripts.py- Automation and scheduled reportingexamples/web_integration.py- Flask and FastAPI integration
- Documentation: This README and inline help (
tq --help) - Repository: https://github.com/jamiemills/ticketq
- Issues: Report bugs and request features via GitHub Issues
- Adapters:
- Zendesk API Documentation
- Jira API Documentation (planned)
- ServiceNow API Documentation (planned)
Want to add support for a new ticketing system? TicketQ's adapter architecture makes it easy:
- Create a new package (e.g.,
ticketq-linear) - Implement the adapter interfaces (
BaseAdapter,BaseAuth,BaseClient) - Register your adapter with the entry point:
"ticketq.adapters" - Users can install and use it:
pip install ticketq-linear
See the Zendesk adapter implementation for a complete example.
MIT License - see LICENSE for details.