NNO Docs
Concepts

NNO CLI

Documentation for NNO CLI

Date: 2026-03-30 Status: Detailed Design — Updated Architecture Parent: System Architecture Package: packages/cli (published as nno binary)


Overview

The NNO CLI (nno) is the universal command-line interface for the Neutrino platform. It is designed as a namespaced, extensible CLI — starting with project tooling and growing to cover feature development, platform management, marketplace operations, and NNO ops as the platform matures.

nno <namespace> <command> [options]

Audiences

AudienceNamespaceUse Case
Project developernno projectLocal dev, build, and deploy for a Neutrino platform project
Feature developernno featureScaffold, develop, validate, and submit feature packages
Platform adminnno platformManage platform provisioning, tenants, feature activation (P2)
Marketplace browsernno marketplaceBrowse catalogue, check submission status
NNO operatornno opsManage infra (P2)

Namespace Roadmap

NamespacePhaseStatus
nno projectP1✅ Current scope
nno featureP1✅ Current scope
nno marketplaceP1✅ Current scope (read + operator actions)
nno platformP2🔜 When NNO Registry is live
nno opsP2🔜 NNO internal tooling

1. Installation

# Global install (recommended)
npm install -g @neutrino-io/cli
# or
pnpm add -g @neutrino-io/cli

# Verify
nno --version

The CLI is a Node.js binary published as @neutrino-io/cli and installed globally. The binary name is nno (defined in package.json bin field).


2. Package Architecture

The CLI is built with Citty — TypeScript-first, lightweight, used by the Nuxt/Nitro ecosystem.

All namespaces live inside a single @neutrino-io/cli package. Each domain is a self-contained plugin (NnoPlugin) registered at startup — keeping domains portable and independently testable without splitting into separate packages.

packages/
└── cli/                  ← single binary + plugin registry
    └── src/
        ├── index.ts      ← register plugins + runMain
        ├── cli.ts        ← registerPlugin(), createCli()
        ├── types.ts      ← NnoPlugin interface, definePlugin()
        ├── plugins/
        │   ├── project.ts      ← nno project namespace
        │   ├── feature.ts      ← nno feature namespace
        │   └── marketplace.ts  ← nno marketplace namespace
        ├── commands/
        │   ├── auth/           ← login, logout, whoami (core, not namespaced)
        │   ├── project/        ← check, dev, build, deploy
        │   ├── feature/        ← init, dev, test, build, validate, submit, status
        │   └── marketplace/    ← list
        └── utils/
            ├── credentials.ts
            └── exec.ts

Plugin interface (packages/cli/src/types.ts):

import type { SubCommandsDef } from 'citty'

export interface NnoPlugin {
  name: string                // namespace (top-level CLI command)
  description?: string
  commands: SubCommandsDef    // citty subcommands
}

export function definePlugin(plugin: NnoPlugin): NnoPlugin

External plugin authoring:

import { definePlugin, registerPlugin } from '@neutrino-io/cli/plugin'
import { defineCommand } from 'citty'

const analyticsPlugin = definePlugin({
  name: 'analytics',
  description: 'Analytics management',
  commands: {
    report: defineCommand({ ... }),
  },
})

// Register before runMain in your entry point
registerPlugin(analyticsPlugin)

Core entry point (packages/cli/src/index.ts):

import { runMain } from 'citty'
import { registerPlugin, createCli } from './cli.js'
import { projectPlugin }     from './plugins/project.js'
import { featurePlugin }     from './plugins/feature.js'
import { marketplacePlugin } from './plugins/marketplace.js'

registerPlugin(projectPlugin)
registerPlugin(featurePlugin)
registerPlugin(marketplacePlugin)

runMain(createCli())

3. Authentication

Commands that interact with NNO services require authentication:

nno login      # interactive login to NNO account
nno logout
nno whoami     # show current auth status
nno whoami
# → Authenticated as [email protected]
# → Platform: r4xk9m2zt5 (Foresight)
# → Role: platform-admin

Auth tokens stored in ~/.nno/credentials.json. Auto-refreshed before expiry.

nno project commands do not require NNO auth — they operate locally against wrangler and Vite.


