Announcing the Distilled Jira SDK
Search, inspect, and automate Jira Cloud from Effect with a reviewable SDK generated from Atlassian's official API contract.
Jira is where a great deal of engineering work becomes visible: planned work, active incidents, release blockers, support escalations, and the history around all of them. Today we are publishing @kevinmichaelchen/distilled-jira, an Effect-native Jira Cloud client built from Atlassian’s official REST API v3 description.
Jira, at a glance
Jira is Atlassian’s work-management platform. Its Cloud REST API v3 lets integrations search and mutate issues, projects, workflows, fields, permissions, users, dashboards, filters, and more. Version 3 also represents rich text with Atlassian Document Format.
Official API docs
SDK repository
Specification mirror
npm package
Why Effect and Distilled?
Jira automation rarely ends with one request. A useful workflow searches, paginates, branches on issue state, retries rate limits, records failures, and often updates several issues. Effect gives that workflow one typed model for dependencies, failures, retries, concurrency, cancellation, and tracing. Distilled adds runtime request and response schemas, redacted credentials, Jira-specific error decoding, and Retry-After awareness.
The result is more than autocomplete: API boundary failures remain explicit values, and the same program can be tested with replacement layers instead of hidden global clients.
How we made the SDK
Mirror the authority
Pin, patch, generate
Keep policy handwritten
Publish independently
The shared generator also normalizes Atlassian’s handful of Java-style dotted operation IDs into the same lower camelCase convention used by the rest of the Jira surface. That policy stays in the common factory rather than becoming a Jira-only collection of aliases.
Code Examples
Set JIRA_BASE_URL, JIRA_EMAIL, and JIRA_API_TOKEN, then install the package:
npm install @kevinmichaelchen/distilled-jira effectpnpm add @kevinmichaelchen/distilled-jira effectbun add @kevinmichaelchen/distilled-jira effectimport * as Effect from "effect/Effect";
import * as Layer from "effect/Layer";
import * as FetchHttpClient from "effect/unstable/http/FetchHttpClient";
import {
addComment,
createIssue,
CredentialsFromEnv,
searchAndReconcileIssuesUsingJql,
} from "@kevinmichaelchen/distilled-jira";
const JiraLive = Layer.mergeAll(FetchHttpClient.layer, CredentialsFromEnv);
Find unresolved issues in a project
Build a review queue with JQL while requesting only the fields needed by the workflow.
const openIssues = searchAndReconcileIssuesUsingJql({
jql: 'project = "PAY" AND resolution = Unresolved ORDER BY priority DESC',
fields: ["summary", "status", "priority", "assignee"],
maxResults: 50,
});
const findOpenIssues = openIssues.pipe(Effect.provide(JiraLive));
Create an issue
Create work from an alert, support escalation, or release check. Jira’s flexible fields object accommodates project-specific custom fields.
const createBug = createIssue({
fields: {
project: { key: "PAY" },
issuetype: { name: "Bug" },
summary: "Checkout requests exceed the latency budget",
labels: ["automation", "performance"],
},
}).pipe(Effect.provide(JiraLive));
Add a structured comment
Attach automation results to an existing issue using Atlassian Document Format.
const addAutomationComment = addComment({
issueIdOrKey: "PAY-123",
body: {
type: "doc",
version: 1,
content: [{
type: "paragraph",
content: [{ type: "text", text: "The latest canary completed successfully." }],
}],
},
}).pipe(Effect.provide(JiraLive));
Each output is decoded at the boundary. Jira authentication failures, missing permissions, malformed responses, and retryable status codes remain visible in the Effect error channel rather than collapsing into an untyped thrown value.
Available now
Start with the Jira SDK guide, inspect the implementation, or install @kevinmichaelchen/distilled-jira.