Skip to content
Night Owls.dev
Jump to a page

@nightowlsdev/cli

Tooling

The pluggable `owl` CLI: scaffold a Night Owls project, install adapters, and contribute their migrations, without ever running DDL.

What it does

@nightowlsdev/cli ships the single `owl` binary that bootstraps and maintains a Night Owls host. `owl init` scaffolds nightowls.config.ts + .env.example and installs the selected storage/runner/auth/model/telemetry adapters; `owl install <adapter>` adds an adapter, merges its env vars, scaffolds files, inserts its config wiring at marker comments, and contributes its migrations into the host's supabase/migrations/ as timestamped files (Night Owls never connects to your DB, you apply them with supabase db push). Each adapter plugs in via a declarative nightOwlsPlugin manifest that is matched structurally, so adapters never import the CLI (no dependency cycle), and plugins can surface their own subcommands and idempotent print-only init hooks (owl <plugin> <cmd>). By deliberate design the CLI imports zero @mastra/*, its bootstrap snapshot store comes from @nightowlsdev/storage-local's factory and it speaks MCP via the raw MCP SDK, preserving the engine wall.

Install

pnpm add @nightowlsdev/cli

Key exports

  • owl binary (init, install, plugins, db install, db types, mcp, <plugin> <cmd>)
  • NightOwlsPlugin / Migration / PluginConfig / PluginCommand / PluginContext types
  • discoverPlugins
  • nodeDiscoverDeps

Usage

cli.sh
# Scaffold a Night Owls host and install adapters
npx owl init

# Add an adapter (merges env, scaffolds files, ejects its migrations)
npx owl install storage-supabase

# List installed plugins; generate DB types
npx owl plugins
npx owl db types

What it provides

cli is the single `owl` binary that bootstraps and maintains a Night Owls host. `owl init` scaffolds a nightowls.config.ts + .env.example and installs the storage/runner/auth/model/telemetry adapters you pick; `owl install <adapter>` adds one later — merging its env vars, scaffolding its files, inserting its config wiring at marker comments, and contributing its migrations into your supabase/migrations/ as timestamped files. It is a migration CONTRIBUTOR, never a runner: Night Owls never connects to your database or executes DDL — you apply the ejected .sql with your own tooling (supabase db push).

When to use it

  • You are standing up a new Night Owls host and want the config + env + route scaffolding generated instead of hand-written.
  • You are adding an adapter (storage-supabase, runner-nextjs, an auth or model provider, telemetry) and want its env vars, config wiring, and migrations installed idempotently.
  • You adopted Night Owls after day one and need its migrations slotted into an existing supabase/migrations/ so they sort after what you already had.
  • You want to expose the local Night Owls environment to a coding agent (Claude Code, Cursor) over `owl mcp`, or generate TypeScript types for the nightowls schema with `owl db types`.

When not to

  • You already have a working nightowls.config.ts and just want to change a value — edit the file; the CLI's job is scaffolding, not ongoing config management.
  • You expect a tool that connects to your database and applies migrations for you — by deliberate design the CLI never runs DDL; it only ejects files you apply yourself.
  • You are writing a one-off script that imports the framework directly — you can `import { defineSwarm }` from core without ever running `owl`.

Alternatives

  • Hand-writing nightowls.config.tsYou want full control over the config file and are comfortable wiring each adapter's env, imports, and snippet by hand. `owl init` just generates a correct starting point you would otherwise assemble yourself.
  • Your own migration tooling (raw supabase CLI / an ORM)For applying migrations — you always use your own tool. The CLI only contributes the .sql files into supabase/migrations/; `supabase db push` (or equivalent) is what runs them.