4. nno project — Project Dev, Build & Deploy [Phase 1]

Current focus. Wraps wrangler and Vite with validation, context injection, and migration handling for a Neutrino platform project.

Commands

nno project check   [--env <local|dev|stg|prod>]
nno project dev     [--service <name|all>] [--env <local|dev>]
nno project build   [--env <stg|prod>]
nno project deploy  [--service <name|all>] [--env <stg|prod>]

4.1 nno project check

Validates the project config for the target environment before any operation. Runs implicitly before build and deploy.

nno project check --env stg

Checks performed:

#CheckSeverity
P01wrangler.toml exists for each serviceError
P02[env.<target>] section exists in wrangler.tomlError
P03No placeholder D1 IDs (local-dev-db not used in non-local env)Error
P04PLATFORM_ID and TENANT_ID vars are 10-char [a-z0-9] NanoIDsError
P05Required env vars present (VITE_AUTH_API_URL etc. for the target env)Warning
P06Wrangler secrets exist for target env (wrangler secret list --env <env>)Warning
P07D1 migration state — pending migrations detectedInfo
P08CF Pages project name matches naming conventionWarning

Example output:

nno project check --env stg

  Checking project config for env: stg

  ✓ P01  wrangler.toml found (auth, console)
  ✓ P02  [env.stg] defined in all service configs
  ✓ P03  D1 IDs populated (no placeholders)
  ✓ P04  PLATFORM_ID=r4xk9m2zt5, TENANT_ID=n7wp3fy8q1
  ⚠ P05  VITE_AUTH_API_URL not set for stg — set in CF Pages dashboard
  ⚠ P06  AUTH_SECRET not set for stg — run: nno project deploy --env stg (will prompt)
  ✓ P08  Pages project name follows convention

  0 errors, 2 warnings — project is deployable with caveats

4.2 nno project dev

Start local development. Validates local config, applies pending migrations, then starts all services.

nno project dev                         # start all services
nno project dev --service auth          # auth worker only
nno project dev --env dev               # target dev CF environment

What it does:

nno project dev

  ├─ nno project check --env local
  ├─ Apply pending local D1 migrations (wrangler d1 migrations apply --local)

  ├─ wrangler dev  (platform auth Worker)                     → localhost:8787  (per-platform auth)
  │    Note: services/auth/ is a TEMPLATE with REPLACE_WITH_* placeholders —
  │    it is NOT deployed from this repo. Each platform project supplies its
  │    own deployed auth Worker; local dev starts a wrangler instance of it.
  └─ vite dev (apps/console)                                  → localhost:5174
       └─ /api/auth proxied to localhost:8787

4.3 nno project build

Build the console shell for the target environment.

nno project build --env stg
nno project build --env prod

What it does:

nno project build --env stg

  ├─ nno project check --env stg
  └─ vite build --mode stg  (apps/console)
       → outputs apps/console/dist/

Vite loads apps/console/.env.stg for environment-specific vars.


4.4 nno project deploy

Full deployment pipeline: check → build → deploy workers → apply migrations → deploy Pages.

nno project deploy --env stg
nno project deploy --env prod
nno project deploy --env stg --service auth     # single service only

What it does:

nno project deploy --env stg

  ├─ nno project check --env stg
  ├─ nno project build --env stg

  ├─ wrangler deploy --env stg  (services/auth/)              (per-platform auth)

  ├─ wrangler d1 migrations apply --env stg --remote  (if P07 flagged pending)

  └─ wrangler pages deploy apps/console/dist
       --project-name=r4xk9m2zt5-n7wp3fy8q1-portal-stg
       --branch=develop

5. nno feature — Feature Package Development [Phase 1]

Scaffold, develop, test, validate, and submit feature packages to the NNO Marketplace.

Commands

nno feature init      <feature-name> [options]
nno feature dev       [--no-service] [--platform <id>] [--env <dev|stg>]
nno feature test      [--watch] [--coverage]
nno feature build     [--analyze]
nno feature validate  [--fix] [--json]
nno feature submit    [--message <msg>] [--private] [--dry-run]
nno feature status    [<submission-id>]

5.1 nno feature init

Scaffold a new feature package from the NNO template.

