npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

work-sdk

v0.5.0

Published

Unified TypeScript issue-tracker API for GitHub, GitLab, Linear, Jira, and Azure DevOps, with safe AI-agent writes.

Downloads

647

Readme

Work SDK

Let AI agents update work trackers without blind writes.

Work SDK is a unified TypeScript issue-tracker API for GitHub Issues, GitLab, Linear, Jira Cloud, and Azure DevOps. It turns every external mutation into a prepared, inspectable change before commit.

Documentation · Quickstart · Examples · Provider comparison · GitHub

npm install work-sdk

Requires Node.js 20 or later. Ships ESM, CommonJS, TypeScript declarations, zero runtime dependencies, and npm provenance.

Try it without credentials

The deterministic memory adapter exercises the same public contract as a real provider:

import { createWorkClient } from "work-sdk";
import { memoryWorkAdapter, workItemFixture } from "work-sdk/testing";

const adapter = memoryWorkAdapter({
  items: [workItemFixture({
    id: "123",
    identifier: "DEMO-123",
    title: "Ship the retry fix",
  })],
});

const work = createWorkClient({ adapter });
const change = await work.prepareComment("123", {
  body: "The deployment completed successfully.",
});

console.log(change.summary, change.changes, change.warnings);

const first = await work.commit(change, {
  idempotencyKey: "deploy:production:123",
});
const replay = await work.commit(change, {
  idempotencyKey: "deploy:production:123",
});

console.log(first.replayed);  // false
console.log(replay.replayed); // true — no duplicate provider write
console.log(first.comment.body); // typed as string for a comment receipt

Why a safe-write protocol?

A timeout cannot tell you whether an issue-tracker write failed or whether only its response was lost. Retrying can duplicate comments. At the same time, an item can change between an agent's read and write, making a previously reasonable update stale.

Work SDK separates intent from execution:

  1. Prepare reads current state, resolves provider semantics, and returns a field-level diff.
  2. Inspect lets an agent, policy, approval UI, or person review changes and warnings.
  3. Commit verifies the plan fingerprint and revision, then records idempotency.

The same idempotency key with the same completed intent returns the stored receipt. Reusing that key with different intent fails with WorkConflictError; an uncertain provider outcome fails with WorkAmbiguousCommitError and blocks blind retries.

Connect a provider

import { createWorkClient } from "work-sdk";
import { github } from "work-sdk/github";

const work = createWorkClient({
  adapter: github({
    token: process.env.GITHUB_TOKEN!,
    owner: "acme",
    repo: "web",
  }),
});

const change = await work.prepareUpdate("123", { state: "closed" });
console.log(change.changes, change.warnings);

await work.commit(change, {
  idempotencyKey: "merge:acme/web#481",
});

Credentials remain inside adapters and never appear in prepared changes.

Supported providers

| Provider | Import | Highlights | | --- | --- | --- | | GitHub Issues | work-sdk/github | Issues, comments, labels, assignees, open/closed state | | GitLab.com and Self-Managed | work-sdk/gitlab | Issues, comments, OAuth/private tokens, guarded label writes | | Linear | work-sdk/linear | Team states, priorities, projects, comments | | Jira Cloud | work-sdk/jira | Project transitions, ADF descriptions, comments | | Azure DevOps / Azure Boards | work-sdk/azure-devops | WIQL, process maps, parent links, atomic revision tests | | Deterministic testing | work-sdk/testing | In-memory adapter and fixtures |

Provider capabilities are runtime data. Check them before an agent proposes an operation:

if (!work.capabilities.priorities) {
  // Omit priority or route through a provider-specific implementation.
}

Work SDK or an official SDK?

Use Work SDK when you need a common issue-tracker client, a diff or approval boundary, coordinated retries, or stale-write protection. Use an official provider SDK when you need the provider's complete API surface or highly specific features with no normalization.

Work SDK is intentionally a focused safety and portability layer.

Durable idempotency

The default store atomically coordinates retries inside one process. Serverless, clustered, and job systems must provide a durable store with an atomic claim:

import type { IdempotencyStore } from "work-sdk";

const store: IdempotencyStore = {
  async acquire(key, intentFingerprint) {
    return db.claimWorkSdkIntent({ key, intentFingerprint });
  },
  async complete(key, leaseId, result) {
    await db.completeWorkSdkIntent({ key, leaseId, result });
  },
  async abandon(key, leaseId, outcome) {
    await db.abandonWorkSdkIntent({ key, leaseId, outcome });
  },
};

const work = createWorkClient({ adapter, idempotencyStore: store });

Use a stable key derived from a business event—not a random agent-run identifier.

An atomic claim is mandatory: a plain get followed by set can duplicate writes across workers. See the complete store contract.

Learn more

Open source under the MIT License.