Strengths

  • Never touches your database: it contributes migrations as timestamped files and prints the apply command — there is no DDL blast radius from running the CLI.
  • Idempotent by construction: re-running init/install never clobbers an existing config, and `owl db install` skips any migration version already present (matched by the _nightowls_<version> filename token).
  • Declarative plugin discovery: adapters expose a plain `nightOwlsPlugin` manifest matched structurally, so no adapter imports the CLI — no dependency cycle, and third-party adapters plug in the same way.
  • Engine-wall clean: the binary imports zero @mastra/* — its bootstrap store comes from storage-local's factory and `owl mcp` speaks the raw MCP SDK.

Limits & trade-offs

  • It generates a STARTING POINT, not a finished app — you still fill in your agents and set MODEL_IDS; the scaffolded config typechecks but does nothing until you complete it.
  • Install exactly one storage adapter and one auth provider; if you install two auth providers you must reconcile the duplicate `auth = …` assignment by hand (model providers and telemetry are the ones that compose).
  • It cannot apply migrations — that is a feature (no DDL), but it means adopting Night Owls is a two-step dance: `owl install`, then run your own migration tool.
  • Some adapters (runner-background, mcp) drop COMMENTED guidance at their marker rather than live wiring, because they are granted to specific agents or wired by hand — you finish those yourself.

How it works

The CLI reads your host package.json, finds the installed @nightowlsdev/* dependencies, dynamic-imports each, and collects any `nightOwlsPlugin` export — a plain object matched structurally against NightOwlsPlugin, so adapters never import the CLI. Each manifest carries env vars (merged into .env.example), a config snippet (a top-level statement inserted above the `// nightowls:<marker>` line, assigning the scaffold's pre-declared binding), files (scaffolded only if absent), migrations (installed into supabase/migrations/ as <timestamp>_nightowls_<version>.sql), an optional idempotent print-only init hook, and optional subcommands surfaced as `owl <plugin> <cmd>`. The install-time timestamp is a base clock plus an index offset so files stay unique and lexically ordered whether you adopt on day one or later. `owl mcp` starts a stdio MCP server exposing nightowls_* diagnostic tools to external coding agents, built on the raw MCP SDK and storage-local so no engine vendor enters the binary.

Examples

Scaffold a host, then add adapters

init generates config + env + adapter wiring; install adds one adapter and ejects its migrations (you apply them yourself).

cli-example-1.sh
# Scaffold nightowls.config.ts + .env.example and install the chosen adapters
npx @nightowlsdev/cli init

# Add storage later: merges env, scaffolds files, wires config, ejects migrations
npx owl install storage-supabase

# Apply the contributed migrations with YOUR OWN tooling — the CLI never runs DDL
supabase db push

Inspect plugins and generate schema types

Every installed adapter is a plugin; each can surface pure, print-only subcommands.

cli-example-2.sh
owl plugins                   # list installed plugins: kind, description, their commands
owl storage-supabase info     # a pure command: the migrations + env this adapter contributes
owl runner-nextjs routes      # the App Router routes this runner scaffolds
owl db types                  # supabase gen types typescript --schema nightowls
owl mcp                       # start the stdio MCP server (nightowls_* tools) for coding agents

Doing the parts it doesn't support

  • Applying the migrations for youNot supported by design — Night Owls never runs DDL. The CLI contributes each adapter's migrations into supabase/migrations/ as timestamped files and prints the apply instruction; you run `supabase db push` (or your migration tool) alongside your app's own migrations.
  • Wiring MCP tools or a durable runner automatically`owl install mcp` and `owl install runner-background` drop COMMENTED guidance at their config marker rather than live wiring, because MCP tools are granted to specific agents' skills and the durable runner is wired by hand. Follow the printed steps to complete them.
  • Shipping a plugin from your own packageExport a plain `nightOwlsPlugin` object (name, pkg, kind, env, config, migrations, init, commands) that structurally matches NightOwlsPlugin — do NOT import the type, that would create a cycle. The CLI discovers it from package.json automatically.

Related

  • getting-startedThe end-to-end walkthrough that starts with `owl init` and runs a first agent on a model key.
  • coreThe framework the scaffolded nightowls.config.ts wires — defineSwarm and the agents you fill in.
  • storage-supabaseThe storage adapter whose migrations `owl install` ejects into supabase/migrations/.
  • runner-nextjsThe default runner `owl install` scaffolds App Router routes for.
  • mcp`owl install mcp` wires the external-MCP connector; `owl mcp` also runs a diagnostics MCP server.