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

@adfrolic/claude-code-integration

v0.1.1

Published

Claude Code integration: a statusline command showing sponsored messages — see README.md.

Readme

Claude Code integration

Status: implemented (Phase 6 of docs/architecture.md's build order). A small Node CLI (adfrolic-claude-code) with two commands:

  • adfrolic-claude-code auth — run once, interactively, to sign in (device-authorization flow — see below). Writes ~/.adfrolic/session.json (0600).
  • adfrolic-claude-code statusline — the command Claude Code's statusLine.command setting invokes on every refresh. Fast, non-interactive, and fails silent (prints nothing, exits 0) on any error, slow network, or missing session — see src/statuslineCommand.ts's doc comment.

The bin is named adfrolic-claude-code, not adfrolic, so it never collides with the universal installer package (adfrolic on npm, see installer/README.md) if both happen to be installed globally at once — most developers only need one or the other (see "Which install path should I use?" below).

Setup

npm install -g @adfrolic/claude-code-integration   # once published
adfrolic-claude-code auth                           # once, interactively

Then add to Claude Code's settings.json:

{
  "statusLine": {
    "type": "command",
    "command": "adfrolic-claude-code statusline"
  }
}

Which install path should I use?

There are two independent ways to get the Claude Code statusline working, and they intentionally don't share a runtime — installing (or updating) one never silently touches the other:

  • npx adfrolic install --host=claude-code (see installer/README.md) — the quickest path: one universal CLI detects Claude Code is present and wires ~/.claude/settings.json itself, using its own bundled, dependency- free statusline/auth implementation (installer/lib/statusline.js). Good default if you also use other AdFrolic-supported editors and want one tool to set all of them up.
  • This package (@adfrolic/claude-code-integration) — a dedicated, separately-versioned package with its own more extensive test suite (authStore.test.ts, statuslineCommand.test.ts) and a couple of extra hardening details (a hard 2-second render deadline, explicit stdin draining). Good default if you only use Claude Code and want the most thoroughly-tested implementation, or if you're scripting/pinning an exact version outside the universal installer's release cadence.

Both talk to the same backend (GET /v1/ads/serve, placement claude_code.wait) and are functionally equivalent from the backend's point of view — pick whichever install path suits you and don't install both globally at once (Claude Code's statusLine.command only runs one).

Why the statusline, not the thinking spinner

Checked early (before implementation started), because the whole claude_code.wait placement concept originally assumed the spinner text ("Baking…", "Simmering…", "Finagling…", etc.) could be swapped per-request. It can't:

  • No hook fires during the thinking/spinner phase — Claude Code's hook events cover prompts, tool calls, session lifecycle, and message display, but nothing while a turn is in progress.
  • No plugin or MCP surface can inject into the spinner at runtime.
  • The spinner's text is only customisable statically, once, via settings (spinnerVerbs/spinnerTipsOverride-style keys) — fixed at session start, not something a backend can serve dynamically per request. That rules it out for an ad network, which needs a fresh creative per impression.

The actual integration point is the statusline — a separate, genuinely-scriptable line rendered below the prompt input (not inside the spinner). It runs a developer-provided command on refresh (event-driven, plus optional timer refresh), with full freedom over its output — adfrolic statusline calls GET /v1/ads/serve (through a local cache, so most refreshes cost no network round trip — see below) and renders the returned creative. Same "shown at a natural pause" intent as claude_code.wait, different exact spot on screen.

Device-authorization sign-in

A CLI has no browser-redirect OAuth surface and no secure place to hold a Firebase client session, so it uses the same device-authorization flow as the VS Code extension (extensions/vscode/src/deviceAuthFlow.ts) — modelled on gh auth login: adfrolic-claude-code auth gets a short user code, opens the web app's confirmation page, and polls until the developer approves it there. See apps/api/src/routes/deviceAuth.ts for the server side and its phishing-risk mitigation notes.

Caching and the impression lifecycle

adfrolic-claude-code statusline may be invoked far more often than once per ad — it caches the current creative (~/.adfrolic/statusline-cache.json) for five minutes so most invocations render from disk with no network call at all. On the invocation where the cached ad's minimum display duration has elapsed, it fires the qualify call and marks the cache so it's never sent twice. This trades a small chance of losing one qualification (if the process is killed mid-request) for never blocking/slowing down the statusline on every single refresh — see src/statuslineCommand.ts.

Known limitation: no click-through

Unlike the VS Code extension's status bar/sidebar, the terminal statusline here is display-only — no keyboard/mouse target within Claude Code's own UI to trigger a click. (OSC 8 terminal hyperlinks were considered and rejected: support is inconsistent enough across terminals that a garbled escape sequence in the statusline was judged a worse failure mode than no click-through at all.) Revisit if Claude Code adds an interactive statusline segment.

Constraints (apply regardless of mechanism chosen)

  • No source code, prompts, AI responses, or terminal contents are ever sent to the backend — see docs/privacy.md.
  • All advertising/accounting logic (ad selection, budgeting, fraud, billing) stays server-side; this client only requests, displays, and reports on adverts via @adfrolic/ad-client, the same shared SDK used by the VS Code extension.
  • A failure anywhere in this integration must never disrupt a Claude Code session (spec section 77) — always fail silently.