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

@sufleur/cli

v0.4.0

Published

CLI for sufleur — type-safe codegen for versioned LLM prompts.

Readme

@sufleur/cli

The CLI for Sufleur — the registry where you author, version, and publish LLM prompts. This is the consumer side: it installs prompts from your Sufleur workspace into your project the way npm installs packages — declared in sufleur.yaml, locked to sufleur-lock.yaml, generated into one TypeScript file with full types and runtime helpers.

Create a workspace and start authoring prompts at https://sufleur.com.

What you call from your code

import { getPrompt } from './generated/prompts';

const review = getPrompt('@my-workspace/code-review');

const { prompt } = review.render('en', {
  diff: '...',
  language: 'go',
});
// → ready-to-send prompt string

const result = review.parseOutput(llmResponseText);
if (result.success) {
  result.data; // typed by the prompt's output schema (Zod-validated)
} else {
  result.error;
}

'@my-workspace/code-review' is checked at compile time: typos fail to type-check, the entrypoint name 'en' is narrowed against the prompt's available entrypoints, and the input shape is the JSON Schema declared on that entrypoint. The version that resolves at codegen time is pinned in sufleur-lock.yaml.

Install

npm i -g @sufleur/cli
sufleur --help

Or run on demand:

npx -p @sufleur/cli sufleur --help

The wrapper downloads the matching prebuilt binary on npm install and exposes it as sufleur. There's no JS in the hot path — the sufleur command is the native binary.

Quick start

mkdir my-app && cd my-app
sufleur init                                  # creates sufleur.yaml interactively
sufleur add @my-workspace/code-review ^1.0.0  # add + fetch + lock
sufleur generate                              # writes ./generated/prompts.ts

The generated file imports two runtime peers — install them in your project:

npm i mustache
npm i -D @types/mustache
# only if any prompt has an output schema:
npm i zod

What sufleur generate emits

