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

@kud/gh-ink

v0.76.0

Published

Ink components for rendering GitHub PR review comments and health — controlled, presentation-only, built on @kud/ink-ui and fed by @kud/gh.

Readme

@kud/gh-ink

Controlled Ink components for rendering GitHub PR domain objects in the terminal. Presentation-first: data comes in as props (the consuming surface owns the fetch), mutations run against @kud/gh. Built on @kud/ink-ui.

Consumed by the standalone gh-pr-* CLIs and by cockpit — one component, many surfaces.

Install

npm install @kud/gh-ink @kud/gh

ink and react are peer dependencies.

Exports

| Export | What | | ----------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- | | CommentsPanel (CommentsPanelProps) | Selectable review-thread + conversation panel — resolve (x), reply (r), show/hide resolved (R). | | healthDisplay / healthGlyph / healthColor | Map a @kud/gh Health token → glyph + @kud/ink-ui colour. Glyph distinguishes (colourblind-safe); colour reinforces. | | healthLegend | Ordered [Health, label] pairs for a help legend. | | renderMarkdown | GitHub-flavoured markdown → styled terminal lines. |

Design

Every component is controlled — the parent owns loading and passes data in — so the same panel drops into a full-screen CLI or a single pane of a dashboard. The core (@kud/gh) decides the semantic token; this layer maps it to a colour. Same seam as @kud/jenkins → @kud/jenkins-ink.

Inbox extensions

A host contributes verbs and screens to the inbox through InboxExtension:

| Field | What | | ----------- | ----------------------------------------------------------------------------------------------------------- | | key | The keypress that opens it, matched after the inbox's own bindings, so an extension never shadows them. | | scope | "item" acts on the selected row and earns a place in its action menu; "global" does not. | | menuGroup | "act" (does something to the row) or "open" (opens something); absent or "other" joins the quiet end. | | hint | Short footer label. The action menu capitalises it for the row ("submit" → "Submit"); the legend keeps title. | | icon | Nerd-font glyph for the menu row, as a "\uF4FA" escape. Shown only in nerd icon mode (see below). | | body | (onExit, target) => ReactNode — rendered inside the inbox frame; claims header/footer via useChrome. |

Nerd-font icons render only when the host calls setIconMode("nerd") from @kud/ink-ui before the first render. In the default text mode the menu's icon column is dropped entirely — no stand-in, nothing to align — so a terminal without a Nerd Font loses nothing but decoration. The built-ins use these codepoints; sibling host verbs should match them rather than invent neighbours:

| Verb | Codepoint | | ----------------------------- | --------- | | Submit / Resubmit | U+F4FA / U+F46A | | Land | U+F419 | | Open PR / in browser / ticket | U+F440 / U+F465 / U+F41B | | Switch here / tab / pane | U+EBCB / U+EAE4 / U+EB56 | | Copy URL / repo / branch | U+F44C / U+F401 / U+F418 | | Unsubscribe / Mute / Remove reviewer | U+F478 / U+F466 / U+F468 | | Close PR / and delete / issue | U+F4DC / U+F48E / U+F41D |

Inbox focus slot and tab icons

App draws one standing row directly above the tab strip for whatever the reader should look at next. The fetch result carries it as focus?: FocusSlot | null: absent means the host has no focus feature and no row is drawn; null means nothing to point at and draws the dim empty line. It rides the fetch (and the cache beside the rows) because it goes stale the same way they do.

| Prop / field | What | | ------------------ | --------------------------------------------------------------------------------------------------- | | focusLabel | What to call the row (default focus). Passing this or focusEmpty reserves the row from first paint. | | focusEmpty | The empty sentence, drawn dim after the label when focus comes back null. | | FocusSlot | label, ref (a ticket key, or a PR-style #427), title, reason, optional marker (the host's priority glyph), mark/markColor/refColor overrides, and target: { tab, url }. | | g | Jumps to focus.target: switches to that tab and lands the cursor on that row, opening a collapsed tail it is folded into. Listed in the ? legend only while a focus is on screen. |

A row whose url matches the target draws the mark in a fixed gutter between the tree glyph and the marker cell; every other row holds two blanks there, so the mark moves nothing sideways. Without a focus the rows draw what they always drew.

Tabs take an optional Section.icon, passed through to ink-ui's TabItem.icon: one glyph naming the tab beside its label, which is also what an inactive tab folds down to when the strip does not fit its width.

Development

npm run typecheck
npm run test
npm run build

Licence

MIT © Erwann Mest