CLI
The Frigear CLI saves you from copying and renaming starters by hand. It creates a project from a
starter, adds an app or a module to a pnpm workspace, and installs Frigear modules in an
app. It works in any pnpm workspace, not only in the Frigear repository. Its package is
@frigear-nu/cli, a citty CLI published to npm.
Run it
Run it without installing it:
pnpx @frigear-nu/cli --help
pnpx @frigear-nu/cli <command> --help
pnpm create frigear-app (or npm create frigear-app@latest) does the same as init below.
Inside the Frigear repository, use the root cli script. It runs packages/cli/bin/cli.mjs, which loads the
TypeScript source with jiti, so there is no build step:
pnpm cli --help
Frigear-nu/frigear-nu GitHub repository with
giget. While that repository is not public, set GIGET_AUTH to a GitHub token that can
read it, for example GIGET_AUTH=$(gh auth token).Commands
| Command | Purpose |
|---|---|
init | Creates a new project from a starter. |
app:create | Adds an app from a starter to apps/<name> of a workspace. |
module:create | Scaffolds a new Nuxt module under packages/. |
add | Installs Frigear modules in a Nuxt app and adds them to its nuxt.config. |
Every command takes --cwd <dir> (default: INIT_CWD, else the current directory).
init
pnpx @frigear-nu/cli init [dir] [--platform <platform>] [-t <template>] [--ref <ref>] [--force] [--no-install]
| Argument | Default | Purpose |
|---|---|---|
dir | frigear-app | Directory to create. Its name becomes the root package.json name. |
--platform, --starter | asked, web when not interactive | What to build: web, mobile or web,mobile, or the starter's name. See the table below. |
-t, --template | Any giget source to copy instead of a starter, for example gh:org/repo/path#ref. Not together with --platform. | |
--ref | main | Branch or tag of the repository to copy the starter from. |
--force | false | Write into a directory that is not empty. |
--no-install | Skip pnpm install and pnpm prepare:env. |
--platform | Starter (also accepted as the value) | What you get |
|---|---|---|
web | workspace | apps/web with sign-in, account pages and user management in the admin area |
mobile | mobile | apps/mobile, a Capacitor app that signs in at an existing issuer |
web,mobile | mobile-standalone | both, with apps/web as the app's OAuth server and API |
With -t, the root package.json is still renamed (when there is one), and pnpm prepare:env only runs when the
template has that script.
app:create
pnpx @frigear-nu/cli app:create <name> [--template <template>] [--ref <ref>] [--no-install]
| Argument | Default | Purpose |
|---|---|---|
name | required | Folder under apps/, kebab-cased. |
--template | web | web (the workspace starter's app), web-standalone (the mobile-standalone starter's OAuth server app) or mobile. |
It needs a pnpm-workspace.yaml above --cwd. The package is named <scope>/<name>, with the scope of the existing
apps (@workspace in the starters), else of the root package. It fails when apps/<name> already has a
package.json, and runs pnpm install at the root unless --no-install is passed.
module:create
pnpx @frigear-nu/cli module:create <name> [--template <template>] [--scope <scope>] [--dir <dir>]
| Argument | Default | Purpose |
|---|---|---|
name | required | Name of the module, for example my-module. It is kebab-cased. |
--template | gh:nuxt/starter#module | A giget template source, for example gh:github.com/my/package. |
--scope | the root package's scope | npm scope, for example @acme. --scope "" leaves the name unscoped. In this repository the root is @frigear-nu/root, so modules are @frigear-nu/<name>. |
--dir | packages | Workspace folder to create the module in. |
It downloads the template into <workspace root>/<dir>/<name> and sets the name in its package.json. It exits
with an error, without changing anything, when that folder already contains a package.json.
add
pnpx @frigear-nu/cli add <module...> [--app <app>] [--no-install]
| Argument | Default | Purpose |
|---|---|---|
module | required | One or more modules: forms means @frigear-nu/forms; a scoped name is used as is. |
--app | see below | The app: a path, or a folder under apps/. |
--no-install | Only edit nuxt.config. |
Without --app, the app is the current directory when it has a nuxt.config, else the only app under apps/ with
one. The command runs pnpm add in the app and adds each module to modules once. It prints each module's
documentation link.
pnpm db:generate, as
Adding modules describes.create-frigear-app
pnpm create frigear-app [dir] [--platform <platform>] [-t <template>] [--ref <ref>] [--force] [--no-install]
npm create frigear-app@latest [dir] [--platform <platform>]
packages/create-frigear-app is what pnpm create and npm create find. It has no dependencies: it runs init of
@frigear-nu/cli@latest with the package manager that started it (pnpm dlx, npx, yarn dlx or bunx), so it takes
the same arguments as init, and every CLI release reaches it without releasing create-frigear-app. The starters
come from main unless you pass --ref. Set FRIGEAR_CLI to run another CLI, such as @frigear-nu/cli@0.1.0 or a
packed tarball.
After module:create in the Frigear repository
The command only creates the package. Scaffold a module starts the path through
the rest: the folder layout, setup(), tests, the release config and the module page.
Developing the CLI
The source is in packages/cli/src, with one file per command in commands/. Its tests run against the repository's
own .starters/, with giget mocked, so nothing is downloaded or installed:
pnpm --filter @frigear-nu/cli test
The published package is built with unbuild into dist/, and publishConfig points bin at dist/cli.mjs. It is
released like every other package.
Next steps
- Scaffold a module – turn a new
module:createpackage into a module. - Installation – create a project with
initand run it. - Publishing – release a new version of the CLI.