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

@easypush/plush

v0.1.3

Published

SDK, CLI, and MCP server for the Plush push notification API.

Readme

easypush

SDK, CLI, and MCP server for Plush.

npm install @easypush/plush
export PLUSH_API_KEY="push_..."
plush login "$PLUSH_API_KEY"
plush send "Build passed" --title "Deploy done" --thread deploy-main
import { PlushClient } from "@easypush/plush";

const plush = new PlushClient();
await plush.send({
  title: "Deploy done",
  body: "main is live",
  thread_id: "deploy-main",
});

const answer = await plush.askQuestion({
  title: "Ship it?",
  body: "The build passed. Choose the next step.",
  question: { kind: "select", options: ["Ship", "Hold"] },
}, { wait: true });

Select questions include an open-ended Other text reply by default, so Codex can offer quick choices while still letting you type a custom answer. Use allowTextResponse: false only for strict fixed-choice prompts.

JSX dashboards:

import { Badge, Progress, Row, Text, Widget } from "@easypush/plush/jsx";

export default function DeployWidget({ progress = 0.68 }) {
  return (
    <Widget
      id="deploy-main"
      action="update"
      title="Deploy"
      family="systemMedium"
      families={["systemSmall", "systemMedium", "systemLarge"]}
    >
      <Row>
        <Text weight="bold">Production deploy</Text>
        <Badge tone="success">healthy</Badge>
      </Row>
      <Progress value={progress} label="Rollout" />
    </Widget>
  );
}

Scripted widgets:

--file renders TSX locally and sends JSON. --script registers the TSX source plus a compiled JavaScriptCore bundle and a rendered fallback, so the iOS app/widget extension can re-render it locally with scoped localStorage, optional scoped keychain, fetch, Web API primitives, console, and process runtime info.

plush widget --file .plush/deploy-widget.tsx --props-json '{"progress":0.68}'
plush widget --script .plush/codex-dashboard.tsx --id codex-dashboard --group-id codex --props-json '{"progress":0.72}'
plush live --file .plush/deploy-live.tsx --props-json '{"progress":0.42}'
plush ask --title "Need input" --body "Ship this? Pick one, or type another answer." --option Ship --option Hold --wait
plush send "Work is ready" --title "Codex finished" --thread codex --app-name Codex --app-icon-url https://chatgpt.com/favicon.ico

MCP:

[mcp_servers.plush]
command = "npx"
args = ["-y", "@easypush/plush", "mcp"]

Run plush login <api-token> once before using plush mcp. MCP requires the saved login and can list devices, send notifications, ask/wait for questions, update/end Live Activities, create/update/delete widgets from JSON or JSX template files, and register_widget_script from JS/TS/JSX/TSX files. Keep agent-authored templates in .plush/ and git-ignore that directory.

Codex Stop hook:

{
  "type": "command",
  "command": "plush codex-hook",
  "statusMessage": "Sending Plush notification",
  "timeout": 10
}

plush codex-hook reads the Stop-hook JSON from stdin, uses the saved login, sends with app.name = "Codex" plus the Codex icon, uses the Codex thread title as the notification title, keeps the workspace name out of the visible body, deduplicates repeats, and exits quietly if not configured. iOS communication-notification metadata is enabled by default so the Codex avatar can render; set PLUSH_CODEX_COMMUNICATION=0 if you want plain APNs presentation with a normal subtitle instead.

Claude Code Stop hook:

plush install-claude-hook

The installer adds an asynchronous native Stop hook to ~/.claude/settings.json without replacing existing hooks. plush claude-hook reads Claude Code's final assistant message, uses the latest custom session title when available, groups the thread by Claude session, and sends with app.name = "Claude Code" plus the Claude icon. Communication metadata is enabled by default so the Claude avatar can render; set PLUSH_CLAUDE_COMMUNICATION=0 for plain presentation or PLUSH_CLAUDE_ENABLED=0 to disable delivery. Remove it with plush uninstall-claude-hook.

Reply from your phone:

plush patch-codex-app

Phone replies are opt-in. Set both PLUSH_CODEX_REPLY=1 and PLUSH_CODEX_FOLLOWUP_SYNC=1 after validating the local watcher on your Mac. When enabled, the local watcher caches the answer locally, sends it through Codex desktop's background thread-follower IPC, and only consumes the Plush queue item after Codex accepts the follow-up. codex://plush/followup remains available after plush patch-codex-app, but the watcher does not consume replies through that fallback path.

Docs: https://easypush.app/doc.md

Claude Code setup: https://easypush.app/claude.md