Local CLI
The nucleo CLI runs on the developer's computer and talks to a remote Nucleo site, without holding any site logic.
On this page
01Overview
@nucleo/cli is a Node package with a single executable, nucleo. It is not WP-CLI: the wp nucleo … commands are described separately.
The CLI holds no site logic. Every command that touches the site calls Nucleo's abilities through the WordPress Abilities API (/wp-json/wp-abilities/v1/abilities/<name>/run), with a user and an Application Password.
The pull and push commands keep the site in a local folder of JSON files. Other commands do local work that the server cannot do: screenshots and CSS coverage with Playwright, token analysis of an HTML file, scaffolding and checking of component plugins.
nucleo mcp exposes the site's MCP server as a STDIO process, for MCP clients that do not speak HTTP.
The CLI code does not check the edition. The edition matters only on the site side: a command that calls a Pro ability fails with HTTP 404 if the site does not have an active Pro license.
02Requirements and installation
Requirements
What it does: lists what is needed to run the CLI.
How to use it: check the version with node --version.
Parameters: none.
Permissions: the site needs a WordPress user with an Application Password. The capabilities required depend on the command: see each command.
Edition: Free
Known limits:
- Node 20 or later. The package is an ES module.
- No mandatory dependencies.
- Playwright is optional. It is needed only for
screenshotandcritical, with the Chromium browser. - The site needs the Nucleo plugin active. The plugin requires WordPress 6.9 or later, the version with the Abilities API that the CLI uses.
icons adddownloads icons fromhttps://api.iconify.design: it needs Internet access.component checkusesphp,phpcs,phpstanandphpunitinstalled locally.
Installation
What it does: makes the nucleo command available.
How to use it: the package is not published on npm: as of 30 October 2026, npm view @nucleo/cli returns 404. There are three ways to install it.
Option 1, release package. The release build creates the file nucleo-cli-<version>.tgz. The file is attached to the GitHub release of the tag v<version>, together with the Free zip and the theme. Install it with npm:
npm i -g ./nucleo-cli-0.2.0.tgz
The bin field of the package creates the nucleo command. The package contains only bin/, src/ and README.md.
Option 2, from the repository. In cli/ run npm link: npm links the nucleo command to the executable in the repository.
Option 3, without installing. Run node cli/bin/nucleo.js <command> from the repository root.
Parameters: none.
Permissions: with -g npm writes to the global package folder.
Edition: Free. The GitHub release contains the CLI together with the Free plugin.
Known limits: none found.
Installing Playwright
What it does: enables screenshot and critical.
How to use it: in the site's project folder:
npm i -D playwright && npx playwright install chromium
The CLI first looks for Playwright next to itself. Then it looks for node_modules/playwright in the working folder and in the first parent folder that contains a package.json. It does not go further up.
Parameters: none.
Permissions: none.
Edition: Free
Known limits: there are three error messages. Each one gives the command to run:
- Playwright missing:
Playwright is not installed. … In the project folder run: npm i -D playwright && npx playwright install chromium. - Chromium missing:
Playwright is installed but Chromium is missing. Run: npx playwright install chromium. - System libraries missing:
Chromium cannot start: system libraries are missing. Run: sudo npx playwright install-deps chromium.
03Configuration and common mechanisms
Connecting to the site
What it does: sets site, user and password for the commands that call the site.
How to use it: three sources, in order of priority: command-line options, environment variables, and the file nucleo.config.json in the current folder.
{
"site": "https://esempio.it",
"user": "marco",
"password": "abcd efgh ijkl mnop qrst uvwx",
"componentsPath": "../wordpress/wp-content/plugins"
}Parameters:
| Name | Type | Allowed values | Default | Notes |
|---|---|---|---|---|
--site / NUCLEO_SITE / site | string | URL http: or https: | none | Required. The CLI removes trailing slashes. |
--user / NUCLEO_USER / user | string | WordPress login | none | Required. |
--password / NUCLEO_APP_PASSWORD / password | string | WordPress Application Password | none | Required. Sent with Basic auth. |
componentsPath (file only) | string | path | none | wp-content/plugins folder of the local WordPress, for component deploy. Relative to the current folder. |
Permissions: authentication is a WordPress Application Password, not OAuth. The CLI does not handle OAuth tokens. Without an OAuth token the site does not check scopes: only the user's capabilities count.
Edition: Free
The password in the file nucleo.config.json stays in plain text. The CLI does not protect it.
Known limits:
- Errors:
Missing site: use --site URL or NUCLEO_SITE,Invalid site URL: …,Invalid site URL (http or https required): …,Missing user: use --user or NUCLEO_USER,Missing Application Password: use --password or NUCLEO_APP_PASSWORD,nucleo.config.json is not valid JSON: …. - The CLI reads the configuration only when a command calls the site.
tokens suggest,screenshot,component newandcomponent checkwork without it.
Calls to abilities
What it does: sends the calls to the site's abilities.
How to use it: read abilities go with GET and the query input[key]=value, with nested objects in square brackets. Write abilities go with POST and the body {"input": {...}}. Every request carries Authorization: Basic … and Accept: application/json.
Parameters: none.
Permissions: those of each ability.
Edition: Free
Known limits:
- HTTP 401 or 403:
<ability>: accesso negato (HTTP <status>). Controlla utente e Application Password. - HTTP 404:
<ability>: ability not found (HTTP 404). Is Nucleo active on this site?. The same message appears when the ability is Pro and the site has no license: Pro abilities are not registered. - Other statuses:
<ability>: <message>with the site's message, orHTTP <status>. - Network:
Connection to <site> failed: …. - Site rate limit: 60 writes every 60 seconds per user and scope group (filter
nucleo/rate_limit). The response isok: falsewitherror.coderate_limited. Only the calls tocontent-list,terms-setandcontent-upsertmade bypullandpushretry: they waitretryAfterseconds (10 if missing), up to 5 times. The other calls report the error.
Command line, output and exit codes
What it does: parses arguments and options with the same rule for all commands.
How to use it: nucleo <command> [arguments] [--option value | --option=value | --flag].
Parameters: boolean options, without a value: --dry-run, --prune, --yes, --help, --version, --no-push, --use-tokens. All others require a value. Boolean options also accept =true or =1 and =false or =0; any other value gives an error.
Permissions: none.
Edition: Free
Known limits:
- An option with a value followed by nothing, or by another
--option, givesMissing value for --<name>.--alone givesInvalid option: --. - An option that the command does not accept gives
Unknown option: --<name>. Use "nucleo help"., before any call to the site. - Exit code: 0 if the command succeeds, 1 for usage errors, site errors or failed steps.
component deployexits with 2 if it copies the plugin but does not activate it. Errors go to stderr with the prefixnucleo:. - An unknown command gives
Unknown command: <name>. Use "nucleo help". - Messages are partly in Italian and partly in English.
04General commands
nucleo help
What it does: prints the list of commands and configuration options, in English. It also lists --urls and --no-push of critical.
How to use it: nucleo help, nucleo --help or nucleo without arguments. --help works with any command and always prints the same general text.
Parameters: none.
Permissions: none.
Edition: Free
Known limits: none found.
nucleo --version
What it does: prints the package version (0.2.0 at this commit).
How to use it: nucleo --version.
Parameters: none.
Permissions: none.
Edition: Free
Known limits: none found.
nucleo guide
What it does: reads the phased guide from the site and prints it as text. Without a phase, the site chooses the first phase not completed.
How to use it: nucleo guide [phase] [--design PATH]. Calls nucleo/guide with GET. The phases are described in the phased guide.
Parameters:
| Name | Type | Allowed values | Default | Notes |
|---|---|---|---|---|
phase (positional) | integer | 0–4 | phase chosen by the site | Out of range: Usage: nucleo guide [0-4] [--design PATH] |
--design | string | up to 500 characters (ability schema) | none | The site replaces <design.html> in the guide texts with this value. |
Permissions: edit_posts. OAuth scope of the ability: nucleo:read.
Edition: Free
Known limits: output on fixed lines: Phase N: <title>, State: tokens … · sections … · layouts … · menus … · post types … · documents …. Then, if present, Checks: (counts per type), Distinct: (list), Coverage: N of M documents read, then the sections Basics: (in every call, except phase 0), To do:, Rules: (with tools:), Exit: and Next:. Empty sections do not appear. A response with ok: false becomes an error with the site's message.
05Site sync
nucleo pull
What it does: downloads the site into a local folder. First it writes the files of nucleo/site-export. Then it downloads the items of the content types into content/<type>/<slug>.json and the terms into terms/<taxonomy>.json. Every item and every term gets the key base: the fingerprint of the site version, which push uses to recognize changes made on the site after the pull.
How to use it: nucleo pull [folder] [--prune]. Calls, in order:
nucleo/site-export, which writes the export files.nucleo/content-listwithperPage: 1for the list of types. Then, for each type, withtype,full: true,perPage: 50andpage, up to the last page.nucleo/terms-getwithout input for the list of taxonomies. Then withtaxonomyfor each one.
Parameters:
| Name | Type | Allowed values | Default | Notes |
|---|---|---|---|---|
folder (positional) | path | any | nucleo-site | Relative to the current folder. |
--prune | flag | — | absent | Deletes the files content/<type>/<slug>.json that are absent on the site, and removes from terms/<taxonomy>.json the terms absent on the site. Moves to the backup copy the .json files in pages/, posts/, layouts/, sections/ and menus/ absent from the export. |
--only | list | FILE[,FILE] | absent | See nucleo pull --only below. |
Permissions: manage_options for site-export (scope nucleo:admin). edit_posts on the type for content-list (scope nucleo:read). edit_posts, plus assign_terms of the taxonomy, for terms-get (scope nucleo:read).
Edition: Free
Known limits:
- It downloads only the types with
modeled: truein thecontent-listresponse, and those with a localcontent/<type>/folder. The same applies to taxonomies with a localterms/<taxonomy>.json. - Items with
managedByare not written. Items skipped by the server become warnings and their local file is not deleted. - A
content-listorterms-getthat is absent (HTTP 404) is not an error: the related part is skipped. - Without
--prune, a local term absent on the site stays in the file. A local file absent on the site is listed aslocal only: …. A document ofpages/,posts/,layouts/,sections/ormenus/absent from the export is listed asno longer on the site: …: a later push would create it again. - An absolute path,
..,., empty segments or\in the site's response gives an error before writing. - Before overwriting or deleting, it copies each local file with different content to
<folder>/.nucleo-backup/<date-time>/<path>. The date-time is the ISO one with-instead of:and.. - Output:
Wrote N files in <folder>, thenlocal backup: …,removed: …andlocal only: …on stdout. Warningswarning: …go to stderr, including menu items skipped bysite-export.
nucleo pull --only
What it does: downloads only some files of nucleo/site-export and updates in site.json only their base. It is used to resolve a conflict by keeping the site's version.
How to use it: nucleo pull [folder] --only pages/home.json,menus/principale.json. Calls only nucleo/site-export.
Parameters:
| Name | Type | Allowed values | Default | Notes |
|---|---|---|---|---|
--only | comma-separated list | paths present in site-export | — | Empty entries are discarded. Empty list: Usage: --only FILE[,FILE] |
Permissions: manage_options (scope nucleo:admin).
Edition: Free
Known limits:
- It rejects paths in
content/andterms/:--only non accetta <file>: content/ e terms/ si scaricano con nucleo pull senza --only. - It rejects a path absent from the export:
<file> non è tra i file di nucleo/site-export. - It does not download
content/andterms/, and it ignores--prune. - A local file that differs from the site's file is first copied to
<folder>/.nucleo-backup/<date-time>/<path>. The output reports it withlocal backup: <path>. - With
site.jsonin the list, the written file keeps thebaseof the localsite.json. - Reads happen before any write: an error does not leave half-written files.
nucleo push
What it does: sends the local folder to the site. Order: images in media/, terms in terms/, items in content/, then all other .json files with nucleo/site-import. Before uploading images or sending data it runs the same push as a dry run: if the site finds errors, the command stops without changing anything. After each accepted batch of content/ or terms/ it writes the base of the items and terms of that batch, even if the push fails later; after a successful push it updates base, tokensBase and siteBase in site.json.
How to use it: nucleo push [folder] [--dry-run] [--prune [--yes]] [--use-tokens] [--acknowledge FILE] [--force FILE[,FILE]]. Calls, in order:
nucleo/media-uploadfor each image.jpg,.jpeg,.png,.webp,.gifand.avifinmedia/(not recursive). It updatesmedia/manifest.jsonwithfile,url,altandsha1.nucleo/terms-setper taxonomy, in batches of 500 terms, parents before children.nucleo/content-upsertper type, in batches of 25 items. Types cited by others (<type>:<slug>infields) go first.- With
--prune:nucleo/content-listwithperPage: 100for each type with a local folder. With--yes:content-upsertwithstatus: "trash". nucleo/site-importwithfiles(all.jsonoutsidecontent/,terms/and.nucleo-backup/),dryRunand, if present,pending,acknowledgeandforce.
Parameters:
| Name | Type | Allowed values | Default | Notes |
|---|---|---|---|---|
folder (positional) | path | any | nucleo-site | Relative to the current folder. |
--dry-run | flag | — | absent | Does not upload images. Sends dryRun: true to terms-set, content-upsert and site-import: the site validates without saving. Images not uploaded enter the manifest with the URL https://media.invalid/<file>. |
--prune | flag | — | absent | Lists the site items absent in content/<type>/ as prune: <type>/<slug>. |
--yes | flag | — | absent | With --prune, moves the listed items to the trash. |
--use-tokens | flag | — | absent | See nucleo push --use-tokens below. |
--acknowledge | path | JSON file | absent | See nucleo push --acknowledge below. |
--force | comma-separated list | paths sent to site-import, files in content/ and terms/ | absent | Overwrites the site's version in case of conflict. Files in content/ and terms/ are sent without base. Another path not sent gives the warning force ignored: …. |
Permissions: upload_files for media-upload (scope nucleo:write). manage_terms of the taxonomy for terms-set (scope nucleo:write). edit_posts for content-upsert (scope nucleo:write). manage_options for site-import (scope nucleo:admin). edit_posts on the type for content-list.
Edition: Free
Known limits:
- Output on stdout:
media: <file> → <url> (id N), or(id N, already present)or(dry run). Thencreated: N,updated: N,unchanged: N(documents identical to the site ones, if greater than 0),content unchanged: N(items ofcontent/and terms ofterms/identical to the site ones, if greater than 0),trashed: N(if greater than 0) anderrors: N. Each error goes to stderr as- <file>: <message> (<code>). - Exit code 1 if there is at least one error.
- With
quality_blockingerrors it prints:Blocking issues: fix them, or ask the user to accept them and pass the file with --acknowledge FILE. - For each
conflictit prints:Conflict: keep the site version with nucleo pull --only <file>, or overwrite it with nucleo push --force <file>.For a file incontent/orterms/the suggestion isnucleo pull, without--only, which rejects them. - An item or a term changed on the site after the pull (different
base) givesconflictand is not written. To keep the site version runnucleo pull; to overwrite it,--forcewith the file. - A failed upload stops the push before
site-import. The items already uploaded stay in the manifest. - Local errors in
content/andterms/stop the push before anything is sent, withContenuti non validi: <file>: <message>. Codes:invalid_json,invalid_value,slug_mismatch(slugfield different from the file name),type_mismatch(typefield different from the folder) andduplicate(same slug inpages/orposts/for the typespageandpost). --prunedoes not touch items withprotected: true, those withmanagedByand the terms. Without--yesit prints(add --yes to trash them).- Invalid JSON outside
content/andterms/,media/manifest.jsonincluded, stops the command before anything is sent:Invalid JSON in <file>: …. - If
site-importrespondsok: false, for examplerate_limitedafter 5 retries, the command exits with 1 and the site's message. - If the preliminary dry-run finds errors, it prints
no changes to the site: the site is not touched. - A missing folder gives
Folder not found: <folder>.
nucleo push --use-tokens
What it does: before sending, it replaces in the local documents the style values equal to a token with the reference $group.key.
How to use it: nucleo push [folder] --use-tokens [--dry-run]. Calls nucleo/tokens-get. The tokens of site.json take precedence over those of the site.
Without --dry-run the files stay modified even if the push fails afterwards.
Parameters: nothing beyond the flag. With --dry-run it counts the replacements, does not change the files and validates the versions with the tokens replaced, like the real push.
Permissions: edit_posts (scope nucleo:read), plus the permissions of push.
Edition: Free
Known limits:
- It applies to
.jsonfiles with arootobject, outsidecontent/,terms/andmedia/. It visitsstyleof each node and its children, including the values per breakpoint. - Groups and properties:
color(color,background,accentColor,dotColorand other keys of the inner parts),space(padding,margin,gap,controlsInset…),radius(borderRadius…),shadow(boxShadow),font(fontFamily,numberFont). The state keys…Hoverand…Currentuse the group of the base key. - The comparison is exact after normalization: lowercase, spaces,
#abc→#aabbcc,px→rem(16 px = 1 rem). A value only close to a token stays unchanged.0and$…references are not replaced. With several equal tokens the first one wins. - Output:
tokens: <file> <n>per file andtokens: N replacements.
nucleo push --acknowledge
What it does: sends to site-import a person's consents on blocking quality reports (quality_blocking).
How to use it: nucleo push nucleo-site --acknowledge consensi.json. The file has this form:
{
"pages/home.json": [
{ "rule": "a11y.contrast.low", "node": "cta", "reason": "Consenso di Marco, 27/10" }
]
}The CLI shows each acknowledgement (Acknowledgement: <file> <rule> @<node>, reason: …) and asks Confirm? [y/N]. It accepts y, yes, s, si or sì. It sends only the confirmed acknowledgements.
Parameters: --acknowledge, path of the file, relative to the current folder.
Permissions: those of push.
Edition: Free
Known limits:
- Without an interactive terminal (agent, CI, pipe) the command refuses:
--acknowledge needs an interactive terminal: a person confirms each acknowledgement. …. - Each entry requires
rule,nodeandreasonas non-empty strings. Otherwise:<file>: <path> deve essere { "percorso.json": [{ "rule", "node", "reason" }] } con reason non vuoto. - Missing file:
Acknowledgement file not found: …. Invalid JSON:Invalid JSON in …. - A consent on a file not sent to
site-import, including incontent/orterms/, gives the warningacknowledgement ignored: …. - The consents file inside the site folder is not sent to
site-import.
06Design and media
nucleo tokens suggest
What it does: reads the CSS of a design HTML file and proposes tokens for nucleo/tokens-set. It writes no files and does not call the site.
How to use it: nucleo tokens suggest design.html > tokens.json. On stdout it prints only {"tokens": …}. On stderr it prints the evidence: <group>.<key>: <value> (<occurrences>) from <variable> and no token: <type> <value> (<occurrences>).
Parameters:
| Name | Type | Allowed values | Default | Notes |
|---|---|---|---|---|
<design.html> (positional) | path | HTML file | — | Required. Otherwise: Usage: nucleo tokens suggest <design.html> |
Permissions: none.
Edition: Free
Known limits:
- It reads
<style>blocks andstyleattributes. It removes<script>first. It ignores@font-face. Definitions outside@media,@supportsand@containerwin. - A value becomes a token only if it appears at least 3 times.
- With at least 3 CSS variables defined in the file, it replaces
var(--name)with the value and ignores the rules without variables whose classes do not appear in the markup. - Product groups:
color(primary,secondary,accent,background,text,surface,border,muted, chosen by lightness and saturation),font(body,heading),space(keys 1–16 by proximity),text(xs–6xl),radius(sm,md,lg,full),shadow(sm,md,lg). Durations always end inno token. - These do not become tokens:
unset,inherit,initial,revert,revert-layer,none,normal, unresolved values withvar(, and values with;{}<>\.
nucleo media upload
What it does: uploads one or more files to the site's media library.
How to use it: nucleo media upload foto1.jpg foto2.png [--alt TEXT]. Calls nucleo/media-upload for each file, with file (base name), data (base64) and alt.
Parameters:
| Name | Type | Allowed values | Default | Notes |
|---|---|---|---|---|
<file...> (positional) | paths | one or more | — | Required. Otherwise: Usage: nucleo media upload <file...> [--alt TEXT] |
--alt | string | any | "" | Same alternative text for all files. |
Permissions: upload_files (scope nucleo:write).
Edition: Free
Known limits:
- The site accepts JPEG, PNG, WebP, GIF and AVIF.
- Output:
<file> → <url> (id N), or(already present)for a file already in the library. A failed file goes to stderr and does not stop the others. Code 1 if at least one fails. - No retry after
rate_limited.
nucleo icons import
What it does: uploads the .svg files of a folder as site icons.
How to use it: nucleo icons import ./icone [--prefix P]. Calls nucleo/icons-set with { set: { name: svg } }, in batches of 50.
Parameters:
| Name | Type | Allowed values | Default | Notes |
|---|---|---|---|---|
<folder> (positional) | path | a folder | — | Not recursive. |
--prefix | string | any | "" | Prepended to the name. |
Permissions: manage_options (scope nucleo:admin).
Edition: Free
Known limits:
- Icon name: prefix plus the file name without extension, in lowercase, with the sequences outside
a-z0-9replaced by-. A name that does not start with a letter is skipped with a warning. - Without valid files:
nessun file SVG con nome valido in <folder>, code 1. - A failed batch does not stop the others. Output:
site icons: N.
nucleo icons add
What it does: downloads icons from Iconify and uploads them as site icons.
How to use it: nucleo icons add mdi:car lucide:truck or nucleo icons add mdi:car --as auto. It downloads https://api.iconify.design/<prefix>/<name>.svg, then calls nucleo/icons-set.
Parameters:
| Name | Type | Allowed values | Default | Notes |
|---|---|---|---|---|
<prefix:name...> | strings | format prefix:name | — | Other format: formato atteso prefisso:nome |
--as | string | any | Iconify icon name | Only with one icon. With several icons: --as vale solo con una icona. |
Permissions: manage_options (scope nucleo:admin).
Edition: Free
Known limits: an icon with an HTTP status other than 200, or with a response that does not start with <svg, gives an error and does not stop the others. Code 1 if at least one fails. The name sent does not go through the normalization of icons import.
nucleo icons remove
What it does: removes site icons.
How to use it: nucleo icons remove auto camion. Calls nucleo/icons-set with { remove: [...] }.
Parameters: <name...>, one or more names.
Permissions: manage_options (scope nucleo:admin).
Edition: Free
Known limits: output site icons: N. An ability error goes to stderr and gives code 1.
nucleo icons list
What it does: prints the site icons on one line and the built-in icons on a second line.
How to use it: nucleo icons list. Calls nucleo/icons-set with empty input, with POST.
Parameters: none.
Permissions: manage_options (scope nucleo:admin).
Edition: Free
Known limits: the call is a write for the site and counts toward the limit of 60 writes per minute. An invalid subcommand gives the usage Usage: nucleo icons import <folder> [--prefix P] | add <prefix:name...> [--as NAME] | remove <name...> | list.
07Local browser (Playwright)
nucleo screenshot
What it does: takes full-page screenshots of a URL at several widths. It does not call the site's abilities.
How to use it: nucleo screenshot https://esempio.it/chi-siamo/ [--out folder] [--widths 390,768,1440]. It requires Playwright with Chromium.
Parameters:
| Name | Type | Allowed values | Default | Notes |
|---|---|---|---|---|
<url> (positional) | URL | http: or https: | — | Errors: Missing URL: …, Invalid URL: …, Invalid URL (http or https required): … |
--out | path | any | screenshots | Created if missing. |
--widths | comma-separated list | integers from 240 to 3840 | 390,820,1440,2560 | Duplicates discarded. Error: Invalid width: … |
Permissions: none on the site. The CLI does not send credentials to the page.
Edition: Free
Known limits:
- Viewport height 900 px. It waits for
networkidlebefore the shot. - File name:
<host-path>-<width>.png, with the characters outsidea-z0-9replaced by-(homeif empty). It prints one path per line. - A page reserved for logged-in users shows the public version: Playwright does not receive the user's cookies.
nucleo critical
What it does: for each template it opens the URL with Chromium at four viewport widths (390, 820, 1440 and 2560 px), collects the CSS rules that match at least one visible element in the first screen, and writes the merged result to <folder>/<template>.css. Without --no-push it sends the CSS as the template's critical CSS.
How to use it:
nucleo critical --urls home=https://esempio.it/,page=https://esempio.it/chi-siamo/ [--out folder] [--no-push]nucleo critical [--out folder] [--no-push]: without--urlsit reads theurlsmap (template → URL) ofnucleo/assets-report.
For each CSS it calls nucleo/critical-set with template and css.
Parameters:
| Name | Type | Allowed values | Default | Notes |
|---|---|---|---|---|
--urls | comma-separated list of template=url | template=url pairs | absent | Each pair is split at the first =: URLs with a query stay intact. A pair without =, without a template or without a URL gives a usage error. |
--out | path | any | critical | Created if missing. |
--no-push | flag | — | absent | Writes the files and does not call critical-set. |
Permissions: manage_options for assets-report (scope nucleo:read). edit_theme_options for critical-set (scope nucleo:design). The site configuration is required even with --urls --no-push.
Edition: with --urls Free. Without --urls Pro, because nucleo/assets-report requires a Pro license. Without a license the command writes nucleo: nucleo/assets-report not found. Without --urls, critical needs Nucleo Pro with an active licence. and exits with 1.
Known limits:
- Without
--urlsit uses theurlsmap of the report. Entries without an absolute URL go to stderr asno URL in the report for template "<name>", skipped. If no URL is left:nucleo: no URL to analyse. Run the asset audit or pass --urls template=URL., with code 1. - Each template is measured at four viewports (390×844, 820×1180, 1440×900, 2560×1440). The rules are merged without duplicates, in order of first appearance.
- The CSS contains only the rules that match at least one visible element in the first screen. Stylesheets from another origin cannot be read and are skipped.
- The CLI caps the CSS at 50 KB: the merge stops at the first rule that would exceed the limit, without an error. The site still rejects a CSS larger than 50 KB (
The critical CSS exceeds the 50 KB limit.): the local file stays written and the command stops at the firstok: falseresult ofcritical-set, with the site's message. - File name: the template with the characters outside
A-Za-z0-9._-replaced by-.
08MCP
nucleo mcp
What it does: acts as a proxy between STDIO and the site's HTTP MCP server (POST <site>/wp-json/nucleo/v1/mcp). It serves MCP clients that start a local process.
How to use it: nucleo mcp with NUCLEO_SITE, NUCLEO_USER and NUCLEO_APP_PASSWORD in the environment of the MCP client. Each stdin line is a JSON-RPC message. Each response goes to stdout on one line.
Parameters: nothing beyond the site configuration.
Permissions: logged-in user via Application Password. Each ability called checks its own capability. OAuth scopes do not apply.
Edition: Free. Pro abilities appear only if the site has a license.
Known limits:
- Requests are processed in sequence, one at a time.
- Notifications, that is messages without
id, produce no output. An error on a notification goes to stderr. - Invalid JSON: response
-32700 Parse error. HTTP error or empty response: response-32000with the message. - The CLI forwards the
Mcp-Session-Idheader if the server sends it. The Nucleo server at this commit does not send it. - The process ends with code 0 when stdin closes.
09Components
nucleo component new
What it does: creates a component (data source, action or block) in a local components plugin. If the plugin is missing, it also creates the skeleton.
How to use it: nucleo component new <data-source|action|block> <name> [--dir FOLDER] [--vendor PREFIX]. It does not call the site.
Parameters:
| Name | Type | Allowed values | Default | Notes |
|---|---|---|---|---|
<kind> | string | data-source, action, block | — | Other value: Invalid kind: … |
<name> | string | ^[a-z][a-z0-9-]{1,40}$ | — | Error: Invalid name: … |
--dir | path | any | nucleo-components | The folder name is the plugin slug. |
--vendor | string | ^[a-z][a-z0-9-]{0,39}$ | from the folder name: nucleo-acme-components becomes acme, nucleo-components becomes site | Error: Invalid vendor: … |
Permissions: none on the site.
Edition: Free
Known limits:
- Plugin skeleton:
<slug>.phpwith the headerNucleo Components: <vendor>,composer.json,phpunit.xml,phpstan.neon,phpcs.xml.distandtests/bootstrap.php. - Component files:
src/DataSources/<Class>.php,src/Actions/<Class>.php, orblocks/<name>/block.nucleo.jsonwithsrc/Blocks/<Class>Renderer.php. Always a test intests/<Class>Test.php. The registered name is<vendor>/<name>. - If an expected file already exists, it writes nothing:
File già esistente: … Nessun file scritto. - It prints the written paths, one per line.
nucleo component check
What it does: runs php -l on the plugin's PHP files, then phpcs, phpstan and phpunit. A failed step does not stop the others.
How to use it: nucleo component check [--dir FOLDER]. It does not call the site.
Parameters:
| Name | Type | Allowed values | Default | Notes |
|---|---|---|---|---|
--dir | path | any | nucleo-components | Must contain <slug>.php. |
NUCLEO_TOOLS (variable) | path | folder | absent | Alternative folder for phpcs, phpstan and phpunit. |
Permissions: none on the site.
Edition: Free
Known limits:
- Tool lookup:
<plugin>/vendor/bin/<tool>, thenNUCLEO_TOOLS/<tool>, then the name in thePATH. - Fixed arguments:
phpcs --standard=phpcs.xml.dist,phpstan analyse --no-progress --memory-limit=1G -c phpstan.neon,phpunit -c phpunit.xml. - Output:
<step>: ok|fail|missingand the output of the step if it is notok. Code 1 if a step is notok. - Missing plugin:
Plugin not found in <dir>: <slug>.php is missing. Create it with "nucleo component new".
nucleo component deploy
What it does: checks the plugin, copies it into the plugins folder of a local WordPress and activates it. The copy is local: no HTTP request carries PHP code.
How to use it: nucleo component deploy [--dir FOLDER] [--plugins PATH]. Steps:
- Calls
nucleo/site-describeand readsenvironment. It proceeds only withlocalordevelopment. - Runs
component check. If a step is notok, it copies nothing. - Copies the folder to a temporary folder next to the destination, without hidden files,
vendor,node_modules,tests,phpunit.xml,phpstan.neon,phpcs.xml.distandcomposer.lock. At the end it replaces the destination. If the copy fails, the previous version stays. - Calls
nucleo/component-activatewithplugin: <slug>.
Parameters:
| Name | Type | Allowed values | Default | Notes |
|---|---|---|---|---|
--dir | path | slug ^[a-z0-9][a-z0-9-]{0,60}$ as folder name | nucleo-components | |
--plugins | path | wp-content/plugins folder | componentsPath of nucleo.config.json | With neither: componentsPath mancante: … |
Permissions: edit_posts for site-describe (scope nucleo:read). activate_plugins for component-activate (scope nucleo:admin). Writing to the file system of the plugins folder.
Edition: Free
Known limits:
- With
staging,productionor a missing environment it prints the human step and exits with 1: the component arrives with the site migration or with the deploy via git. - It does not overwrite an existing destination without the line
Nucleo Components:in the first 8 KB of the main file. It refuses a source and a destination that coincide or contain each other, also through symbolic links: it copies nothing and exits with 1. - If the site answers
not_foundafter the copy,componentsPathis not the plugins folder of the linked site: message and exit with 1. - Other activation errors: the copy stays, the command prints
activate <slug> from Plugins (<error>)and exits with 2. - Success output:
copied N files to <destination>andplugin active.
Was this page helpful?