CLICommandsMenu

CLI

Every command of the Intelligo CLI — create, add, doctor, migrate and upgrade — documented from its own source.

A scaffolded app has @intelligo-dev/cli as a dev dependency; run it with pnpm exec intelligo.

Output
intelligo <command>
intelligo create [dir]      Scaffold an app, then install the registry pages you pick
                            (--items a,b | --all, --yes, --no-install, --name <name>)
intelligo doctor            Report configuration and migration-chain problems
intelligo migrate           Apply the framework's migration chain to DATABASE_URL
intelligo migrate --check   Compare the framework's and the app's migrations to a database
                            (--json: one object whose `state` is up_to_date | pending |
                            fresh | ahead | unmanaged | legacy)
intelligo admin grant <email>  Make a signed-up user a platform admin (--force in production)
intelligo add <feature>     Generate consumer-owned source (--force to overwrite)
intelligo upgrade --check   Show what a template upgrade would change
intelligo sync [items…]     Install registry pages from this release's registry
                            (names space- or comma-separated),
                            keeping seams and merging messages (--force replaces
                            hand-edited files; --check only reports, exit 1 on drift)

create

A new application on the framework.

This is onboarding, not the product boundary: what it writes is the consumer’s from the moment it lands, and the enduring relationship is the versioned packages, not this scaffold. So it generates through the same manifest machinery as add, which means the very first upgrade already knows which files you have since edited.

In a terminal it asks for the project name when none is given, then which registry pages to install (--items a,b or --all answer that without asking). The pages are installed by intelligo sync — one shadcn add per item, from the registry this CLI carries — after the dependencies (from the root of a parent pnpm workspace when the app is a member of one), and only once you approve the exact commands, or pass --yes. --no-install stops after the scaffold and prints them instead.

source

add

Generate consumer-owned source.

“Owned” is the operative word: the files land in the consumer’s repository and Intelligo stops deciding what is in them. The manifest records what was written and its hash so a later upgrade can tell an untouched file from one the consumer has made their own, and refuse to overwrite the latter.

source

Feature What it generates
pnpm-standalone pnpm settings for an app that is its own workspace root: dependency build scripts declined, so pnpm 10+ installs without a prompt, and pnpm add allowed at the root for the shadcn CLI. intelligo create writes it when pnpm installs an app outside any workspace — pnpm-workspace.yaml, .npmrc
admin-page Mount the Intelligo operational console at /admin, styled with the app’s tokens, for platform admins only — app/[locale]/admin/page.tsx
maintenance A CRON_SECRET-gated GET /api/cron/maintenance that reconciles stale executions, drops expired reservations and rate-limit buckets, expires trials and prunes old jobs — scheduled every five minutes, in vercel.json when the app has none — app/api/cron/maintenance/route.ts
vitest A Vitest setup for the app’s own tests: the @ alias, a server-only stub, and the @intelligo-dev/* packages inlined so the stub reaches them — vitest.config.ts, tests/stubs/server-only.ts

doctor

Report the problems that are invisible until they are an incident.

source

migrate

Apply the framework’s migration chain.

A consumer application has two migration chains in one database: the framework’s, shipped inside @intelligo-dev/core (its .sql files and journal are in the package’s files), and its own, which drizzle-kit generates from the tables the application owns. They must not share a journal — drizzle-kit applies by timestamp, so a framework migration published after the consumer generated one of theirs would be silently skipped — and a consumer cannot write into node_modules anyway. So the framework chain is applied by this command, into drizzle’s default drizzle.__drizzle_migrations table, and the consumer’s chain by drizzle-kit migrate from their own drizzle.config.ts, into a table of its own (the scaffold sets migrations.table to __app_migrations).

Migrations are selected by content hash (what migrate --check compares), not by drizzle’s journal-timestamp rule, and are recorded in the same table drizzle’s migrator writes — see readPendingMigrations for why.

The one thing this refuses to do is guess. A database with the framework’s tables but no migration records was provisioned with db:push; applying the whole chain to it would fail part-way (not every migration is IF NOT EXISTS-guarded) and leave the records half-written. Baselining is the fix, and it is deliberately a manual step — see packages/core/src/db/migrations/README.md.

source

migrate –check

Answers “would deploying this code against that database work?” without changing anything. Two failure modes matter and neither is visible from the code alone:

  • migrations the database has not applied yet (deploying now runs code against an older schema);
  • migrations the database has applied that this checkout does not contain (the database is ahead — usually a rollback in progress).

Drizzle records applied migrations in drizzle.__drizzle_migrations by content hash. A database provisioned with db:push has the schema but no rows there at all, which this reports distinctly: “unmanaged” is a different problem from “behind”, and baselining is the fix (see the migrations README).

The framework’s chain is one baseline. A database that ran the pre-1.0 chain holds its hashes, which legacy-chain.json (next to the journal) lists: they are reported as legacy, not as unknown, and a database holding all of them is adoptable — its schema is the baseline’s, so migrate records the baseline without running it.

The exit code is 1 whenever anything is pending or the database is ahead, which a brand-new database and a stale one share. A deploy gate that must tell them apart reads migrate --check --json: one JSON object on stdout, same exit code, whose state is

  • up_to_date — every migration is applied;
  • pending — a migrated database is behind this checkout;
  • fresh — no migration records and none of the framework’s tables: an empty database, migrate applies the chain;
  • unmanaged — the tables exist with no records (db:push);
  • ahead — applied migrations this checkout does not contain;
  • legacy — the pre-1.0 chain; adoptable says whether migrate can take it over.

Beside state it carries exitCode, chain, applied, pending, unknown, legacy, legacyMissing and adoptable. state describes the framework’s chain; app is the application’s own chain (app-chain-check.ts) — { chain, applied, pending, unknown }, or null when the app owns none — and exitCode covers both.

source

upgrade –check

Reports what a template upgrade would do, and does nothing. Upgrades never overwrite consumer source, so the interesting output is not “these templates changed” but “these changed AND you have edited them” — the set where the consumer has to make a decision.

source

sync

Keeps an app’s installed registry pages exactly what the framework ships. Installing stays the shadcn CLI’s job — every item goes in with shadcn add <item> --yes --overwrite — and this command adds what shadcn cannot know:

  • the version: items come from the registry bundled with this CLI, so they match the @intelligo-dev/* packages of the same release;
  • the order: an item that imports a sibling’s files lands after it (requires.json items);
  • the seams: files an item ships once for the deployment to own (requires.json seams) are put back after the install, and message files are merged key by key, the app’s copy winning;
  • the record: intelligo.manifest.json keeps each installed file’s hash, so --check can tell a file edited by hand from one a newer registry replaced. Scaffold files an install replaces (globals.css, the theme provider) leave the app-scaffold record for this one, so upgrade --check stops calling them customized.

--check installs nothing and exits 1 when any installed file is missing, edited or behind the registry — the gate CI runs.

source