The nola CLI
The nola executable is part of the nola-lang dev dependency. Run commands with npx nola-lang <command> or through your project’s npm scripts.
Use nola <command> --help to see a command’s flags. Flags apply only to the command that defines them. Commands exit with 0 on success and 1 on failure, with errors written to stderr. Running nola without a command, or with --help, prints the command list; an unknown command prints the list and exits with 1. Use --version to print the installed version.
Within a Nola project, npx nola-lang uses the locally installed package. Elsewhere, npx downloads it. Keep the -lang suffix: npx nola can resolve an unrelated package outside a project. To create a new project, use npm create nola.
nola init [dir] [--template <t>|--add] [--provider <id>] [--ide vscode|none] [--agents <list>]nola build [dir] [--out <dir>]nola run <entry>nola check [dir]nola console [--port <n>]nola declarations [dir] [--watch]nola skill install [--agents <list>] [--force]nola key [--print]nola loginnola logoutnola accountnola init
Section titled “nola init”nola init [dir] [--template <name> | --add] [--provider nola|openai|anthropic|google|typesafe|none] [--ide vscode|none] [--agents claude,universal,agents-md|all|none]Creates a project or adds Nola to an existing one, using the same flow as npm create nola.
| Flag | Effect |
|---|---|
--template <name> |
Selects a template. See the template list below. |
--add |
Adds Nola to dir by writing nola.config.ts and merging dependencies into package.json. Cannot be combined with --template. See Add Nola to an existing project. |
--ide vscode|none |
Writes .vscode/launch.json and .vscode/extensions.json by default. Use none to skip them. |
--agents <list> |
Selects agent skill files. Defaults to claude,universal; none skips them. See nola skill install below. |
--provider <id> |
Selects nola, openai, anthropic, google, typesafe, or none. |
--trial / --no-trial |
Shorthand for --provider nola / --provider none. |
The first template menu offers:
feature-extraction, the default: one.tsifile that extracts typed data with a top-levelask.function-calling: one.tsifile that usesaskto call an async function from a neighboring TypeScript file.agent-loop: one.tsifile with a top-levelwhileloop around an ask, and a context statement read again on every pass.typescript-interop: an infer function imported from plain TypeScript.triage-ticket: a single-file example usingtypesafe(). Its provider is preselected, and the setup instructions ask you to setTYPESAFE_API_KEY.empty: configuration files and a stubsrc/main.tsifor a project whose code you write yourself.
The first four run offline with their default configuration. More examples… opens a second menu with file-ticket, extract-resume, extract-invoice, classify-message, chain-of-thought, and research-notes. You can pass any of these names to --template.
Every template except empty is one of the examples in the Nola repository. The scaffolder copies it from the release tag that matches its own version, falling back to main when the tag is missing, so scaffolding those templates needs network access. empty ships inside the package and works offline.
After you select a template, the interactive flow asks for an inference provider, with nola: dev highlighted. The Nola provider configures model: "nola", writes NOLA_API_KEY to .env, and ensures .env is ignored by git. A machine that has not used its anonymous trial receives 25 free runs.
If the trial was already issued, selecting Nola opens the browser sign-in flow before the remaining setup steps. The menu says Trial key already issued. Get another? Enter to sign in. A failed sign-in returns to the menu. If you are already signed in, the menu indicates that, and the key is created on your account.
Other providers write their configuration and an API-key placeholder in .env.example:
| Provider | Model configuration | Environment variable |
|---|---|---|
openai |
openai("gpt-5-mini") |
OPENAI_API_KEY |
anthropic |
anthropic("claude-sonnet-4-5") |
ANTHROPIC_API_KEY |
google |
google("gemini-2.5-flash") |
GEMINI_API_KEY |
typesafe |
typesafe() |
TYPESAFE_API_KEY |
Copy the placeholder to .env and supply your key. The typesafe.ai option includes a warning for templates with unsupported types: it accepts literal unions and booleans, and rejects unsupported output types before a network request.
--provider none keeps the template’s configuration, including offline replay where provided. It is the default for non-interactive runs. If a non-interactive run requests Nola on a machine that has used its trial and has no saved sign-in, no key is issued; the output directs you to nola login.
nola build
Section titled “nola build”nola build [dir] [--out dist]Compiles every .tsi under dir, which defaults to ., into the output directory, which defaults to dist. It skips node_modules, .git, and dist, and preserves the source directory structure. For example, src/person.tsi produces dist/src/person.tsi.js, its source map, and a .tsi.d.ts declaration file.
For app projects, build.target: "app" is the default. The build bundles nola.config.ts into dist/nola.config.js and adds an import to each built module so the app configures itself. It refuses to overwrite a dist/nola.config.js that Nola did not generate. Library builds with build.target: "lib" skip this configuration step.
Views of plain TypeScript modules are emitted as .tsi.js and .tsi.d.ts files beside the built output. nola build does not compile the underlying .ts files; see Deploying for how to include them.
nola run
Section titled “nola run”nola run <entry>Runs a .ts or .tsi entry point with the Nola loader registered for its directory. The loader compiles .tsi in memory and loads nola.config.ts and its neighboring .env.
This is a shortcut for node --import nola-lang/register <entry>. Like node, it exits when the program’s event loop drains, so a trace still on its way to the console arrives before the process ends, and a program that keeps a server open keeps running. If the program fails, nola run still gives traces already on their way up to two seconds to arrive, then exits with code 1. Scaffolded projects use it for npm start. See The Node loader.
nola check
Section titled “nola check”nola check [dir]Type-checks both the compiled .tsi code and the project’s TypeScript files, using tsconfig.json. Diagnostics point back to the original .tsi positions, in the form file:line:col NOLA… or TS….
Nola compile errors (NOLA1xxx and NOLA2xxx) are reported first. Use this command to check Nola source; plain tsc cannot parse .tsi.
nola console
Section titled “nola console”nola console [--port <n>]Starts the local Nola Console for viewing ask traces. It listens only on loopback, using the first available port from 4141 upward. Pass --port to require a specific port. One console instance can receive traces from all projects on the machine.
The console stores traces in ~/.nola/console using Node’s built-in SQLite database, which requires Node ≥ 22.13. On startup, it prints the URL and storage directory. It then prints one line per event, including the time, event kind, source site, provider, and duration. Events include ask start and end, provider requests and replies, validation failures, retries, and invocation end.
To connect a project, set telemetry: "<url>" in nola.config.ts using the printed URL. This is shorthand for nola.tracer("<url>"). Add terminalTrace() to the telemetry list if you also want terminal traces. See Telemetry.
Clear traces, below the trace list, deletes all stored traces, asks, and ask definitions and prints a clear line. New events continue to arrive. Press Ctrl+C to stop the console. Trace delivery is asynchronous, so inference continues even when the console is unavailable.
nola declarations
Section titled “nola declarations”nola declarations [dir] [--watch]Writes <name>.d.tsi.ts beside each .tsi file. These declarations let plain tsc and framework builds resolve .tsi imports when "allowArbitraryExtensions": true is set.
Use --watch to regenerate declarations as .tsi files change; press Ctrl+C to stop it. Add the generated files to .gitignore. The editor hides them when the source .tsi is present, and nola check ignores them. Nola’s bundler plugins can generate them during a build.
nola skill install
Section titled “nola skill install”nola skill install [--agents claude,universal,agents-md | all | none] [--force]Installs Nola instructions for coding assistants in the project. Each copy is self-contained and stamped with the nola-lang version that wrote it.
| Target | Files written |
|---|---|
claude |
.claude/skills/nola/. When universal is also selected, this is a relative symlink to that copy. Otherwise, it is a separate copy. |
universal |
.agents/skills/nola/, the shared Agent Skills location used by compatible coding assistants. |
agents-md |
The skill body embedded in AGENTS.md. |
Interactive runs preselect claude and universal. Non-interactive runs must pass --agents. Scaffolding and --add install both by default; --agents overrides that choice.
Copies stamped with the installed version are left alone. Older copies are reported as stale and replaced only with --force, so run nola skill install --force after upgrading. With the universal target, --force also removes superseded, Nola-generated .cursor/rules/nola.mdc and .github/instructions/nola.instructions.md files. Files without Nola’s generation stamp are left alone.
On Windows, a git checkout without symlink support may leave a plain file where the Claude skill link should be. Running nola skill install repairs it. Creating a symlink requires Developer Mode or an elevated shell; otherwise, the installer writes a copy and reports that choice.
You can also install the skill through the community Agent Skills CLI: npx skills add nola-lang/nola uses the public repository, while npx skills experimental_sync finds it in an installed nola-lang project’s dependencies. These copies have no Nola version stamp, so nola skill install reports them as externally installed and leaves them alone.
nola key
Section titled “nola key”nola keynola key --printGets a Nola API key and offers to save it in the current project’s .env.
- If you are signed in, the key is created on your account.
- If this machine has not used its free trial, it receives an anonymous trial key.
- If the machine has used its trial, the command asks you to sign in. Yes is selected by default. Choosing No or pressing Esc exits with
1without opening the browser.
The output includes the new key and whether it was saved:
Key minted on your Nola account.NOLA_API_KEY=nola_sk_…Added to .env. Use it with `model: "nola"` in nola.config.ts.After printing the key, the command asks Add it to .env?, with Yes selected. Enter accepts; the arrow keys change the choice. Esc or Ctrl+C leaves without writing.
If .env already contains NOLA_API_KEY, a second prompt asks whether to replace it, with No selected. Accepting replaces that line; any other response keeps the existing key. Non-interactive runs print Not written — add the line above to .env yourself.
This command changes only .env. For project setup, including .gitignore, configuration, and dependencies, use the scaffold or nola init --add --trial.
With --print, stdout contains only the key. Sign-in messages go to stderr, so NOLA_API_KEY=$(npx nola-lang key --print) works. This mode does not write .env.
An account can have ten live keys. Use the account console to list or revoke them. The command exits with 1 if key creation fails, sign-in is declined or times out, or a non-interactive run needs you to sign in. The error message explains the failure and, when needed, directs you to npx nola-lang login. For development, NOLA_API_URL overrides the API endpoint.
nola login and nola logout
Section titled “nola login and nola logout”nola loginnola logoutnola login opens a browser to sign this machine in to Nola. It prints the link before opening it:
Sign in to Nola: open https://….auth0.com/authorize?…Waiting for the browser…Signed in as you@example.com.The CLI waits for the browser to return to a local callback on 127.0.0.1, using one of the server-specified ports from 47831–47833. Complete sign-in on the machine running the command. Over SSH, forward the callback port or sign in locally.
Set NOLA_BROWSER to choose the browser command, such as NOLA_BROWSER="firefox". Set NOLA_NO_BROWSER=1 to print the link without opening it.
The session is stored in ~/.nola/credentials.json with owner-only permissions and refreshed automatically. Tokens are not printed or stored in the project.
If this machine used an anonymous trial, sign-in preserves that account’s key and run usage. Subsequent keys are created on the same account. If the current project’s .env contains a trial key from another machine, sign-in links that trial account too and prints Linked this project's trial account to your Nola account.
The command exits with 1 if sign-in is declined, takes longer than five minutes, is unavailable on the server, or returns without a Nola account. In the last case, it reports Sign-in did not return your Nola account — the server's sign-in provider is misconfigured. and stores nothing.
If the server later rejects a saved session, for example with account_claim_missing or account_mismatch, the CLI removes it. Run nola login again to sign in.
nola logout revokes and removes the saved session, then prints Signed out of Nola. If you are already signed out, it reports that instead.
nola account
Section titled “nola account”nola accountShows the signed-in account and opens its console page. The command works from any directory. If you are signed out, an interactive run starts sign-in; a non-interactive run exits with 1 and directs you to nola login.
If the current project’s .env contains a trial key, that trial account is linked first. The command then prints the account status and balance:
Nola account: you@example.com — 3 / 25 free runs usedBalance $7.84The output also explains that the hosted service is intended for prototyping and development. It opens your account page and prints the link in case the browser does not open. NOLA_NO_BROWSER=1 skips opening the browser. The page signs you in with the same account without putting a key or token in the URL.
The account page shows your balance and API keys, masked to their prefix and last characters. You can add $5, $25, $50, or a custom amount through Stripe, up to a $100 account balance. All keys on the account share its balance and free runs.
Revoking a key stops it from working immediately. Use nola key to create a replacement. Viewing the account does not change project files or existing keys.
The command exits with 1 if the session is invalid or the API cannot be reached. An invalid-session message directs you to nola login. NOLA_API_URL overrides the API endpoint for development.
You can use another provider instead of hosted Nola inference. See Providers. For an existing project, npx nola-lang init --add --no-trial writes configuration without requesting a trial.
npm create nola and nola init
Section titled “npm create nola and nola init”npm create nola runs create-nola, an alias for create-nola-lang. The installed nola init command uses the same setup flow and produces the same project.
Next: The Node loader