nno feature init analytics
nno feature init inventory --no-service
nno feature init crm --dir ./packages/ui-crm

Options: --no-service, --no-database, --dir <path>, --template <id>

Generates the full scaffold structure, runs pnpm install, prints next steps.


5.2 nno feature dev

Start the local feature development environment — runs a mock NNO shell alongside the feature's Vite dev server and optional Wrangler service.

nno feature dev
nno feature dev --no-service
nno feature dev --platform r4xk9m2zt5 --env stg

Default mode:

nno feature dev

  ├─ NNO Mock Shell     localhost:5100   (ShellContextProvider + mock user/tenant)
  ├─ Feature Vite Dev   localhost:5180   (mounted inside mock shell, full HMR)
  └─ Wrangler Service   localhost:8790   (local D1, hot-restart)

Mock shell config (~/.nno/mock-shell.json):

{
  "platform": { "id": "dev-platform", "name": "Local Dev Platform" },
  "tenant":   { "id": "dev-tenant",   "name": "Local Dev Tenant" },
  "user": { "id": "dev-user", "email": "[email protected]", "permissions": ["*"] }
}

Real platform mode (--platform): connects mock shell to actual NNO auth service; uses real tenant config from NNO Registry.

Port assignments:

ServiceDefault PortConfig key
Mock shell5100fixed
Feature Vite dev5180dev.port in nno.config.ts
Feature Wrangler service8790dev.servicePort in nno.config.ts

5.3 nno feature test

Run tests with vitest — correct configuration for both UI (jsdom) and service (CF Workers pool) targets.

nno feature test
nno feature test --watch
nno feature test --coverage
nno feature test --service-only
nno feature test --ui-only

5.4 nno feature build

Build the feature package for distribution using tsup (UI) and wrangler build (service).

nno feature build
nno feature build --analyze

Output:

dist/
├── index.js        ← UI package (ESM)
├── index.d.ts      ← Type declarations
├── feature.js      ← FeatureDefinition (tree-shakeable)
└── service/
    └── worker.js   ← Compiled Hono Worker (if service present)

5.5 nno feature validate

Validate the feature package against the NNO SDK contract. Must pass before nno feature submit.

nno feature validate
nno feature validate --fix
nno feature validate --json

Validation rules:

#RuleSeverity
V01nno.config.ts exists and parses without errorError
V02feature.id matches ^[a-z][a-z0-9-]*$Error
V03feature.id matches nno.config.ts id fieldError
V04feature.version is valid semverError
V05feature.version matches package.json versionError
V06All permissions[].key values match ^\{id\}:[a-z-]+$Error
V07At least one required: true permission declaredError
V08serviceEnvKey present when requiresService: trueError
V09service/ directory exists when requiresService: trueError
V10service/wrangler.toml is a valid template (no hardcoded IDs)Error
V11All navigation[].path values exist in routes[].pathError
V12No duplicate route pathsError
V13No route path starts with /\{feature-id\} (shell prefixes automatically)Error
V14No imports from shell internal paths (@/, apps/console/)Error
V15No hardcoded API URLs (must use serviceEnvKey + useServiceUrl)Warning
V16feature.ts default export is a valid FeatureDefinition (Zod)Error
V17nno.config.ts compatibility.shellVersion is valid semver rangeWarning
V18package.json has publishConfigWarning
V19README.md exists and is non-emptyWarning
V20Build succeeds (nno feature build exits 0)Error

5.6 nno feature submit (Phase 2)

Provisional design — subject to revision.

nno feature submit and the associated submission/review pipeline are Phase 2 capabilities, contingent on lifting the Q4 NNO-only authorship restriction. NNO currently authors all feature packages internally; external feature submissions are not yet supported. The design below documents the intended future workflow.

Submit the feature package to NNO Marketplace for review.

nno feature submit
nno feature submit --message "Initial submission — analytics v1"
nno feature submit --private
nno feature submit --dry-run

Flow:

nno feature submit
  ├─ nno feature validate    (fails fast on errors)
  ├─ nno feature build
  ├─ Package dist/ + nno.config.ts + README.md → submission bundle (.nno)
  ├─ Upload to NNO Marketplace review queue
  └─ Returns submission ID + tracking URL

