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

@postlyra/cli

v0.4.0

Published

Mine content ideas from your own git history — your commits never leave your machine

Readme

postlyra

Mine content ideas out of your own git history, on your own machine. Your commits never leave it — only the finished ideas do.

$ postlyra mine
myrepo: 14 commit(s), 6 already mined, 8 new
website: 3 commit(s), 0 already mined, 3 new

Pushed 6 idea(s) — 6 new, 0 updated:
  - the queue timeout bug that cost a night of sleep
  - why I killed the Sunday cron in favor of a Friday button
  - a before/after on the onboarding flow's time-to-first-post
  ...

What it does

postlyra mine walks the git repos you point it at, pulls the commit subjects from the last N days, and asks an AI (yours — see below) to turn that work log into a short list of finished posts: each idea is one insight, written ready to publish, with a short working title, which pillar and format it fits, and — for reels — exactly what to screen-record. The finished ideas get pushed to your Postlyra account, where you pick the platform and adjust length; the raw commits never leave your machine.

Point it at a notes vault too (vault in the config, or --vault PATH) and the notes you capture as you work are mined the same way: everything in <vault>/0-inbox/ touched inside the window, plus every bullet in <vault>/0-inbox/content-inbox.md, the file you dump one-liners into. Commits tell it what you built; notes tell it what you were thinking.

The privacy pitch

Postlyra can't read your local git clones, and you shouldn't have to hand a SaaS access to your repos just so it can read commit subjects. This CLI flips that: it runs entirely on your machine.

  • Your commits are read locally by git log, right here on your disk.
  • They're sent only to the AI you already run and pay for — the claude CLI if it's on your PATH, or the Anthropic API directly if you set ANTHROPIC_API_KEY. Either way, that's a call you control, to a provider you already trust with your code.
  • Only the finished ideas reach Postlyra — a short working title, the finished post text, a pillar, a format, maybe a recording note. No commit messages, no diffs, no file contents, no repo names beyond the short label you configured (e.g. myrepo, not the machine path it lives at).

If neither claude nor ANTHROPIC_API_KEY is available, the tool refuses to run rather than silently doing something else with your commit text.

Install

npm install -g @postlyra/cli
postlyra --help

Or run it without installing anything globally:

npx @postlyra/cli --help

Zero runtime dependencies — nothing else to install. Requires Node.js 20 or newer.

Setup

postlyra init     # API URL, folders to scan, optional vault, mining window
postlyra login    # opens the browser to approve -> stores a token, picks a brand

login works like gh auth login: it opens Postlyra in your browser, where you are already signed in (two-factor and passkeys included), you approve once, and the CLI receives an API token on a local callback. No password is ever typed into the terminal, and the token shows up on Profile → API tokens named after this machine — revoke it there any time.

On a machine with no browser to open (a container, an SSH session), run postlyra login --with-password for the email/password/two-factor prompts instead.

init and login write to ~/.config/postlyra/config.json, chmod 600 because it holds your API token.

One login token serves every brand (workspace) on your account. login pins this machine to one brand — automatically when the account has only one, by asking when it has several. Switch any time with postlyra brands use "Channel One", or override a single run with --brand "Channel One".

Brands are picked by name — case and punctuation don't matter, so channel-one and channelone find "Channel One" too. Every brand also has an id (shown by postlyra brands, and on Settings → Brand in Studio); it's only needed when two brands on the account share a name, which the CLI refuses to resolve rather than guess at.

Usage

postlyra login                 Sign in through the browser, store an API token, and pick a brand
postlyra init                  Interactive setup (API URL, folders, vault, mining window)
postlyra brands                List the account's brands (`*` marks the selected one)
postlyra brands use <name>     Pick the brand this machine mines into
postlyra mine [options]        Mine recent commits and vault notes into content ideas
postlyra status                Check auth, brand, folders, and unmined-commit count
postlyra upgrade               Upgrade the CLI to the latest published version
postlyra --version             Print the installed CLI version

Mine options:

| Flag | Meaning | | ------------ | ------------------------------------------------------------------- | | --brand B | Mine into this brand for one run (name or id), overriding the configured brand | | --days N | Override the configured mining window, in days | | --max N | Override the configured maximum ideas for this run | | --vault P | Mine this vault path for this run, ignoring the configured one | | --no-vault | Skip the vault entirely — commits only | | --dry-run | Collect + filter only — print the work log, skip the AI call and the push | | --json | Machine-readable output instead of the friendly terminal summary |

