Install & Update
The CLI runs on all four runtimes, and it installs on all four. Pick the one you
already have. Whichever you choose you get the same gjsify command, and the
runtime you installed with becomes the one it builds for by default.
| You have | Install with | Updates with |
|---|---|---|
| GJS | one curl line, no Node.js anywhere | gjsify self-update |
| Node.js | npm or pnpm | your package manager |
| Bun | bun add -g | bun add -g again |
| Deno | deno install -g | the same command with -f |
On Windows take Node.js, Bun or Deno: the GJS route needs a gjs binary and
there is none. On macOS all four are possible, but Node, Bun and Deno are the
tested ones.
A global install is not the only shape. You can also add the CLI to a single project as a dev dependency, and for a browser or NativeScript build you may not need the CLI at all.
If you have gjs 1.86 or newer and curl, this is all you need:
curl -fsSL https://github.com/gjsify/gjsify/releases/latest/download/install.mjs \ -o /tmp/g.mjs && gjs -m /tmp/g.mjs && rm /tmp/g.mjsIt puts the CLI and its dependencies under
~/.local/share/gjsify/global/node_modules/ and writes a small sh launcher to
~/.local/bin/gjsify. Add that directory to your PATH if it isn’t there yet:
export PATH="$HOME/.local/bin:$PATH"The download is checksummed before it runs. If you want the details of the bootstrap and how the CLI finds its native prebuilds, see How It Works.
Node.js
Section titled “Node.js”npm install -g @gjsify/clipnpm add -g @gjsify/cliNode.js 20 or newer — the floor @gjsify/node-gi
declares, and the one the CLI and its builds hold to. Pick this route if you
already manage your developer tools through npm.
Yarn has no equivalent, since Yarn 2 dropped yarn global add, so use npm or
pnpm for the global install even when your projects are on Yarn.
bun add -g @gjsify/cliThe launcher lands in $BUN_INSTALL/bin (~/.bun/bin unless you moved it),
which Bun’s own installer normally put on your PATH already.
Bun blocks lifecycle scripts it has not been told to trust, so the install prints
something like “Blocked 2 postinstalls”. The CLI works anyway. Run
bun pm -g untrusted to see which ones, and bun pm trust if you want them to
run.
deno install -g -A -n gjsify npm:@gjsify/cliBoth flags are load-bearing. -n gjsify names the executable, because Deno does
not take a bin name from an npm package by itself, and -A grants the
permissions the CLI needs to read your project, write build output and reach the
registry.
The launcher lands in $DENO_INSTALL_ROOT/bin, or ~/.deno/bin by default. Deno
prints the directory and the export PATH=… line to add if it is not on your
path yet.
Or add it to one project
Section titled “Or add it to one project”Nothing says the CLI has to be global. Add it as a dev dependency and it becomes one more tool in that project’s toolchain, pinned in the lockfile with everything else, so a colleague who clones the repo gets the version you built against instead of whatever they happen to have installed.
npm install -D @gjsify/cliyarn add -D @gjsify/clipnpm add -D @gjsify/clibun add --dev @gjsify/clideno add -D npm:@gjsify/cliThen call it the way you call any other project-local binary. Inside a
package.json script the bare name works, because the runner puts
node_modules/.bin on the path:
{ "scripts": { "build": "gjsify build src/index.ts --app gjs --outfile dist/index.gjs.js", "start": "gjsify run dist/index.gjs.js" }}From your shell, reach it through your runner: npx gjsify …, pnpm exec gjsify …,
yarn gjsify …, bunx gjsify … or deno run -A npm:@gjsify/cli ….
This is how every template that gjsify create scaffolds is set up, so a project
made that way already works this way and needs nothing installed globally.
Do you need the CLI?
Section titled “Do you need the CLI?”For a browser or NativeScript build, no.
@gjsify/vite-plugin-gjsify is an ordinary npm
package whose only peer dependency is vite. Spread a preset into
vite.config.ts and run plain vite / vite build: your dev server resolves
modules the same way gjsify build --app browser does, so dev and production
agree, and no gjsify binary is involved anywhere.
npm install -D @gjsify/vite-plugin-gjsify viteFor a native GJS or GTK build the CLI is still the way. The Vite presets
mirror the --app browser and --app nativescript targets; producing the
--app gjs bundle a GNOME app ships as is the CLI’s job.
Two more plugins stand alone the same way, if all you want is one piece:
@gjsify/vite-plugin-blueprint compiles .blp
templates, and @gjsify/vite-plugin-gettext runs the PO/MO pipeline.
Update
Section titled “Update”There is no single update command, because it depends on how you installed.
gjsify self-update # install the latest releasegjsify self-update --check # only tell me whether there is onegjsify self-update --tag next # follow a different dist-taggjsify self-update --force # reinstall the same versionnpm install -g @gjsify/cli@latestbun add -g @gjsify/cli@latestdeno install -g -A -n gjsify -f npm:@gjsify/cligjsify self-update only updates installs it owns, meaning the GJS bootstrap
above and gjsify install -g. An npm, Bun or Deno install lands somewhere it
does not manage, so it warns and stops rather than half-updating you. Use your
package manager there.
On the GJS route, self-update refreshes the CLI’s runtime dependencies too (the
bundler, the formatter, the native gi:// bridges). Pass --skip-deps to update
only the CLI bundle, which is faster but can leave those stale.
Deno needs -f from the second install onwards: without it, it stops with
“Existing installation found” rather than overwriting.
Pin a version
Section titled “Pin a version”gjs -m /tmp/g.mjs --tag 0.46.0npm install -g @gjsify/cli@0.46.0bun add -g @gjsify/cli@0.46.0deno install -g -A -n gjsify -f npm:@gjsify/cli@0.46.0On the GJS route --tag takes an npm dist-tag (latest, next) or an exact
version, and gjsify self-update --tag 0.46.0 does the same for an install you
already have.
Install somewhere else
Section titled “Install somewhere else”GJS only. npm, Bun and Deno each have their own prefix setting.
GJSIFY_GLOBAL_PREFIX=$HOME/.gjsify GJSIFY_GLOBAL_BIN_DIR=$HOME/.gjsify/bin \ gjs -m /tmp/g.mjsGJSIFY_GLOBAL_PREFIX defaults to ~/.local/share/gjsify/global, and
GJSIFY_GLOBAL_BIN_DIR to ~/.local/bin.
Which runtime will the CLI build for?
Section titled “Which runtime will the CLI build for?”gjsify follows whatever runtime is running it. Installed through the GJS
bootstrap it runs on GJS, so --app and --runtime default to gjs; installed
from npm it runs on Node, so they default to node; installed with Bun or Deno
they default to bun and deno (all three consume the same --app node
bundle). Override it per command with --app / --runtime, or per project with
gjsify.app in package.json.
Your operating system is never part of that decision. The CLI asks which runtime
is executing it right now, nothing else (buildAppForRuntime(hostRuntime())). So
on Windows it targets Node, Bun or Deno, but that is a consequence rather than a
rule: it targets them because those are the only runtimes that can install and
run it there. Give a machine gjs and the same CLI targets GJS, whatever the OS
underneath.
gjsify showcase is the one exception: a showcase’s canonical build is its
--app gjs bundle, so it picks gjs whenever gjs is installed, whatever the
host.
Which version do npx, bunx and deno run give you?
Section titled “Which version do npx, bunx and deno run give you?”Not necessarily the newest one, and the command that fails because of it will not
say so. All three runners reuse a cached copy of an unpinned bin, so the same
npx @gjsify/cli … can keep serving a release from months ago. Pin the tag to
force a fresh resolve:
npx @gjsify/cli@latest showcase excalibur-jelly-jumperbunx @gjsify/cli@latest showcase excalibur-jelly-jumperdeno run -A --reload --min-dep-age=0 npm:@gjsify/cli@latest showcase excalibur-jelly-jumperDeno needs the extra flag because it applies a second rule: by default it refuses
any version published in the last 24 hours and quietly falls back to an older one.
That bites exactly when you have hit a bug, been told to run @latest, and got
the same pre-fix binary back. --min-dep-age=0 waives it for one run, or set
"minimumDependencyAge" in your deno.json.
gjsify showcase prints the version it is running as ([gjsify 0.46.0]), so
check that line first when a command misbehaves.
What you need
Section titled “What you need”- A runtime:
gjs1.86+, Node.js 20+, Bun, or Deno 2. gjs1.86 or newer if you took the GJS route. Fedora 43+, Arch and Debian forky/sid ship it. Debian 13 (trixie) ships 1.82.3 and is too old: Debian went from 1.82 straight to 1.88 in forky, so no Debian stable clears the floor yet. The bootstrap checks the version and stops with install commands for the major distributions rather than failing later.curl(orwget) for the GJS route.- An internet connection for the first run. Later installs and updates resolve from cache where they can.
Installing the CLI is not the same as being able to build a GTK app: that also needs the GNOME libraries themselves. Getting Started has the per-distribution package lists.
Uninstall
Section titled “Uninstall”gjsify uninstall -g @gjsify/clinpm uninstall -g @gjsify/clibun remove -g @gjsify/clideno uninstall -g gjsifyOn the GJS route, add --dry-run to see what would go first. To remove
everything by hand:
rm -rf ~/.local/share/gjsify ~/.local/bin/gjsifyThe bootstrap cache at ~/.cache/gjsify/ is safe to delete at any time; the next
install rebuilds it.