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

@rallycry/conveyor-incidents

v0.3.1

Published

Typed TypeScript client for Conveyor's public incidents REST API

Readme

@rallycry/conveyor-incidents

Typed TypeScript client for reporting incidents to Conveyor via the public REST API.

Install

npm install @rallycry/conveyor-incidents
# or
bun add @rallycry/conveyor-incidents

Usage

import { ConveyorIncidents } from "@rallycry/conveyor-incidents";

const incidents = new ConveyorIncidents({
  apiKey: process.env.CONVEYOR_INCIDENT_TOKEN!, // cvyr_... project token with "incident" scope
  projectId: process.env.CONVEYOR_PROJECT_ID!,
});

const { incidentId, attachmentResults } = await incidents.report({
  title: "Checkout service returned 500",
  description: "Happened on release v1.4.2 under load.",
  severity: "high",
  source: "prod-web", // stable values let the server dedup repeats
  fingerprintKey: "checkout-500-v1.4.2",
  attachments: [
    {
      fileName: "stack.txt",
      mimeType: "text/plain",
      content: stackTrace, // string or Uint8Array
    },
  ],
});

Card types

report() accepts an optional type"incident" (default), "suggestion", or "task":

  • "incident" — fingerprint dedup (see below); repeat reports collapse into one incident.
  • "suggestion" — AI duplicate detection; a repeat report upvotes the existing suggestion and returns its id instead of creating a new card. fingerprintKey and severity are ignored (suggestions are ranked by votes).
  • "task" — creates a plain task card. No dedup; fingerprintKey is ignored. severity maps to the card's priority.
// Platform-user suggestion, routed to the team for review
await incidents.report({
  type: "suggestion",
  title: "Add dark mode toggle",
  assigned: ["[email protected]"],
  review: ["[email protected]", "[email protected]"],
});

Assigning members by email

assigned and review are optional arrays of email addresses, matched against the target project's members:

  • assigned — the first email that resolves to a project member becomes the card's assignee; remaining entries are ignored.
  • reviewevery email that resolves to a project member is added as a reviewer.
  • Emails that don't match a project member are silently skipped — safe to pass end-user emails; only teammates who are members of the Conveyor project resolve.
  • Applied only when a new card is created. Dedup hits (incident fingerprint match, suggestion AI-merge) leave the existing card untouched.
// Incident auto-assigned when reporter is @rallycry.gg
await incidents.report({
  title: "Checkout service returned 500",
  severity: "high",
  fingerprintKey: "checkout-500-v1.4.2",
  assigned: ["[email protected]"],
});

Creator attribution (createdBy)

createdBy is an optional single email, matched against the target project's members the same way as assigned/review:

  • A resolvable project-member email becomes the card's creator.
  • When omitted — or when the email doesn't resolve to a member — the card is attributed to the "Conveyor Incidents" system user, not a human.
  • Applied only when a new card is created; dedup hits keep the existing creator.

Behavior change in 0.3.0: previously, cards reported through this endpoint were attributed to the token owner (suggestions/tasks) or the project owner (incidents). Pass createdBy explicitly if you want a specific member credited.

await incidents.report({
  type: "task",
  title: "Wire up the new webhook",
  createdBy: "[email protected]",
});

About source and fingerprintKey

Conveyor deduplicates reports by a fingerprint derived from (projectId, source, fingerprintKey) — or by (projectId, source, title) if fingerprintKey is omitted. Use stable values for source (e.g. "prod-web", not "node-pid-1234") so that repeat reports collapse into a single incident instead of creating noise.

Attachment limits

  • 5 MB per file (MAX_ATTACHMENT_BYTES, exported). Oversized files are rejected client-side with a descriptive attachmentResults error — no HTTP call is made.
  • 10 attachments per card (server-enforced).

Error handling

  • The main report() call throws ConveyorIncidentsError on non-2xx responses; it exposes .status and .body.
  • Attachment upload failures are captured per-file in attachmentResults and never throw — inspect ok and error.

Node <18

Pass a fetch polyfill via opts.fetch if your runtime lacks a global fetch.

DEP0169 url.parse() warning

The @rallycry/conveyor-incidents SDK does not call url.parse() — it uses the WHATWG URL constructor and the global fetch API. If your process emits this warning while using the SDK, the call is coming from another dependency in your project. Run node --trace-deprecation your-script.js to locate the source.

Troubleshooting 403 from /api/incidents/report

The endpoint requires a project token with scope: "incident". After the 2026-04-22 scope migration, older project tokens default to scope: "claude_code" and are rejected. The error body now includes a reason field — "scope_mismatch" indicates the token exists but is scoped for another surface; generate a new token from Project Settings → Incidents in the Conveyor UI.

API

new ConveyorIncidents({
  apiKey: string;
  projectId: string;
  baseUrl?: string; // default: "https://api.conveyor.rallycryapp.com"
  fetch?: typeof fetch;
});

client.report({
  title: string;
  description?: string;
  severity?: "critical" | "high" | "medium" | "low"; // default: "medium"
  source?: string;                                    // default: "client"
  fingerprintKey?: string;
  plan?: string;
  type?: "incident" | "suggestion" | "task";          // default: "incident"
  assigned?: string[]; // project-member emails; first match becomes assignee
  review?: string[];   // project-member emails; every match becomes a reviewer
  createdBy?: string;  // project-member email; no match → "Conveyor Incidents" system user
  attachments?: Array<{
    fileName: string;
    mimeType: string;
    content: Uint8Array | string; // strings are utf-8 encoded
  }>;
}): Promise<{
  incidentId: string;
  cardId: string; // alias of incidentId — prefer for suggestion/task types
  attachmentResults: Array<{
    fileName: string;
    ok: boolean;
    fileId?: string;
    error?: string;
  }>;
}>;

License

MIT