Environment variables:

| Variable | Meaning | | -------------------- | ---------------------------------------------------------------- | | POSTLYRA_API_URL | Overrides the configured API URL for one invocation | | ANTHROPIC_API_KEY | Fallback AI backend when the claude CLI isn't on PATH |

Config reference

~/.config/postlyra/config.json:

{
  "apiUrl": "https://api.postlyra.com",
  "token": "...",
  "brand": "0f8fad5b-d9cb-469f-a165-70867728950e",
  "brandName": "My Brand",
  "folders": ["~/Sites/myproject", "~/code"],
  "exclude": ["*/website"],
  "vault": "~/Sites/second-brain",
  "days": 7,
  "maxIdeas": 8,
  "allBranches": true
}
  • apiUrl — your Postlyra API base URL. Defaults to https://api.postlyra.com, so postlyra login works out of the box with zero config. POSTLYRA_API_URL overrides this per-invocation (also what the test suite uses to point at a stub server instead of the real API).
  • token — the Sanctum API token from postlyra login. Never commit or share this file.
  • brand — the brand (workspace) this machine mines into: the brand's UUID id from postlyra brands, sent as the X-Postlyra-Brand header on every mining call. The id is stored rather than the name you typed, so renaming the brand in Studio doesn't strand this config. Empty is fine on a single-brand account (the server uses your only brand); a multi-brand account must pick one or every mine run refuses to guess. brandName is display-only.
  • folders — paths to scan. Each entry is either a git repo itself (has a .git directory) or a parent folder holding several repos one level down (e.g. ~/Sites containing ~/Sites/myproject, ~/Sites/website, ...). ~ expands to your home directory. A repo found directly under a parent folder is labeled parent/repo (Sites/myproject); a folder that's a repo itself is labeled by its own name.
  • exclude — glob-ish patterns matched against the label, e.g. "*/website" excludes every product's website repo without touching anything else. * matches within one path segment only.
  • vault — optional path to a notes vault (Obsidian or any folder of markdown). Two things are mined from it, both entirely on your machine: every 0-inbox/*.md note modified inside the window, and every bullet in 0-inbox/content-inbox.md. Leave it empty (or pass --no-vault) to mine commits only. A vault with no 0-inbox/ directory is skipped with a warning rather than an error.
  • days — default mining window; --days N overrides it for one run. It bounds vault notes by modification time as well as commits by date.
  • maxIdeas — how many ideas one run asks the AI for, and the hard cap on what gets pushed; --max N overrides it for one run. Defaults to 8. This was a server-side setting until 2026-08-15 (Postlyra's Settings → Content page); it lives here now, with everything else that decides how a run is scoped.
  • allBranches — when true, git log --all is used so commits on branches other than the checked-out one are included too.

How the dedup works

Idea text comes out of an AI, so the same commits through two runs (or two models) can produce different headlines — text can never be the identity for "have I already mined this." Identity lives on the source instead:

  1. Every source item gets a stable ref: <label>@<short-sha> for a commit (e.g. myrepo@a1b2c3d), vault:<filename> for a note, and vault:content-inbox.md@<hash> for one bullet of the inbox file — the inbox is a list you append to forever, so the file can't be the unit. Reformatting a bullet keeps its ref; rewording it mines again, which is what you want: the idea changed.
  2. Before calling the AI, postlyra mine fetches GET /ideas/mining-context, which returns every ref already attached to an existing idea (a 90-day window server-side). Commits whose ref is already known are dropped from the work log before the AI ever sees them — this is the primary dedup, it works across machines, and it saves tokens.
  3. Every idea the AI proposes is asked to cite the refs (in refs) of the commits it drew from; the CLI validates those against what it actually collected and falls back to attributing the whole relevant section if the model's citation is missing or invalid. Those refs get pushed alongside the idea as source_refs.
  4. Server-side, POST /ideas/import also computes an idempotency key from the sorted refs + headline, so re-running mine with an overlapping window (or after a failed push) updates the same idea instead of duplicating it.

Run postlyra mine --dry-run --json any time to see exactly what would be collected, what got filtered as already-mined, and what the AI would see — without spending a single token or pushing anything.