mn-cli provides the mn command for validating and running blueprints,
inspecting runtime state, managing jobs, exporting artifacts, and starting local
services installed by mn-deploy.
Install locally and run tests:
python3.11 -m venv .venv
. .venv/bin/activate
.venv/bin/python -m pip install -e .
.venv/bin/python -m pytest -qTry the CLI:
mn --version
mn runtime start
mn node list
mn blueprint run message_routing_tracemn runtime start starts a normal, federation-capable Core. There is no
separate worker mode: every Core owns its Redis state, can own jobs, and runs
all agents for those jobs locally. The successful start output includes the
advertised host, gRPC port, node identity, a join token, and the exact
mn node add command to run from another Core. Treat the displayed token as a
credential, keep terminal output private, and use mn node refresh-token when
it must be rotated.
Static HTML exports use the optional mirrorneuron-web-ui-skill package. With
the MirrorNeuron GAR package index configured, install it with:
.venv/bin/python -m pip install "mirrorneuron-cli[web-ui]"mn model exposes one type-aware workflow: list, add, show, update,
remove, and doctor. Add a catalog or arbitrary DMR reference with
mn model add <MODEL>, or register canonical provider JSON with
mn model add --file <definition.json>. Registrations are stored in
$MN_HOME/models/registry.json; provider secrets remain environment-variable
references. Use mn model list --available to include catalog-only choices.
Add --default to make one newly added DMR or provider model the logical
default ahead of the built-in Nemotron/Gemma fallback chain. Provider files
used with --default must contain exactly one model.
When the requested DMR artifact is already installed locally or on a cluster
node, mn model add reuses it and creates the same managed registry record
without pulling a second copy.
Model-aware blueprint launch logic is testable without Core, Docker, DMR,
LiteLLM, SSH, or a network. RuntimeModelDependencies supplies the model
catalog, resource report, system summary, BlueprintModelOps, and gateway
effects used by the real run_bundle handler. The reusable
tests/runtime_model_fakes.py cluster records model preparation, remote-route
reconciliation, and LiteLLM synchronization in memory.
Run the focused gate from this workspace:
../mn-system-tests/.venv/bin/python -m pytest -q \
tests/test_run_cmds_models.py tests/test_run_cmds_run.py \
-k "adaptive_model_placement or injected_remote_installed_state or injected_cluster"The runtime-selection scenarios are:
- a local-only 16 GB Apple node validates the portable Gemma fallback policy;
- adding a healthy 128 GB CUDA node validates that Nemotron is feasible;
- already-installed remote models remain usable without a second install;
- the first SDK model call selects and prepares the owner node, then uses that node's reachable LiteLLM gateway route.
mn blueprint run --debug prints the deferred policy for blueprint-declared
foundational LLMs. RAG and OCR model details are owned by their skills and
appear only in runtime events when those skills first call the SDK wrapper.
Those events report the selected model/node, fallback reason, and install/reuse state. Debug mode
also prints DockerWorker build commands and complete captured build output,
including builds performed through a remote node's native SDK service.
Live Spark checks are a separate, opt-in boundary smoke after this injected gate passes; they are not the development loop for placement policy.
CPU-only HostLocal workflows stay on the submitting runtime node by default.
When the local Core runs in Docker, prepared HostLocal Python environments are
reported to submissions through the Core-visible cache mount rather than the
host filesystem path.
Automatic HostLocal service ports use MN_AUTO_PORT_START through
MN_AUTO_PORT_END (62000-62049 by default in the local Docker runtime). That
range is published only on host loopback; the runtime's internal proxy marker
allows the service process to accept Docker forwarding without advertising a
non-loopback endpoint.
Detached runs keep their output relay alive until terminal state unless
MN_RUN_EVENT_RELAY_MAX_SECONDS is explicitly set.
Override blueprint config for one run without changing config/overwrite.json:
mn blueprint run ./vc_assistant \
--set document_sources.folder_path=/path/to/documents \
--set execution.debug=trueRepeat --set for multiple values. Values use JSON types when possible and
otherwise remain strings.
For a blueprint-owned web service, override the listener without editing its checked-in config:
mn blueprint run ./cctv_operator --web-ui \
--web-ui-host 0.0.0.0 \
--web-ui-port 61017--web-ui-host and --web-ui-port set web_ui.service.host and
web_ui.service.port for that run. A wildcard host exposes the service to
reachable peers; the blueprint is responsible for its authentication and
network-safety contract.
Create a reusable job once, then start independent runs that share its declared job data:
mn job create ./vc_assistant --job-id vc-diligence
mn job show vc-diligence
mn job start vc-diligence --inputs run-input.json
mn run list --job vc-diligence
mn run show <run-id>
mn run pause <run-id>
mn run resume <run-id>
mn run cancel <run-id>In an interactive terminal, run pause, resume, and cancel display a spinner
while Core processes the request. JSON and MN_CLI_OUTPUT=plain output remain
free of transient progress so they are safe for automation.
job_id is the durable configuration and data owner. run_id is one
execution and the identity used for control, logs, output, retention, and run
deletion. Starting the same job again creates another run; retrying a run does
not. Use mn blueprint run --job-id <job-id> to run an existing definition.
Without that option, blueprint run creates a durable job and starts
its first run.
With --job-id, the CLI prepares the currently installed blueprint revision
and atomically replaces the inactive job's executable bundle before starting
the run. Job data, schedules, and earlier run history are preserved. In
contrast, mn job start and scheduled dispatches are source independent and
reuse the stored definition-scoped submission and Docker services.
Lifecycle commands are deliberately separate:
mn job archive vc-diligence # retains shared data
mn job reset-data vc-diligence # confirms; clears/reseeds and advances generation
mn run delete <terminal-run-id> # confirms; never deletes shared data
mn job delete vc-diligence # confirms; deletes all runs, runtime resources, definition, and dataExecution status and controls use mn run ...; attached blueprint progress
uses the canonical workflow-progress stream and the same public-step contract as the
launch-time monitor.
mn node reconcile and mn node drain start durable Core operations and
render item updates in completion order. MN_CLI_OUTPUT=plain emits stable
→, ✓, and ! Warning: progress lines; the rich terminal shows live
counters and recent results.
If the owner of a cancelled job is offline, cancellation_pending means the
request was accepted and cleanup is queued for that node's rejoin. It is not a
command failure. Ctrl+C detaches without aborting the operation; reattach with:
mn operation show op-…
mn operation watch op-…Configuration is loaded by mn_cli.config. .env files provide defaults, and
real environment variables always override them. MN_ENV selects the
environment-specific defaults file and defaults to dev when unset.
Precedence:
real environment variables
> .env.${MN_ENV}
> .env
> built-in safe defaults
Development:
export MN_ENV=dev
cp .env.example .env.dev
mn --versionTests:
export MN_ENV=test
mn --versionProduction does not require any .env file. Provide deployment-specific values
through the real environment:
export MN_ENV=production
export MN_HOME=/var/lib/mirrorneuron
export MN_LOG_LEVEL=info
export MN_API_HOST=0.0.0.0
export MN_API_PORT=8080
mn runtime statusKeep secrets, credentials, production hostnames, production database URLs, cloud
credentials, and user-specific local paths out of source files. Use
environment variables or uncommitted .env files instead.
mn runtime update and the periodic interactive update check use the newest
stable install_support/v* snapshot in MirrorNeuronLab/mn-deploy as their
release plan. The snapshot pins the Core release tag, the SDK/CLI/API Python
package versions, and the Web UI npm version. The updater installs the exact
Python package versions from the public GAR agent-skills index and configures
the exact Web UI npm version for Docker Compose; it does not follow a source
branch, package-manager latest tag, or the Core repository's latest-release
endpoint. A component is shown as an update only when the snapshot version is
strictly newer than the installed stable version, so a stale snapshot cannot
offer a downgrade.
The Core remains a versioned GitHub Release binary because it is not a Python
or npm package. Its release asset URL is constructed from the same support
snapshot tag. For private mirrors, set MN_DEPLOY_REPO, MN_DEPLOY_REF,
MN_PIP_INDEX_URL, or MN_PIP_EXTRA_INDEX_URL before running the command.
- A running MirrorNeuron core is required for live runtime commands.
- The default gRPC target comes from
MN_GRPC_TARGET, then local deployment settings, thenlocalhost:55051. - Use
mn blueprint validatebeforemn blueprint run ./folderwhen checking a local bundle. - Validation honors first-use runtime-model preparation, so a compatible declared model need not already be installed.
mn blueprint runvalidates model declarations but does not install models. Workers select, install, and route each managed model on its first actual use.- Docker workers receive a worker-reachable model-control target and use the SDK to select the best cluster node independently for LLM and for model specifications supplied at runtime by RAG and OCR skills.
- Node-local workflows are hard-pinned as a whole after topology lowering. Runtime health rejects nodes whose coordination-store identity differs from the submitting Core or whose Redis endpoint is read-only.
- OpenShell workers that reuse a job-scoped sandbox are prepared before submission; the submitted node receives the concrete sandbox name and SSH host instead of asking Core to create host resources.
defaultis a LiteLLM model group, not a concrete model: it prefersnemotron3and falls back togemma4:e2bwhen no healthy node can run Nemotron. The existing cluster model monitor rebuilds these routes as nodes join, rejoin, or leave; incomplete peer snapshots retain the last safe routes until departure is confirmed. Gateway route names andfallback_modelare read from the SDK's merged model catalog, including~/.mn/models/catalog.json(or$MN_HOME) and the highest-priorityMN_MODEL_CATALOG_PATHoverride. When a local runtime's DHCP address changes, the monitor rehomes only DMR registrations whose artifact is confirmed on the local host and whose former owner is absent from live membership. It then rebuilds gateway routes from the current live node address; this avoids treating an unverified.localname as a cluster endpoint.--debugretains complete Docker build diagnostics and prints deferred model policies. Actual model/node selection appears later in runtime events.