Skip to content

Repository files navigation

MirrorNeuron CLI

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.

Quick Start

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 -q

Try the CLI:

mn --version
mn runtime start
mn node list
mn blueprint run message_routing_trace

mn 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]"

Model operations

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.

Fast runtime-model orchestration tests

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=true

Repeat --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.

Stable jobs and execution runs

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 data

Execution 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.

Durable operations

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

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 --version

Tests:

export MN_ENV=test
mn --version

Production 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 status

Keep 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.

Details

Release Updates

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.

Notes

  • A running MirrorNeuron core is required for live runtime commands.
  • The default gRPC target comes from MN_GRPC_TARGET, then local deployment settings, then localhost:55051.
  • Use mn blueprint validate before mn blueprint run ./folder when checking a local bundle.
  • Validation honors first-use runtime-model preparation, so a compatible declared model need not already be installed.
  • mn blueprint run validates 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.
  • default is a LiteLLM model group, not a concrete model: it prefers nemotron3 and falls back to gemma4:e2b when 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 and fallback_model are read from the SDK's merged model catalog, including ~/.mn/models/catalog.json (or $MN_HOME) and the highest-priority MN_MODEL_CATALOG_PATH override. 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 .local name as a cluster endpoint.
  • --debug retains complete Docker build diagnostics and prints deferred model policies. Actual model/node selection appears later in runtime events.

About

The command line tool for MirrorNeuron

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages