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

metalmind

v0.5.3

Published

Unified CLI for Obsidian vault, code graph (graphify), and cross-repo intelligence. Mistborn-themed with a neutral alias set.

Readme

metalmind CLI

The Node/TypeScript CLI that drives metalmind init, pulse, tap copper, burn bronze, etc. Published as the metalmind npm package (imminent).

For users: see the repo root README.md. This file is for hacking on the CLI.

Layout

cli/
├── src/
│   ├── cli.ts                 Commander entry + command wiring
│   ├── commands/              Verb implementations (init, tap, burn, store, …)
│   ├── install/               Wizard + per-concern installers
│   │   ├── wizard.ts          Orchestration
│   │   ├── prereqs.ts         Platform + tool detection
│   │   ├── vault.ts           Obsidian vault scaffold
│   │   ├── serena.ts          Serena install via uv tool
│   │   ├── graphify.ts        graphify install via uv tool
│   │   ├── vault-rag.ts       metalmind-vault-rag install via uv tool
│   │   ├── stack.ts           Docker compose up + model pull
│   │   ├── watcher.ts         Platform dispatcher (launchd | systemd)
│   │   ├── launchd.ts         macOS watcher install
│   │   ├── systemd.ts         Linux watcher install
│   │   ├── mcp.ts             ~/.claude.json edits
│   │   ├── settings.ts        ~/.claude/settings.json env edits
│   │   ├── aliases.ts         Shell rc source-line injection
│   │   ├── templates.ts       CLAUDE.md stamps + rules copy
│   │   ├── output-style.ts    Output-style migration
│   │   └── teardown.ts        Reversible uninstall
│   ├── backends/              MCP client + recall/graph/vault backends
│   ├── forge/                 Cross-repo graph groups
│   └── config.ts              Zod schema for ~/.metalmind/config.json
├── templates/                 Bundled at publish time via `files`
│   ├── metalmind-stack/       compose.yml for Qdrant + Ollama
│   ├── vault-rag-pkg/         Populated by scripts/sync-vault-rag-pkg.mjs
│   │                          from ../../packages/vault-rag/ (gitignored)
│   ├── vault/                 CLAUDE.md.template for the Obsidian vault
│   ├── claude/                Global CLAUDE.md + rules + agents + commands
│   ├── launchd/               macOS plist template
│   ├── systemd/               Linux .service template
│   └── zsh/                   aliases.sh
├── scripts/
│   └── sync-vault-rag-pkg.mjs Copies packages/vault-rag/ into templates/
├── tsup.config.ts             Bundler config (ESM, node20 target)
└── package.json

1 file = 1 instance: each installer lives in its own file with a single install<Thing>() + uninstall<Thing>() pair. Wizard composes them; teardown reverses.

Dev loop

pnpm install
pnpm dev               # tsx watch — runs src/cli.ts directly
pnpm typecheck         # tsc --noEmit
pnpm test              # vitest run (157 tests, ~800ms)
pnpm test:watch
pnpm build             # tsup → dist/cli.js (ESM, shebang, node20)
pnpm test:python       # pytest against ../packages/vault-rag/ (requires uv)
pnpm test:smoke        # end-to-end integration (builds, links, runs cli/test/integration/smoke.sh)

After a build, the installed shim picks up new code immediately (pnpm / npm global links resolve through the local dist/cli.js).

Testing conventions

  • Vitest with vi.hoisted() for runCommand mocks — lets tests simulate uv / docker / launchctl / systemctl without touching the real system.
  • Temp dirs for all filesystem side-effects (mkdtemp in beforeEach, rm -rf in afterEach).
  • Path overrides on every installer — every function that writes to ~/.claude.json / ~/Library/LaunchAgents / ~/.config/systemd accepts an override so tests can redirect to a temp path.
  • No real network: setupStack takes a fetchFn for polling; tests pass a fake that returns 200 immediately.

Each installer has a mirror *.test.ts next to it — add tests alongside the code you touch.

Test tiers

| Tier | Runner | Covers | Runtime | |---|---|---|---| | Unit | pnpm test | All TS modules — mocked runCommand, fetch, fs | ~800ms | | Python | pnpm test:python | packages/vault-rag: imports, search helpers, HTTP endpoint | ~4s | | Smoke | pnpm test:smoke | Scripted end-to-end: init --yes → stamp → save → uninstall | ~10s |

Smoke test uses a temp $HOME, skips Docker/Serena/graphify, and asserts every managed file ends up in the right place. It's the "would a fresh-machine install work?" question answered in 20 assertions.

Adding a new install step

  1. Create src/install/<thing>.ts with install<Thing>(): Promise<...> + uninstall<Thing>(): Promise<...>. Return a result object so callers can log what happened.
  2. Accept path overrides as options (<thingPath>?: string) for testability.
  3. Wire into src/install/wizard.ts — a log.step(...) + success line.
  4. Wire the inverse into src/install/teardown.ts.
  5. Add tests under src/install/<thing>.test.ts following the existing mock pattern.

Bundling the Python package

metalmind-vault-rag is a standalone Python package living at the monorepo root: packages/vault-rag/. At build/prepack time, cli/scripts/sync-vault-rag-pkg.mjs copies it into cli/templates/vault-rag-pkg/ (gitignored) so the npm tarball ships it alongside dist/cli.js. On a user's machine, the wizard runs uv tool install --from <bundled-path> metalmind-vault-rag. Four binaries land on PATH: metalmind-vault-rag-{server,watcher,indexer,doctor}.

To iterate on the Python side:

cd packages/vault-rag
uv tool install --reinstall --force --from . metalmind-vault-rag
# reload watcher if running:
launchctl unload ~/Library/LaunchAgents/com.metalmind.vault-indexer.plist   # macOS
launchctl load ~/Library/LaunchAgents/com.metalmind.vault-indexer.plist
# or on Linux:
systemctl --user restart metalmind-vault-indexer.service

Publishing

pnpm build
pnpm test
npm pack --dry-run     # sanity-check tarball contents + size
npm version <patch|minor|major>
npm publish --access public
git push --follow-tags

Before the first publish: make sure npm whoami returns the intended account.

Philosophy

  • No hidden state: every side-effect has a corresponding teardown. Users who run metalmind uninstall should be able to verify with their own eyes that we left nothing behind (except their notes, which we never touched).
  • Idempotent: re-running metalmind init is safe and should converge to the same state.
  • Skill-first over MCP: when a CLI call works, prefer it over registering an MCP tool — MCP schemas get injected into every session and cost tokens.
  • Thin vertical slices: prefer ~100-line commits that each leave the system green. See .claude/rules/principles.md.