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

@lovinka/vitrinka

v1.12.0

Published

vitrinka CLI + MCP server — capture and publish artifact sets, drive the annotation-board work queue from any MCP-aware AI.

Readme

@lovinka/vitrinka

The vitrinka client — one package, two bins:

  • vitrinka — the CLI: capture screenshots into .screenshots/, build a self-contained gallery, publish artifact sets, scaffold interactive artifacts, and arm the annotation-board watch monitor.
  • vitrinka-mcp — the MCP server: lets any MCP-aware AI browse artifact sets and drive the annotation-board work queue (pick up an annotation → fix the app → attach the after-shot → reply) without touching the web UI.

Both share the same token / operator / base-url / actor-encoding conventions, single-sourced in src/lib/ (previously duplicated between the CLI and the MCP server — the latin-1 X-Board-Actor encoding bug once had to be fixed in three places). The MCP server is a thin, stateless stdio process: every tool call becomes one HTTPS request against the deployed vitrinka Go server.

Install

# both bins on PATH
npm i -g @lovinka/vitrinka

# one-command machine setup — status-first onboarding: prints a ✓/✗ table, silently
# installs the Claude skills bundle (vitrinka + listen, screenshot, artifact,
# brainstorming) + the /vitrinka:listen command stub + PATH shim + shell completion,
# then asks [Y/n] only for the missing config-touchers: MCP registration, write
# token (silent input), operator persona, Claude Code UI wiring.
# (npm install itself has NO side effects; skills land only via this command or
# `vitrinka install-skills`.)
vitrinka install

# later: update the CLI, see what's new, refresh everything a previous install put
# here (npm i -g @lovinka/vitrinka@latest when behind — or git pull in a checkout —
# then re-copies the skills bundle + /vitrinka:listen stub and refreshes the
# Claude UI wiring where it was already consented to; never asks new questions)
vitrinka update

# health check / repair / clean removal
vitrinka doctor          # server, token, operator, skills, shim, MCP, UI wiring
vitrinka doctor --fix    # repairs the repairable (skills, shim, MCP, UI wiring)
vitrinka uninstall       # removes everything install put here (--purge: token too)

Registering the MCP by hand (install does this for you when the claude CLI is present): claude mcp add --scope user vitrinka -- npx -y --package=@lovinka/vitrinka vitrinka-mcp

vitrinka install also offers (interactive [Y/n], or --claude/--no-claude) to wire the Claude Code UI — re-runnable standalone as vitrinka install-claude:

  • Footer badge — a footerLinksRegexes entry in ~/.claude/settings.json renders a clickable 🧷 board badge in Claude Code's footer whenever a /boards/ URL appears in the conversation (clickable in every terminal; needs Claude Code ≥ 2.1.176).
  • Statusline segment~/.claude/vitrinka-statusline.sh wraps your existing statusline command (recorded on its VITRINKA_ORIG= line) and appends a 🧷 <board-url> segment when the session's .screenshots/.vitrinka descriptor exists (plain-text URL — Claude Code strips OSC 8 from statusline output, and terminals cmd+click-linkify visible URLs themselves); with no statusline configured it renders a minimal dir │ branch │ 🧷 board │ model line itself. Needs jq; degrades to pass-through without it, and never double-renders a board segment your own statusline already prints.
  • Session-start board link~/.claude/hooks/vitrinka-board-link.sh, a SessionStart hook that prints the repo's live board URL into session context at start, so the clickable footer badge exists from message one (the statusline URL isn't clickable in every terminal). Silent no-op in repos without a .screenshots/.vitrinka descriptor; needs jq.
  • App badge (only when Vitrinka.app is installed) — a second footerLinksRegexes entry that renders ⧉ app next to the board badge; its vitrinka:// deep link opens the same board in the desktop app (which registers only the custom scheme — https stays in the browser).

Desktop-app flag~/.config/vitrinka/desktop-app is the ONE canonical "is Vitrinka.app installed here" answer (content = the app path). apps/desktop's make install stamps it; install-claude and doctor re-sync it to reality (and add/remove the app badge accordingly). Skills and tools should test this flag file instead of probing /Applications themselves — vitrinka open uses it to open boards in the app (pass --browser to force the browser).

All steps are idempotent — re-runs detect the wiring and no-op. To remove: delete ~/.claude/vitrinka-statusline.sh and ~/.claude/hooks/vitrinka-board-link.sh, restore statusLine.command in ~/.claude/settings.json to the VITRINKA_ORIG value (or drop the key), and remove the footerLinksRegexes entry whose pattern contains /boards/ plus the hooks.SessionStart entry running vitrinka-board-link.

