nuvix-cli
v0.1.0
Published
Build, test, publish and deploy a Nuvix backend from a nuvix.json file.
Maintainers
Readme
nuvix-cli
Build a backend from a JSON file.
npm install -g nuvix-clinvx new Booking && cd Booking
nvx init
# edit nuvix.json
nvx build && nvx test && nvx publish && nvx deployWhat this is, and what it is not
nuvix.json describes the backend you want: tables, columns, indexes, who can reach them.
nvx build sends it to Nuvix, which validates it, works out what has to change, and stores an
immutable artifact. nvx deploy applies that artifact.
The CLI does not build anything. It reads a file, posts it, and renders what came back. It has no opinion about whether a column type exists or a foreign key resolves, because the platform has one and a second opinion would be worthless — the day the two disagreed, the CLI's would be wrong by definition, and it would be telling you your configuration is broken while being unable to deploy it either way.
What that buys you: an MCP client, the dashboard and this CLI cannot form different views of the same file.
Commands
| | |
|---|---|
| nvx new <name> | create a project directory |
| nvx init | connect this checkout to a server and project |
| nvx login / logout / whoami | credentials |
| nvx diff | what would change, without changing anything |
| nvx build | validate and produce an immutable build |
| nvx test | check the live backend against a build |
| nvx publish | mark a build as the one intended to run |
| nvx deploy | apply it |
| nvx status | project, latest build, published version, deployment |
| nvx openapi | the API document a build describes |
| nvx pull | overwrite nuvix.json with the project's current state |
| nvx logs | the project's log, timings included |
| nvx config | read or change this project's connection |
nvx help <command> for any of them.
nuvix.json
{
"schemaVersion": "1.0",
"project": { "name": "Booking" },
"database": {
"tables": [
{
"name": "customers",
"columns": [
{ "name": "email", "type": "text", "maxLength": 200, "nullable": false, "unique": true }
],
"api": { "enabled": true }
},
{
"name": "bookings",
"columns": [
{ "name": "customer_id", "type": "uuid", "references": "customers" },
{ "name": "starts_at", "type": "timestamp", "nullable": false }
],
"indexes": [ { "columns": ["starts_at"] } ],
"api": { "enabled": true, "ownerColumn": "customer_id" },
"realtime": { "enabled": true }
}
]
}
}id, created_at and updated_at are added for you. Declaring one is an error; set
"standardColumns": false to opt out of all three. Tables may reference each other in any order —
the plan sorts them.
Five things the build engine does that are worth knowing before your first one:
- An unknown field is an error, not a shrug.
"nulable"fails the build instead of silently becoming a column with the wrong nullability. - Every problem comes back at once, each with a JSON path
(
$.database.tables[2].columns[1].type). Fix them all, build once more. - A build never drops anything. A table you stop mentioning is reported as a warning and left
alone. Removing one is a deliberate act through the dashboard or the
schema_*MCP tools. - A column's type and nullability cannot be changed in place. Add a new column instead.
- Building changes nothing. Only
nvx deploytouches the schema, and only for a published build, and only after showing you what it will do.
Automation and agents
Every command takes --json and answers a single document on stdout — nothing else goes there, so
a pipe is safe.
nvx build --json{
"status": "failed",
"buildId": "build_9f3a1c2b",
"errors": [
{ "code": "config.reference_not_found",
"path": "$.database.tables[1].columns[0].references",
"message": "'custmers' is neither a table in this configuration nor one the project already has.",
"remediation": "Reference one of: bookings, customers." }
]
}That is the loop an agent runs: build, read the paths, edit the file, build again.
Exit codes are a contract — they may be added to, never renumbered:
0 success 4 authorization
1 general failure 5 build validation failed
2 configuration 6 tests failed
3 authentication 7 deployment failedIn CI, authenticate with a project token in the environment and say yes on purpose:
env:
NUVIX_TOKEN: ${{ secrets.NUVIX_TOKEN }}
NUVIX_SERVER: https://api.nuvix.com
run: |
nvx build --json
nvx test --json
nvx publish --json
nvx deploy --json --yes--json implies --non-interactive; it does not imply --yes. A deploy that nobody
approved has to be asked for explicitly, or every scripted build becomes an unreviewed production
change.
Credentials
Never in nuvix.json, never in .nuvix/project.json, never printed.
| Where | Used by |
|---|---|
| NUVIX_TOKEN | CI and agents. Wins over anything stored. |
| ~/.nuvix/credentials.json, mode 0600 | nvx login |
That file is not an OS keychain, and this CLI does not claim to be one — reaching Windows
Credential Manager or the macOS Keychain from Node means a native dependency or a different
shell-out per platform, and an integration that silently fell back to a file would be worse than a
file, because you would believe the stronger claim. nvx whoami prints where your credential
actually is.
Files in a project
| | Committed | |
|---|---|---|
| nuvix.json | yes | the desired state of the backend |
| nuvix.lock | yes | the build this working tree produced, and the configuration hash |
| .nuvix/project.json | no | which server and project this checkout points at |
The hash in nuvix.lock is of the canonicalised configuration, so reformatting the file does not
make nvx status report drift and a real edit does.
Development
npm install
npm run build
npm testNo runtime dependencies, on purpose: this installs globally onto other people's machines and into CI, so every dependency would be a supply-chain surface somebody else chose. The argument parser, the prompts and the HTTP client are all a few dozen lines against the Node standard library.