5.7 nno feature status (Phase 2)

Provisional design — subject to revision.

nno feature status is a Phase 2 capability tied to the external submission workflow. It is not available until the submission pipeline is enabled.

Check marketplace submission status.

nno feature status                   # all pending submissions for your platform
nno feature status sub_9x2m4k7p1q   # specific submission

Statuses: PENDINGIN_REVIEWAPPROVED | REJECTED


6. nno marketplace — Stack Template Catalogue [Phase 3]

Commands

nno marketplace list     [--search <term>]
nno marketplace approve  <submission-id>
nno marketplace reject   <submission-id> [--reason <msg>]

nno marketplace list is available to all authenticated users. It browses NNO-authored stack templates from services/stack-registry. nno marketplace approve and nno marketplace reject are operator commands — they are registered in the CLI and available as stubs for NNO operators to approve or reject marketplace submissions.


7. nno platform — Platform Management [Phase 2]

Available when NNO Registry is live. Handles provisioning, tenant management, and feature activation.

nno platform deploy  --platform <id> --env <stg|prod> [--wait]
nno platform status  --platform <id>
nno platform tenants --platform <id>

nno platform deploy supersedes the nno project deploy wrangler wrapper — it calls the NNO CLI Service API which orchestrates the full GitHub commit → CF Pages build cycle.


8. Configuration

Project: nno.config.ts

See Feature Package SDK — Section 5 for the full schema.

Global: ~/.nno/config.json

{
  "apiUrl": "https://api.stack.nno.app",
  "defaultPlatform": "r4xk9m2zt5",
  "defaultEnv": "stg"
}

9. CI/CD Integration

Feature Package CI (GitHub Actions)

jobs:
  validate-and-test:
    steps:
      - run: npm install -g @neutrino-io/cli
      - run: pnpm install
      - run: nno feature validate --json
      - run: nno feature test --coverage
      - run: nno feature build

Platform Project CI (GitHub Actions)

jobs:
  deploy-stg:
    if: github.ref == 'refs/heads/develop'
    steps:
      - run: nno project check --env stg
      - run: nno project deploy --env stg

  deploy-prod:
    if: github.ref == 'refs/heads/main'
    steps:
      - run: nno project check --env prod
      - run: nno project deploy --env prod

10. NNO Backend Services (CLI calls)

CLI commands that interact with NNO cloud services route to their respective backend services. The CLI binary calls these services directly (via the NNO Gateway or directly):

CLI CommandNNO ServiceEndpointAction
nno loginservices/iamPOST /api/auth/sign-in/emailAuthenticates user, returns session token (Designed, not yet available)
nno whoamiservices/iamGET /api/nno/sessionReturns current session + permissions
nno marketplace listservices/stack-registryGET /api/v1/stacksLists NNO-authored stack templates
nno platform deployservices/cliPOST /api/v1/platforms/\{id\}/deployTriggers CF Pages rebuild (P2)

nno project commands are fully local — no NNO service calls.


11. Error Handling & Exit Codes

Exit CodeMeaning
0Success
1General error (network, auth, unexpected)
2Validation failure (validate or check found errors)
3Build failure
4Submission rejected by server (conflict, quota, etc.)

All errors include an actionable message:

✗ Error [V08]: serviceEnvKey is required when requiresService is true

  Add serviceEnvKey to your FeatureDefinition:
  → serviceEnvKey: 'VITE_ANALYTICS_API_URL'

  Docs: https://docs.nno.app/sdk/feature-definition#serviceenvkey

12. Command Migration Reference

Flat commands from the original spec map to namespaced commands:

Original (flat)Namespaced
nno devnno project dev
nno buildnno project build / nno feature build
nno deploynno project deploy / nno platform deploy (P2)
nno validatenno project check / nno feature validate
nno initnno feature init
nno testnno feature test
nno submitnno feature submit (Phase 2)
nno statusnno feature status (Phase 2)
nno listnno marketplace list

Status: Detailed design — single-package plugin architecture Tech stack: Citty (TypeScript-first CLI framework) Implementation target: packages/cli/ Related: Feature Package SDK · System Architecture · NNO CLI Service

On this page