A single .ts file containing every prompt inlined (no runtime fetches). The header documents what's exported; the public API is getPrompt(name), which returns:

  • render(entrypoint, input){ prompt: string } — Mustache renders the entrypoint template against input. The input type is narrowed by entrypoint name; entrypoints with no input schema take no second argument.
  • metadata{ version, ...your custom workspace metadata, outputSchema? }. The pinned version comes from the lockfile; the rest comes from whatever metadata your registry assigned to that prompt version.
  • parseOutput(raw) (only present if the prompt has an output schema) — strips ``` fences, JSON-parses, and validates with a Zod schema generated from the prompt's JSON Schema. Returns { success: true, data } or { success: false, error }.

Plus exported types per entrypoint:

export type CodeReview_EnInput = { diff: string; language: string };

Optional schema properties are emitted with ?:, and oneOf schemas become TypeScript union types.

Prompts published with DRAFT status emit a runtime console.warn when their getPrompt is called.

sufleur.yaml

The manifest. Looks like:

api_keys:
  my-workspace: ${MY_WORKSPACE_API_KEY}

prompts:
  '@my-workspace/greeting': '*'
  '@my-workspace/code-review': '^2.0.0'
  # alias: keep two pinned versions side-by-side under different names
  '@my-workspace/code-review-strict': '@my-workspace/code-review@~1.4.0'

output:
  language: typescript
  file: ./generated/prompts.ts

Constraints are npm-style semver ranges (^, ~, >=, exact, *). The resolution is recorded in sufleur-lock.yaml. Commit both filessufleur.yaml is the source of truth, sufleur-lock.yaml is the receipt.

CI usage

sufleur install --frozen   # fail if lockfile is stale
sufleur generate

--frozen is the npm-ci equivalent: refuses to update the lockfile, hard-errors if the manifest and lockfile disagree.

Commands

| Command | Description | | ------- | ----------- | | sufleur init | Interactive scaffolding for sufleur.yaml. | | sufleur add @ws/name [range] | Add a prompt, fetch it, update the lockfile. --alias <name> keeps multiple versions; --force overwrites an existing entry. | | sufleur remove @ws/name | Remove a prompt from the manifest and prune its cache (kept if another alias still resolves to the same version). | | sufleur install | Resolve the manifest, fetch what's missing, refresh the lockfile. --frozen for CI. | | sufleur update [@ws/name] | Re-resolve constraints — one prompt or all. | | sufleur generate | Regenerate the output file from the lockfile + cache. |

-v / --verbose enables HTTP request/response logs on any command. Variables in .env are loaded automatically; per-workspace API keys can be referenced as ${ENV_VAR_NAME} in sufleur.yaml.

Authoring prompts from the CLI

The commands above install published prompts into your project. The CLI also exposes the full authoring side — designed so a coding agent (Claude Code, Cursor, etc.) can create, version, and edit prompts in your Sufleur workspace on your behalf.

Hand it to your agent

sufleur skill prints a markdown skill description — when to use the CLI, FQ-name format, the full command surface, JSON flags. Pipe it wherever your agent loads skills from:

# Claude Code (each skill is a directory with a SKILL.md inside)
mkdir -p ~/.claude/skills/sufleur && sufleur skill > ~/.claude/skills/sufleur/SKILL.md

# Cursor
sufleur skill > .cursor/rules/sufleur.md

The skill ships inside the binary, so it always matches the sufleur version on your PATH.

Log in

sufleur login    # device-code flow — opens a browser, polls until approved
sufleur me       # show the authenticated user
sufleur logout   # revoke the stored credential

Credentials land in $XDG_CONFIG_HOME/sufleur/credentials.yaml (or ~/.config/sufleur/credentials.yaml). This user credential is separate from the workspace API keys referenced in sufleur.yaml — those stay machine-to-machine, this one identifies you as the author.

Authoring commands

All accept --json. Prompts are addressed as @workspace/name, versions as @workspace/name@version (use the literal label draft while the version is unpublished).

| Command | What it does | | ------- | ------------ | | workspace list | List the workspaces you belong to, with your role | | prompt create @ws/name --description "..." | Create a new prompt in a workspace | | prompt list @ws [--search ... --limit ... --offset ...] | List prompts in a workspace | | prompt get @ws/name | Show one prompt's details | | prompt update @ws/name --description "..." | Update the description | | version draft @ws/name | Fork the latest published version into a new draft | | version list @ws/name [--status DRAFT\|PUBLISHED] | List versions of a prompt | | version get @ws/name@version | Show one version's details | | version delete @ws/name@draft | Delete a draft (published versions are immutable) | | version set-metadata @ws/name@draft --string K=V (or --from-file …) | Patch or sync metadata | | version delete-metadata @ws/name@draft --key K | Remove a metadata key | | version set-output-schema @ws/name@draft --file schema.json | Replace the version's output schema | | version set-readme @ws/name@draft [--content STR \| --file PATH] | Replace the version's README | | version get-readme @ws/name@version | Print the version's README to stdout (raw markdown) | | version dump @ws/name@version --to ./dir | Export files, output schema, README, and metadata to disk | | file list @ws/name@version | List files in a version | | file create @ws/name@draft --file path.mustache [--entrypoint] | Add a new file | | file update @ws/name@draft --name X [--file ...] [--rename Y] | Replace content and/or rename | | file delete @ws/name@draft --name X | Delete a file | | file set-entrypoint @ws/name@draft --name X [--clear] | Mark (or unmark) a file as an entrypoint |

Render before publishing

sufleur prompt render <dir> --entrypoint <name> [--vars '{...}' | --vars-file path.json] runs the same Mustache pipeline as the generated runtime — useful for previewing a draft locally before publishing, or for quick experimentation against a version dump directory. No auth required.

Supported platforms

| OS | Architectures | | ------- | ------------------------------ | | macOS | x64, arm64 | | Linux | x64, arm64 | | Windows | x64, arm64 (Windows 10 1803+) |

Alpine / musl libc is currently unsupported (no musllinux binary). Override the binary download URL with SUFLEUR_BINARY_MIRROR. Set SUFLEUR_SKIP_POSTINSTALL=1 to defer the download (e.g. when building an image you'll rehydrate later with npm rebuild @sufleur/cli).

Links

License

MIT.