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

@wildfire/rec-cli

v0.1.0

Published

CLI for managing REC+ sites (templates over FTPS, content over the API), built for coding agents

Readme

rec-cli

A small CLI for working on a REC+ site from the terminal: templates over FTPS, pages and other content over the REST API. It's built so coding agents (Claude Code, Codex and others) can drive it from its --help output, and it's just as usable by hand.

How it works

You edit template files locally, but everything else happens on the REC+ site itself: it renders the pages and compiles the SCSS, so there's no local server or build step. rec-cli push uploads your changes over FTPS and they take effect as soon as they're on the site. Pushing to the site's active template changes what visitors see straight away, which is why live sites are normally changed through a fork (see below). Pages and other content live in the site's database and are changed through its API with rec-cli api.

Quick start

Needs Node.js 22.12 or newer.

npm install -g @wildfire/rec-cli

rec-cli upgrade updates it later.

Then make a folder for the site and set it up:

mkdir my-site && cd my-site
rec-cli init

rec-cli init asks for the site URL, an API account (create one in the site's admin under API Accounts, with the content and templates scopes) and the two FTP accounts (listed under FTP Access). It writes them to .env, makes the folder a git repository if it isn't one, adds .env, .rec-cli/, *-base/ and .playwright-cli/ to .gitignore, checks the connections, writes an AGENTS.md with instructions for coding agents (plus a CLAUDE.md that includes it), and offers to download the site's templates. Re-run it any time; Enter keeps the current values.

A typical change, by hand

On a live site, work in a fork of the active template so visitors don't see changes until you publish them:

rec-cli templates                          # which template is active? (say it's "mytheme")
rec-cli fork mytheme-header                # new template extending it; prints its preview URL
rec-cli pull                               # brings down the new (nearly empty) mytheme-header folder
mkdir -p mytheme-header/html/sections
cp mytheme/html/sections/header.html.twig mytheme-header/html/sections/   # override just this file
# ...edit mytheme-header/html/sections/header.html.twig...
rec-cli push mytheme-header --dry-run      # check what will be uploaded
rec-cli push mytheme-header

If mytheme doesn't have its own copy of the file, it's inherited from further up the chain, so copy it from there instead (e.g. responsive-base/html/sections/header.html.twig); rec-cli templates shows what each template extends.

Open the preview URL from rec-cli fork (or rec-cli templates --json) to see the site with your fork; only that browser session sees it. When it's ready, flatten the fork in the site's admin under Templates: that copies its files into the parent template and makes them live. Run rec-cli bump-cache after CSS or JS changes so browsers fetch the new files.

On a site that isn't live yet, you can skip the fork and edit and push the active template directly.

Working with an agent

Start your agent in the site folder. It reads AGENTS.md (Claude Code reads it through CLAUDE.md), which points it at the site's own docs and the rec-cli commands. Then describe the task, for example:

Read AGENTS.md and the site docs it links to. Then update the header in our template to match the attached mockup, at desktop (1400px) and mobile (390px) widths. Pull first, push your changes as you go, check each change on the site with playwright-cli, and bump the cache when CSS changes are done. This site is live, so fork the active template and work in the fork. Don't commit until I've reviewed it.

Add anything you learn about the site to the "Site notes" section of AGENTS.md, so later sessions start with it.

Commands

rec-cli init                         # set up .env, .gitignore and AGENTS.md for a site
rec-cli pull                         # download every template folder (only new or changed files)
rec-cli push rivendell               # upload a template folder or file (only new or changed files)
rec-cli push rivendell --dry-run     # see what would change first
rec-cli userfiles push userfiles/images/design   # upload design assets (never downloads)
rec-cli templates                    # list template folders, active/locked status
rec-cli bump-cache                   # bump the asset cache buster after css/js changes
rec-cli fork winter-2026             # new template extending the active one (asks first)
rec-cli ftp views ls rivendell/html  # single FTPS commands: ls, get, put, rm, mkdir
rec-cli ftp userfiles put ./hero.jpg images/design/hero.jpg
rec-cli api GET /pages               # any /api/v1 endpoint, prints the JSON response
rec-cli api POST /pages -d @page.json
rec-cli api DELETE /pages/12         # sent as POST ?force_method=DELETE
rec-cli upgrade                      # update rec-cli itself to the latest version

rec-cli <command> --help shows each command's arguments, options and an example. API endpoints are documented on each site at /admin/docs/api.md.

Global options: --json (machine-readable output), --verbose (log requests and transfers to stderr), --yes (skip confirmations; without a terminal, confirmations fail instead of waiting).

Exit codes: 0 success, 1 failed operation or API error, 2 usage or config error.

How pull and push decide what to copy

After every sync, rec-cli records each file's size and modified time in .rec-cli/state.json (gitignored), so the next run can tell which side changed since then:

  • only the side being copied from changed: the file is copied;
  • only the other side changed: it's left alone and listed (push won't overwrite a colleague's change on the site; pull won't overwrite your unpushed edit);
  • both changed: the contents are compared, and if they differ the file is left alone on both sides and listed as a conflict.

Files with no record yet (the first sync, or a new clone) fall back to comparing times: copied when the source is newer, compared by content otherwise. --force copies everything regardless, and --dry-run shows what would happen. After a transfer the local file takes the site's modified time. Site times are never changed, only moved on by real uploads, as REC+'s compiled template cache only rebuilds when a file gets newer.

It's still not version control: it only tracks what changed since the last sync, and a change that keeps a file the same size within the same second as a sync can be missed. Keep the site folder in git and commit before pulling, so git diff shows anything a pull brings in.

push --delete removes site files you don't have locally (after confirming). pull never deletes local files. .git, *.md, .env*, .playwright-cli, node_modules and similar are never transferred. Base templates (*-base) are pulled for reference but can't be pushed.

Config

Each site gets its own folder with a .env (see .env.example). rec-cli finds the nearest .env walking up from the current folder, so it works from any subfolder, and real environment variables override it.

Development

To work on rec-cli from source:

git clone https://github.com/WildfireInternet/rec-cli.git
cd rec-cli
npm install
npm link    # puts your local `rec-cli` on your PATH
npm test

The offline tests run bin/rec-cli against a fake API server. To also run the live tests, add a .env.test (gitignored, same keys as .env.example) for a dev site you can safely write to: they only read from the API, and their FTP writes stay in throwaway rec-cli-test-* folders that are removed afterwards. Node doesn't use the OS certificate store by default, so for a local dev site with a locally trusted certificate run rec-cli with NODE_OPTIONS=--use-system-ca (the live tests set this for you).

Commands live in lib/commands/, one file each, exporting { name, description, args, options, example, help, destructive, run(ctx) }; add new ones to lib/commands/index.js. The starter AGENTS.md that rec-cli init writes is templates/AGENTS.md.

License

MIT, see LICENSE.