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

pi-working-vibe

v0.1.2

Published

Custom Working… message + tool-aware spinner for pi. Vibe files with [default] and [tool:<name>] sections; ships with mafia, hacker, pirate, zen.

Readme

pi-working-vibe

Custom Working… message and tool-aware spinner for pi.

pi-working-vibe demo

Replace pi's default ⠋ Working… with themed flavor text that rotates while the agent is thinking, and automatically switches when the model calls a tool. Ships with four ready-to-use vibes: mafia, hacker, pirate, zen.

⠋ The Don is stirring...                        (default thinking)
⠙ The boys are kicking down doors...            (when calling bash)
⠹ The ledger is being scanned...                (when calling read)
⠸ The contract is being amended...              (when calling edit)

Install

# From npm (recommended)
pi install npm:pi-working-vibe

# From GitHub (always latest main)
pi install git:github.com/Davidcreador/pi-working-vibe

# Project-local (writes to .pi/settings.json instead of global)
pi install -l npm:pi-working-vibe

# Try without installing (single-run, ephemeral)
pi -e npm:pi-working-vibe

That's it. Default vibe (mafia) activates immediately on the next session.

Update later with pi update npm:pi-working-vibe. Remove with pi remove npm:pi-working-vibe.

What it does

  • Rotating message: picks random lines from vibes/<name>.txt every ~3.5s while pi is in a turn.
  • Tool-aware: switches to a tool-specific pool the instant the model invokes bash, read, edit, grep, find, ls, write, web_search, web_fetch, todo, or any custom tool you've authored a section for.
  • Customizable spinner: swap the ⠋⠙⠹⠸ glyphs for one of six presets (dots, line, pulse, braille, arrow) or fully custom frames, with a themeable color.
  • Safe: atomic settings writes, path-traversal guards, mtime-cached file IO, file-size caps, graceful degradation when a vibe pool is missing.

Vibe file format

Vibes are plain text. One message per line. # for comments. Optional [section] headers split lines into named pools:

# mafia.txt
The Don is stirring...
Shadows tally the books...

[tool:bash]
The boys are kicking down doors...
A package is being delivered...

[tool:read]
The ledger is being scanned...

[tool:edit]
The contract is being amended...

Pools fall back to [default] when the active tool doesn't have its own section. A file with no headers becomes one big default pool (backward compatible with any flat vibe file).

Customize your own vibe

Drop a .txt file into ~/.pi/agent/vibes/ and switch to it:

# in pi
/vibe list                  # shows installed vibes (bundled + user)
/vibe vibe:hacker           # switch
/vibe info                  # current settings + line counts
/vibe pools                 # sections in the active vibe
/vibe preview               # show a sample line

User files in ~/.pi/agent/vibes/ override bundled files of the same name, so you can fork mafia.txt without losing the package update.

/vibe command reference

| Form | Effect | |---|---| | /vibe | Toggle master switch | | /vibe info | Show active settings + line counts | | /vibe list | List installed vibes (user + bundled) | | /vibe pools | List sections in the active vibe | | /vibe on | /vibe off | Enable / disable | | /vibe reload | Re-read settings + vibe file from disk | | /vibe preview | Pick a sample line from the active pool | | /vibe vibe:<name> | Switch active vibe | | /vibe indicator:<preset> | default | dots | line | pulse | braille | arrow | custom | | /vibe color:<token> | Theme color for spinner (e.g. accent, primary, dim) | | /vibe rotate:<ms> | Message rotation interval (0 = no rotation) | | /vibe interval:<ms> | Spinner frame interval |

Settings reference

All keys live at the top level of settings.json. Project file <cwd>/.pi/settings.json overrides global ~/.pi/agent/settings.json.

| Key | Type | Default | Effect | |---|---|---|---| | workingVibe | boolean | true | Master switch | | workingVibeName | string | "mafia" | Vibe file name (no .txt) | | workingVibeRotateMs | number | 3500 | Rotation interval; 0 = static. Floor 750ms | | workingIndicator | enum | "default" | Spinner preset | | workingIndicatorColor | string | "accent" | Theme color token | | workingIndicatorFrames | string[] | [] | Custom frames (when workingIndicator: "custom") | | workingIndicatorIntervalMs | number | 90 | Spinner frame interval. Floor 40ms |

Legacy: a string value workingVibe: "<name>" from earlier ad-hoc usage is auto-migrated to {workingVibe: true, workingVibeName: "<name>"} on first load.

Lifecycle (how it hooks into pi)

session_start         → load settings, install indicator, build picker
agent_start           → reset state, set message, start rotation timer
tool_call             → activePool=tool:<name>, refresh message
tool_execution_end    → if no more active tools, back to default
message_start (asst.) → snap to a fresh line as model resumes talking
agent_end             → stop rotation, reset state
session_shutdown      → tear down timer + null out ctx ref

Built on the extension API patterns: setWorkingMessage, setWorkingIndicator, and the tool_call / tool_execution_end event pair.

Authoring tips

  • Pi only renders the working line during the streaming/tool phase. Compaction and retry loaders keep their own built-in styling — this is a pi constraint.
  • Custom frames are rendered verbatim; colors come from pi's theme.
  • Parallel tool calls: the most-recently-started tool wins. When that tool ends, the pool falls back to the next most-recent surviving tool, or to default if there are none.
  • Edit a .txt file while pi is running — mtime caching auto-invalidates on the next read, or run /vibe reload.

Bundled vibes

| File | Theme | |---|---| | mafia.txt | 1930s mob / made-men / consigliere | | hacker.txt | 90s cyberpunk / phreakers / ICE | | pirate.txt | High seas / treasure / plunder | | zen.txt | Calm / contemplative / minimalist |

Each ships with ~110–140 lines across 11 sections (default + 10 tool pools).

Contributing

PRs welcome — especially new vibe themes. Each vibe should cover the standard tool taxonomy (bash, read, edit, write, grep, find, ls, web_search, web_fetch, todo) plus a meaty [default] pool.

License

MIT