For Claude Desktop or any other MCP client, add the equivalent entry by hand:

{
  "mcpServers": {
    "vitrinka": {
      "command": "npx",
      "args": ["-y", "--package=@lovinka/vitrinka", "vitrinka-mcp"],
      "env": {
        "VITRINKA_BASE_URL": "https://vitrinka.in",
        "VITRINKA_TOKEN": "…"
      }
    }
  }
}

vitrinka is reachable over the WireGuard mesh — bring the VPN up (or point VITRINKA_BASE_URL at any reachable host) before use.

Configuration (env)

| Var | Default | Purpose | |---|---|---| | VITRINKA_URL / VITRINKA_BASE_URL | https://vitrinka.in | vitrinka server base URL. VITRINKA_URL wins, then VITRINKA_BASE_URL; the CLI's --base flag overrides both. | | VITRINKA_TOKEN | — | Bearer write token. Falls back to ~/.config/vitrinka/token. Required only by the mutating tools; read tools work unauthenticated. | | VITRINKA_OPERATOR | — | Operator persona name. Falls back to ~/.config/vitrinka/operator (written by vitrinka install onboarding). When set, write calls carry X-Board-Actor: <name> so the board credits the operator's machine — agent-authored content (reply, attach_after) keeps its explicit claude attribution. |

MCP tools

Artifacts library

  • list_projects — all projects (name, branch/set counts, last update).
  • list_sets — a project's (or one branch's) artifact sets, newest first.
  • get_set — one set's metadata + full file list + share URL.
  • rename_set — set/clear a set's custom URL-addressable name. (write)
  • update_set — edit a set's custom name and/or human title. (write)

Annotation-board work queue

  • list_boards — the annotation boards (canvases over screenshot sets).
  • ask_board — post a first-class multiple-choice question on a board. (write)
  • scrape_board — read a whole board as one structured testing digest.
  • wait_for_workblock (long-poll) until annotation work exists.
  • list_work — the agent queue (FIFO); filter by status / board / project+branch.
  • get_annotation — one annotation's full brief.
  • get_capsule — one annotation's compact markdown work brief.
  • set_status — move an annotation through its lifecycle. (write)
  • reply — post a reply into an annotation's thread as claude. (write)
  • attach_after — attach the "after" proof shot to an annotation. (write)
  • highlight — draw an ink rectangle on an annotation's card (live via SSE). (write)

Agent loop: list_workset_status working → fix the app → push a new set (vitrinka snap/push) → attach_afterreplyset_status in_review. Only the user resolves (accepts in the board UI) — never set status resolved yourself.

Unattended worker

When no listening Claude session is open, the fallback worker long-polls the queue and spawns one claude -p per annotation:

vitrinka-mcp work --repo ~/Documents/Work/FixIt [--board <slug>] [--grace 8]

Local development

cd pkg
npm install
npm run build        # tsc → dist/ (rewrites .ts import specifiers to .js on emit)
npm test             # node --test tests/  (spawns the server/worker over real stdio + unit-tests src/lib)
npm run typecheck
node dist/cli.js help        # CLI
node dist/bin-mcp.js         # MCP server over stdio (Ctrl-C to stop)

The source (src/*.ts, src/lib/*.ts) is dependency-free, erasable TypeScript (node builtins + global fetch only) and runs directly under Node 24 via type stripping — that is how a repo checkout registers the MCP server:

claude mcp add --scope user vitrinka -- node <repo>/mcp/server.ts   # shim → pkg/src/mcp.ts

The published dist/ is plain ESM and runs on Node ≥ 20.

Release (Lovinka org)

npm login                     # as the lovinka npm org
cd pkg
npm publish --access public   # prepublishOnly runs the build

files is a whitelist (dist + README.md), so npm pack --dry-run should list only the compiled output — verify before publishing.

Deprecating the old MCP-only package

@lovinka/vitrinka-mcp (the previous MCP-only package) is superseded by this unified package. After @lovinka/vitrinka is published, deprecate it:

npm deprecate @lovinka/vitrinka-mcp "moved to @lovinka/vitrinka (vitrinka-mcp bin)"

Existing npx -y @lovinka/vitrinka-mcp registrations keep resolving (deprecation only prints a warning); migrate them to npx -y --package=@lovinka/vitrinka vitrinka-mcp at leisure.

License

MIT