Skip to content

Contributing

This page is for people building imprnt itself. imprnt is open source under the MIT license.

repo one monorepo
runs on Node
built with Bun
license MIT

The monorepo

Everything lives in one git repository: the core and every plugin, wired together with bun workspaces so one bun install sets up the whole thing and you develop it all side by side. At publish time the one repo splits into two package families.

imprnt packages/imprnt/
the core CLI one package

ingest, recall, check, plus init, snapshot, hot, context, and plugin. One install gives two commands, imprnt for machinery and imp for humans, served by a single program.

imprnt-plugin-* packages/plugin-*/
the gallery one package each

every plugin ships on its own. The naming convention matches the shape ESLint uses, so anyone can publish a plugin without joining an npm org. The core never imports or depends on one (the one place it names them is a short list of hints so imprnt plugin list can suggest official plugins).

Terminal window
bun install
bun run build # compile each package
bun run test # test all packages
bun run check # typecheck + test + build

Ship Node, build with Bun

What a user installs runs on Node, the runtime everyone already has, so npm i -g imprnt works without making anyone install Bun first. A code plugin compiles the same way, so running plugin code needs only Node too.

Generic ships, personal stays private

the one rule

Your private plugins never ship. They live in plugins/_personal/, gitignored and never published, and imprnt plugin list skips them so your private cast stays off the public listing.

ships in the public gallery
  • the generic plugin gallery
  • Scribe, the default character you copy
  • the universal anti-slop core
stays local, never published
  • your edited copy of a gallery plugin
  • your own character and house style
  • anything in plugins/_personal/

To personalize, copy a gallery plugin into _personal/, edit it, and wire the local file directly.

Releasing

imprnt publishes to npm on two dist-tags: named pointers that tell npm which version of the one imprnt package to install.

Channel Install What it is
latest npm i -g imprnt Stable. What a normal user gets. Promoted deliberately.
edge npm i -g imprnt@edge Every push to master. May be rough.

Every package versions independently. Turborepo’s --affected works out which packages a change actually touched, so a package whose files did not change is never republished. A core installed from edge pulls its plugins from edge too, so the newest core gets exercised against the newest plugins automatically.

All publishing runs through one GitHub Actions workflow with two paths:

Three safeguards sit on that workflow:

no stored secrets Trusted publishing

The workflow signs in to npm with OIDC: GitHub proves which repository and workflow is publishing, run by run, so there is no long-lived token to steal.

signed receipt Provenance attestation

Every published package carries a signed public record of the exact commit and workflow that built it.

human gate Required approval

A stable release pauses at a GitHub Environment until a required reviewer clicks approve. Nothing automated reaches latest on its own.

Trusted publishing is configured once per package on npmjs.com.

To cut a stable release, use the imprnt-release skill (it fires the workflow and reports), or run it by hand:

Terminal window
# fire the release, then approve the npm-production gate
gh workflow run publish.yml -f mode=release
# plan only, publishes nothing
gh workflow run publish.yml -f mode=release -f dry_run=true

npm only allows a full unpublish within 72 hours, so for a normal release you cannot count on it. To undo a bad latest, point the tag back to the last good version and deprecate the bad one:

Terminal window
npm dist-tag add imprnt@<last-good> latest
npm deprecate imprnt@<bad> "broken release, use <last-good>"