Configure Nova
Generate or update the Nova config file with an interactive wizard that guides you through each step and saves when you confirm.
Summary
The configure command creates and maintains the complete nova.config.json file through focused editors for every supported configuration field.
Existing values populate each prompt so you can edit an accurate snapshot and only persist changes when you confirm them.
Why Use This Command?
- The wizard writes the JSON with only the fields you confirm, no extra cleanup required.
- The wizard lists each field, explains what each field is for, and guides you to fill known values.
- Every supported
nova.config.jsonvalue is reachable through the wizard; no field is reserved for direct JSON editing. - Avoid typos and mismatched formats with built-in validation for slugs, emails, and URLs.
- Dry run lets you walk through the questions without touching the config file until you're ready.
Use Cases
- Onboarding — Create the first
nova.config.jsonfor a new or migrated repository. - Metadata refresh — Keep project descriptions, entities, and canonical URLs in sync after ownership changes.
- Normalization — Clean up manually edited entries without hunting for typos in raw JSON.
- Generator support — Feed consistent metadata to Nova generators so docs, README files, and release notes stay accurate.
Requirements
- Node.js runtime — Use any Node.js LTS release with either the installed
novaCLI ornpx. - Project root — Run the command from the directory containing the top-level
package.json(monorepo root included). - Interactive terminal — The session needs to support interactive prompts for the wizard to function.
Usage
You can run this command in two ways:
Options
| Flag | Description |
|---|---|
-d, --dry-run | Run without writing any files. |
-r, --replace-file | Overwrite the existing nova.config.json instead of creating a dated copy. |
-s, --status | Show the read-only GitHub environment status and exit without opening the wizard. |
Read-Only Environment Status
Use --status when you only want to compare the environment declarations with their GitHub Variable and Secret names. This path does not open the wizard and does not write nova.config.json or reconcile any values.
nova utility configure --status
Flow Overview
Without --status, the command loops until you choose Save & Exit or Cancel. You can edit any category multiple times during the same run.
Editing an existing config?
Existing values are pre-filled in each prompt. Press Enter to keep a value, type a new value to replace it, or enter a single space to clear that field.
Project
- Purpose: Edit project display name, slug, short/long descriptions, keywords, legal name, pronouns, supported platforms, starting year, and license in one guided step.
- Nice to know: Slug updates propagate to workspace names for roles that depend on it (
project,docs,config,app,tool) to keep names consistent. Pronouns control first-person wording (we/us/our vs I/me/my), platforms help suggest initial issue fields and badges, and starting year plus license feed the LICENSE generator. - Things to watch: Slug allows only letters, numbers, hyphens, and underscores up to 214 characters; keywords are validated per item (50 characters max); starting year must be an integer ≥ 1970.
Entities
- Purpose: Manage project-related people and organizations with name, email, URL, and roles in a single flow.
- Nice to know: Roles are chosen from the allowed set (author, contributor, supporter) so you don't have to remember labels.
- Things to watch: Emails must be valid (contain
@and a domain); URLs must be validhttp://orhttps://before they're saved.
Emails
- Purpose: Capture a canonical contact for issues/support so tools and metadata can reference a single address.
- Nice to know: Single email field today, kept simple for quick updates.
- Things to watch: Only valid addresses persist; blanks remove the stored email.
URLs
- Purpose: Configure canonical links with validation/normalization before persisting: homepage, repository, bugs, license, logo, docs, npm, docker, funding, privacy policy, and terms of use.
- Nice to know: Repository accepts
git:,git+https:,git+ssh:,git+http:plushttp://,https://; all other URLs arehttp://,https://only. Privacy policy and terms of use URLs appear in generated GitHub issue templates. - Things to watch: Funding sources are entered comma-separated and saved as a list after validation.
README
- Purpose: Select the exact badges and order generated inside Nova's README badges region.
- Nice to know: When
readme.badgeshas never been configured, the wizard suggests badges from the project platforms and available npm, Docker, GitHub, and funding sources. Saving the category writes your choices explicitly, so later generators never guess. - Things to watch: Verified Homebridge status is never inferred. Badges that depend on npm, Docker, GitHub, or funding metadata require the corresponding source field.
Workspaces
- Purpose: List detected workspaces (
package.json) and edit each with role/policy in one place. - Nice to know: Roles (project, config, docs, app, package, tool, template) and policies (freezable, trackable, distributable) are constrained to allowed combinations so you don't accidentally pick an invalid pairing.
- Things to watch: Naming rules enforced by role (config/app/tool require the project-slug prefix when set); distributable workspaces can opt into syncing selected metadata fields.
Environment variables
Environment variables and secrets live in the top-level environment block and are editable in the Environment category below.
Workflows
- Purpose: Manage the list of GitHub Actions workflow templates that the workflow generator reads from at generation time.
- Nice to know: The menu lists existing workflow entries with Edit and Remove actions alongside an Add option and a Back option to return to the category menu. When adding or editing, the wizard prompts for a template, name, runner, optional timeout, trigger filters, build scopes, deployment targets, target ordering, target settings, and workflow settings. A workflow with a Docker Hub or GHCR target also chooses one or both supported container platforms. Existing custom template and target names remain selectable so opening the wizard never replaces or drops them.
- Things to watch:
runsOncurrently offers onlyubuntu-latest. Enter a whole number from1through360fortimeoutMinutes, or leave it blank to preserve each generated job's template timeout. The name must be unique within the same template so the output filenames remain distinct. Upstream choices use another workflow's{template}-{name}key. Multiple upstream choices are alternatives: any one completion can start this workflow; the wizard does not create a wait-for-all chain.
Multiline values
The interactive prompt is single-line. To include line breaks in a setting value (e.g., issue messages with paragraphs), type \n where you want a newline.
The wizard converts \n sequences to actual line breaks when saving. Trigger branch, path, tag, and workflow filters use validated JSON arrays; workflow and target setting maps use validated JSON objects whose values must be strings. These focused inputs keep arbitrary template-specific values editable without leaving the configure flow.
GitHub
- Purpose: Configure GitHub repository settings, policies, issue-template fields, and the GitHub recipes stored under the top-level
recipes.githubblock. - Nice to know: The focused submenu covers repository identity and features, GitHub Actions permissions and allow-lists, ordered labels, every repository policy, the complete default-branch ruleset, security toggles, issue-template fields, and GitHub recipe toggles. Optional booleans include an explicit Unset state, so absence stays different from
false. - Actions and policies: Configure action availability, SHA requirements, selected-action patterns, workflow-token permissions, artifact retention, merge methods and message presentation, auto-merge, update-branch behavior, web signoff, security features, and every supported default-branch protection field without hand-editing JSON.
- Bug report fields: A multiselect chooses the exact semantic fields and order the issue template generator includes, saved under
github.issueTemplate.bugReportFields. When this array has never been configured, the wizard suggests an initial selection fromproject.platformsand configured URLs; saving no choices writes an explicit empty array. - Things to watch: Owner and repository name are required (non-empty) and trimmed before they're saved.
Ignore Files
- Purpose: Manage every physical
.gitignore,.dockerignore, and.assetsignoregenerated by the ignore-files generator. - Nice to know: Add or remove project-relative file paths, select the ordered Nova bundles for each file, and add, edit, or remove its project-owned patterns. On first open, the root
.gitignoreeditor can import entries already beneath the Project Excludes marker. - Things to watch: Paths must begin with
./, end in a supported ignore-file basename, and cannot contain traversal or empty path components..dockerignoreis root-owned and must use exactly./.dockerignore; nested.gitignoreand.assetsignorepaths remain supported. Bundle choices are determined by the physical file type.
Migrating an existing project
If your repository already has a hand-maintained .gitignore, open the Ignore Files category once to import those entries into nova.config.json before regenerating. A regenerate emits only what the config holds, so excludes that were never imported are dropped from the output.
AI Tools
- Purpose: Select which AI tools the agent-conventions generator emits files for, saved under the top-level
agentsfield. Claude Code writesCLAUDE.mdand Codex writesAGENTS.md; both shareVISION.md,PROJECT_RULES.md, andconventions/*.md. - Nice to know: The category is a multiselect that pre-checks whatever is already stored, so reopening it shows your current selection.
- Things to watch: Selecting no tools removes the optional
agentsfield, which disables agent-convention output until a tool is selected again.
Recipes
- Purpose: Configure all GitHub, license, miscellaneous, Nova config, README, and per-workspace
package.jsonrecipes from one category. - Nice to know: Each recipe has an individual
enabledtoggle, includingfix-markdown-tablesandnormalize-order. Generic recipe settings remain editable through a validated prompt, while closed recipes such asremove-operating-system-filespresent only Nova's reviewed platform and file choices. - Things to watch:
package-jsonrecipes are scoped by workspace path. The menu includes registered workspaces plus any existing recipe path, so temporarily unregistered paths are preserved and remain editable. Cleanup recipes do not accept arbitrary paths or patterns.
Environment
- Purpose: Manage the
environmentblock — per-workspace environment values, project-wide keys, and their namespace prefixes — without editingnova.config.jsonby hand. - Nice to know: Each value has a required
reach:localstays on the developer machine,managedis tracked locally and on GitHub but delivered nowhere,buildis injected into CI builds, andruntimeis reconciled to deployed servers.managed,build, andruntimevalues also requiresecretto choose GitHub Secret or Variable storage. The wizard can add the repo root./workspace alongside the others, bringing its.envunder management. - Things to watch: Removing a value is confirm-gated and offers to drop its local
.envline as well. Every namespace — theprojectgroup, each workspace (including the root./), and each workflow — requires a non-emptyprefixbefore it can be saved. On exit, the section can check GitHub status and reconcile — stubbing missing keys and deleting stale ones through theghCLI — so Nova manages key names and existence only, never their values.
Settings
- Purpose: Select the project's release strategy, lock-step versioning behavior, per-script workspace concurrency, verified local cache settings, and whether the root runs as part of the workspace tree.
- Nice to know: With no release history or pending changelog entries, you can revisit this category and change SemVer (
major.minor.patch) to CalVer (YYYY.M.MICRO) or back. On save, Nova migrates every workspace version, exact internal version pin, AndroidversionName, and authoritative AppleMARKETING_VERSIONtogether; freezable workspaces remain0.0.0. Workspace limits, lock-step versioning, and every cache setting remain editable independently at any time. - Things to watch: A pending
.changelog/*.mdentry blocks a strategy switch so its release meaning cannot change underneath it. Once the root or any non-freezable workspace changelog contains a release heading, Nova detects that history and makes only the version strategy read-only. A configured mismatch, mixed strategies, or an unsupported numeric heading stops configuration and identifies the affected changelog.
Saving and Canceling
- Choosing Save & Exit writes to a file called
nova.config.json. - Choosing Cancel exits immediately without persisting changes and prints a debug log.
Output Example
{
"project": {
"name": {
"slug": "example",
"title": "Example"
},
"description": {
"short": "A Nova-powered JavaScript toolkit."
},
"keywords": ["example", "nova", "tooling"],
"legalName": "Example Author LLC",
"pronouns": "business",
"platforms": ["nodejs", "linux", "windows"],
"startingYear": 2025,
"license": "MIT"
},
"entities": [
{
"name": "Example Author",
"email": "[email protected]",
"url": "https://example.com/author",
"roles": ["author"]
}
],
"emails": {
"bugs": "[email protected]"
},
"github": {
"owner": "example",
"repo": "example-project",
"topics": ["nova", "tooling"],
"features": {
"issues": true,
"wiki": false,
"projects": false,
"discussions": false,
"sponsorships": true
},
"policies": {
"visibility": "public",
"defaultBranch": "main",
"mergeMethods": {
"merge": false,
"squash": true,
"rebase": false
},
"autoDeleteHeadBranch": true
},
"issueTemplate": {
"bugReportFields": ["nodejs", "screenshots"]
}
},
"urls": {
"homepage": "https://example.com",
"repository": "https://github.com/example/example-project",
"bugs": "https://github.com/example/example-project/issues",
"license": "https://github.com/example/example-project/blob/main/LICENSE",
"logo": "https://example.com/assets/logo.svg",
"documentation": "https://docs.example.com/project",
"npm": "https://www.npmjs.com/package/example-project",
"docker": "https://hub.docker.com/r/example/example-project",
"fundSources": ["https://github.com/sponsors/example"],
"privacyPolicy": "https://example.com/privacy",
"termsOfUse": "https://example.com/terms"
},
"readme": {
"badges": [
"npm-version",
"npm-downloads",
"docker-pulls",
"docker-image-size",
"github-release",
"github-top-language",
"github-license",
"funding"
]
},
"workspaces": {
"./": {
"name": "example-project",
"role": "project",
"policy": "freezable"
},
"./apps/docs": {
"name": "example-docs",
"role": "docs",
"policy": "freezable"
},
"./packages/nova": {
"name": "@company/example",
"role": "package",
"policy": "distributable"
}
},
"workflows": [
{
"template": "lock-inactive-issues",
"name": "project",
"triggers": ["schedule-weekly"]
},
{
"template": "publish",
"name": "project",
"triggers": ["release"],
"build": ["./packages/nova"],
"deploy": [
{
"to": "npm",
"path": "./packages/nova"
}
],
"with": {
"NPM_TOKEN": "NPM_TOKEN"
}
}
],
"ignoreFiles": {
"./.gitignore": {
"bundles": ["nova"],
"patterns": [".local/", "scratch/"]
}
},
"agents": ["claude-code", "codex"],
"recipes": {
"github": {
"sync-actions": { "enabled": false },
"sync-features": { "enabled": true },
"sync-identity": { "enabled": true },
"sync-labels": { "enabled": false },
"sync-policies": { "enabled": true },
"sync-rulesets": { "enabled": false },
"sync-security": { "enabled": false }
},
"license": {
"update-copyright": { "enabled": true }
},
"miscellaneous": {
"fix-markdown-tables": { "enabled": true }
},
"nova-config": {
"normalize-order": { "enabled": true }
},
"read-me": {
"update-badges": { "enabled": true },
"update-credits": { "enabled": true }
},
"package-json": {
"./": {
"cleanup": {
"enabled": true,
"settings": {
"removeUnknownKeys": true,
"reorderKeys": true
}
},
"normalize-dependencies": {
"enabled": true,
"settings": {
"pinDependencyVersions": true,
"pinDevDependencyVersions": true
}
}
},
"./packages/nova": {
"sync-identity": {
"enabled": true,
"settings": {
"description": true,
"keywords": true,
"displayName": true
}
}
}
}
},
"environment": {
"project": {
"prefix": "EXAMPLE_",
"variables": [
{ "key": "NPM_TOKEN", "reach": "managed", "secret": true }
]
},
"workspaces": {
"./": {
"prefix": "ROOT_"
},
"./apps/docs": {
"prefix": "DOCS_",
"variables": [
{ "key": "LOCAL_API_MOCK", "reach": "local", "defaultValue": "http://127.0.0.1:8787" },
{ "key": "SENTRY_PROJECT", "reach": "managed", "secret": false },
{ "key": "PUBLIC_SITE_URL", "reach": "build", "secret": false, "defaultValue": "https://docs.example.com" },
{ "key": "STRIPE_SECRET_KEY", "reach": "runtime", "secret": true }
]
}
},
"workflows": {
"project": {
"prefix": "PUBLISH_"
}
}
},
"settings": {
"lockStepVersioning": false,
"runWorkspaces": {
"cache": {
"directory": "./node_modules/.cache/nova/run-workspaces",
"enabled": true,
"scripts": ["build", "check"]
},
"concurrency": {
"build": 2,
"check": 2,
"deploy": 2
}
},
"versionStrategy": "semver"
}
}
Troubleshooting
- "Must be run inside the project root directory." — Verify you execute the command where the project root
package.jsonresides. App or package folders inside monorepos are not allowed. - Validation loops keep reappearing — Fix the highlighted email or URL before continuing. To drop the value, enter a single space and press Enter.
- No file was created — Confirm that
nova.config.jsonis writable and that--dry-runwas not passed or Cancel was not chosen.