A powerful Go library for interacting with Atlassian Jira Cloud and Server/Data Center APIs.
This library builds upon the excellent jira-cli project by Ankit Pokhrel, transforming it from a CLI tool into a reusable Go library.
This library started with the jira-cli project - a feature-rich, interactive command-line tool for Jira that has helped thousands of developers. We recognized that the core Jira API implementation within jira-cli was excellent and could benefit the broader Go community if made available as a standalone library.
While the core Jira API logic comes from jira-cli, we've made significant enhancements to transform it into a proper library:
- Created a completely new, simplified API wrapper
- Designed clean
ClientConfig
structure for easy initialization - Added high-level methods that hide complexity
- Implemented proper error propagation and handling
- Removed all CLI-specific logic and dependencies
- Added
NewClient()
function for stateless client creation - Removed global state and singleton patterns
- Made the package suitable for concurrent use
- Maintained backward compatibility while adding new features
- Created extensive library-focused documentation
- Added complete working examples (
examples/
directory) - Wrote inline code documentation for all public APIs
- Included authentication guides for all supported methods
- Unified API for both Cloud and Server installations
- Simplified method signatures for common operations
- Added convenient helper methods
- Proper Go module structure without CLI dependencies
- Clean separation of concerns
- Removed ~15,000 lines of CLI/TUI code
- Eliminated 20+ CLI-specific dependencies
- Restructured packages for library use
- Removed vendor lock-in
As of November 2024, Atlassian has deprecated the traditional search endpoints (/rest/api/3/search
and /rest/api/2/search
) for Jira Cloud. This library has been updated to use the new /rest/api/3/search/jql
endpoint automatically.
- New Endpoint: Search now uses
/rest/api/3/search/jql
for Cloud instances - Bounded Queries Required: The new API requires bounded JQL queries (e.g., with date or project restrictions)
- Automatic Bounds: The library automatically adds bounds if your query doesn't have them
- Backward Compatible: Server/Data Center installations continue to use the original endpoints
If you're upgrading from v0.3.0 or earlier:
- Your existing code should continue to work without changes
- Unbounded queries will automatically get a 90-day date restriction added
- Consider adding explicit bounds to your JQL queries for better performance
There are scenarios where you need programmatic access to Jira without CLI overhead:
- Building web services that integrate with Jira
- Creating automation scripts in Go
- Developing custom tools with specific workflows
- Embedding Jira functionality in existing applications
- Building company-specific CLIs with custom business logic
This library provides a clean, focused API for these use cases while preserving the battle-tested Jira integration code from the original project.
- Original jira-cli project: Ankit Pokhrel and contributors for the core Jira API implementation
- Library transformation: Significant refactoring and new development to create this library interface
If you need a full-featured CLI tool for Jira, the original jira-cli is excellent!
- 🚀 Full API Coverage - Support for Issues, Projects, Boards, Sprints, Epics, and more
- 🔐 Multiple Authentication - API tokens, Basic auth, Bearer tokens (PAT), and mTLS
- ☁️ Cloud & Server Support - Works with both Jira Cloud and Server/Data Center
- 🎯 Type Safety - Strongly typed Go structs for all Jira entities
- 🛡️ Error Handling - Comprehensive error types with detailed information
- 📦 Clean Library Design - No CLI dependencies, pure library functionality
- 🔄 Stateless Clients - Safe for concurrent use in services and applications
go get github.com/eliziario/jira-lib/lib
package main
import (
"fmt"
"log"
"github.com/eliziario/jira-lib/lib"
)
func main() {
// Create a client
client, err := lib.NewClient(lib.ClientConfig{
Server: "https://your-domain.atlassian.net",
Login: "[email protected]",
APIToken: "your-api-token",
})
if err != nil {
log.Fatal(err)
}
// Get an issue
issue, err := client.GetIssue("PROJ-123")
if err != nil {
log.Fatal(err)
}
fmt.Printf("Issue: %s - %s\n", issue.Key, issue.Fields.Summary)
}
client, err := lib.NewClient(lib.ClientConfig{
Server: "https://your-domain.atlassian.net",
Login: "[email protected]",
APIToken: "your-api-token", // Get from: https://id.atlassian.com/manage-profile/security/api-tokens
})
client, err := lib.NewClient(lib.ClientConfig{
Server: "https://jira.company.com",
Login: "username",
APIToken: "password", // Use password for basic auth
InstallationType: "Local",
})
client, err := lib.NewClient(lib.ClientConfig{
Server: "https://jira.company.com",
Login: "username",
APIToken: "personal-access-token",
AuthType: "bearer",
})
client, err := lib.NewClient(lib.ClientConfig{
Server: "https://jira.company.com",
Login: "username",
AuthType: "mtls",
MTLSConfig: &lib.MTLSConfig{
CaCert: "/path/to/ca.crt",
ClientCert: "/path/to/client.crt",
ClientKey: "/path/to/client.key",
},
})
// Search with JQL (manual pagination)
results, err := client.SearchIssues("project = PROJ AND status = 'In Progress'", 0, 50)
for _, issue := range results.Issues {
fmt.Printf("%s: %s\n", issue.Key, issue.Fields.Summary)
}
// Fetch ALL issues with automatic pagination
allIssues, err := client.GetAllIssues(lib.GetAllIssuesOptions{
Project: "PROJ",
StartDate: "2024-01-01",
DateField: "created",
JQL: "status != Closed",
OrderBy: "priority DESC",
})
fmt.Printf("Found %d total issues\n", len(allIssues))
// Fetch issues from the last 7 days
recentIssues, err := client.GetRecentIssues(7, "PROJ")
// Fetch issues in a date range
rangeIssues, err := client.GetIssuesByDateRange("2024-01-01", "2024-01-31", "updated")
request := &jira.CreateRequest{
Project: "PROJ",
Name: "Task",
Summary: "New task",
Body: "Task description",
Priority: "High",
Labels: []string{"backend", "urgent"},
}
response, err := client.CreateIssue(request)
fmt.Printf("Created: %s\n", response.Key)
request := &jira.EditRequest{
Summary: "Updated summary",
Priority: "Low",
Labels: []string{"updated"},
}
err := client.UpdateIssue("PROJ-123", request)
// Get available transitions
transitions, err := client.GetTransitions("PROJ-123")
// Apply transition
request := &jira.TransitionRequest{
Transition: &jira.TransitionRequestData{
ID: transitionID,
},
}
err = client.TransitionIssue("PROJ-123", request)
// Add public comment
err := client.AddComment("PROJ-123", "This is a comment", false)
// Add internal comment
err := client.AddComment("PROJ-123", "Internal note", true)
For operations not covered by the high-level API, you can access the underlying client:
rawClient := client.GetRawClient()
// Use any method from pkg/jira
meta, err := rawClient.GetCreateMeta(&jira.CreateMetaRequest{
Projects: "PROJ",
Expand: "projects.issuetypes.fields",
})
For more control over client configuration:
import (
"github.com/eliziario/jira-lib/api"
"github.com/eliziario/jira-lib/pkg/jira"
)
// Create client without global state
client := api.NewClient(jira.Config{
Server: "https://your-domain.atlassian.net",
Login: "[email protected]",
APIToken: "your-api-token",
})
The library provides typed errors for better error handling:
issue, err := client.GetIssue("PROJ-999")
if err != nil {
switch e := err.(type) {
case *jira.ErrUnexpectedResponse:
fmt.Printf("HTTP %d: %s\n", e.StatusCode, e.Status)
fmt.Printf("Error: %s\n", e.Body)
default:
if err == jira.ErrNoResult {
fmt.Println("Issue not found")
} else {
fmt.Printf("Error: %v\n", err)
}
}
}
lib/
- New high-level library interface with simplified APIapi/
- Enhanced client initialization and proxy functionspkg/jira/
- Core Jira API client implementation (from jira-cli)pkg/adf/
- Atlassian Document Format utilitiespkg/md/
- Markdown conversion utilitiespkg/jql/
- JQL query builderpkg/netrc/
- .netrc file support for authenticationexamples/
- New complete working examples demonstrating library usage
Check the examples directory for complete working examples:
- basic-usage - Simple command-line tool demonstrating core operations
- advanced-cli - Full-featured interactive CLI with configuration management
- fetch-all-issues - Demonstrates fetching all issues with pagination and filtering
All examples were created specifically to demonstrate library usage patterns.
- ✅ Issues (Create, Read, Update, Delete, Transition)
- ✅ Comments (Add, Update, Delete)
- ✅ Projects (List, Get details)
- ✅ Boards (List, Get board configuration)
- ✅ Sprints (List, Get issues in sprint)
- ✅ Epics (List, Get epic issues)
- ✅ Users (Search, Get user details)
- ✅ Worklogs (Add, Update)
- ✅ Issue Links (Create, Delete)
- ✅ Attachments (via raw client)
- ✅ Custom Fields (via raw client)
- ✅ JQL Search
- Go 1.21 or higher
- Jira Cloud or Server/Data Center instance
- API token or appropriate credentials
Contributions are welcome! Please feel free to submit a Pull Request.
For bugs or issues related to the core Jira API functionality, you may also want to check the original jira-cli project.
MIT License - see LICENSE file for details.
This library inherits its MIT license from the original jira-cli project.
- jira-cli - The original CLI tool this library was derived from
- go-jira - Another popular Go client library for Atlassian Jira
- jira-terminal - Terminal UI for Jira
If you find this library useful:
- ⭐ Star this repository
- 🐛 Report bugs or request features via issues
- 💻 Contribute improvements via pull requests
- ⭐ Also consider starring the original jira-cli project