Use when working with Simulink models — analyzing topology, inspecting parameters, modifying values, or managing model lifecycle via MATLAB Engine.
Unified skill for all Simulink CLI operations (read-only analysis and parameter editing).
Canonical skill name is simulink-automation (module path simulink_cli is internal only).
This skill belongs to plugin simulink-automation-suite.
matlab.engine.shareEngine in MATLAB.Call schema to get the full runtime contract (actions, fields, types, defaults, error codes):
python -m simulink_cli schema
python -m simulink_cli --json '{"action":"schema"}'
Schema output is the authoritative reference for command syntax. Do not rely on static docs for field names or types.
list_openedsession listinspect with a specific target and specific param for single-value checks; highlight for visual location.simulink-analyzer agent (see Responsibility & Handoff).set_param with dry-run preview before any write; block_add for placing new blocks (note: some library source paths contain literal newlines — use JSON \n escape, common in SPS libraries); line_add for connecting ports (supports both numeric signal ports and physical port names like LConn1/RConn1 for SPS connections); line_delete to remove a signal connection; block_delete to remove a block (also silently removes connected lines). See Write Safety Model below.simulate to run the model simulation after the modeling workflow is complete.model_update to compile/update diagram after structural changes.inspect the target after write to confirm the change took effect.model_save then model_close when done.Both single-param (param/value) and multi-param (params object) modes available. Always read and understand the model before modifying.
This skill and the simulink-analyzer agent have non-overlapping responsibilities.
The following actions are handled directly without dispatching the agent:
| Action | Reason |
|---|---|
session (list/current/use/clear) | Meta-query; main agent needs session context for dispatch decisions |
list_opened | Meta-query; main agent needs model list for dispatch decisions |
schema | Self-discovery; main agent may need the action catalog |
highlight | UI side-effect; no analysis output to isolate |
inspect (specific target + specific param) | Single-value response; main agent needs the value in context |
set_param | Write operation; requires user interaction for safety |
model_new / model_open / model_save | Write/lifecycle operations |
model_close / model_update | Lifecycle operations; direct execution |
block_add | Write operation; structural mutation |
line_add | Write operation; signal routing |
line_delete | Write operation; signal disconnection |
block_delete | Write operation; structural removal (also removes connected lines) |
simulate | Operational; runs model simulation |
matlab_eval | Operational; executes arbitrary MATLAB code |
The following actions are delegated to the analyzer agent for context isolation:
| Action | Reason |
|---|---|
scan (any configuration) | Topology output; potentially large |
find (any criteria) | Search results; potentially large |
connections (any configuration) | Connection graph; potentially large |
inspect (no specific param or param=All) | Full parameter list; potentially large |
| Multi-step read analysis workflows | Workflow-level context isolation |
Before dispatching, resolve session and model via direct session current or list_opened, then provide them explicitly to the agent.
| Action | Reason |
|---|---|
| Post-simulation signal analysis | Waveform data can be millions of points; isolate from main context |
| Dynamic performance evaluation | Rise time, overshoot, settling time, steady-state error |
| Multi-signal comparison | Cross-correlation, phase analysis |
Before dispatching, ensure simulate has been run (so sl_sim_result exists in workspace). Provide session, model, and specific analysis goals.
When a user request involves both analysis and modification (e.g., "check the PID parameters, then set Kp to 2.0"):
simulink-analyzer agent for the analysis portion first.Always analyze before writing. Never combine analysis delegation and write execution in a single step.
All writes go through a guarded preview-execute-verify cycle:
set_param defaults to dry_run=true. Returns current_value, proposed_value, apply_payload, and rollback.apply_payload verbatim in JSON mode. It carries expected_current_value as a precondition guard.verified field in the response. If false, investigate before proceeding.rollback payload from any response to restore the prior value.If the model changed between preview and execute, precondition_failed is returned without writing.
If read-back fails, verification_failed is returned with rollback and write-state data.
For response shape examples, see reference.md.
Error-driven next actions (consult schema for the full error code list):
| Error | Recovery |
|---|---|
engine_unavailable | Install/configure MATLAB Engine for Python, retry |
no_session | Run matlab.engine.shareEngine in MATLAB, retry |
session_required | session list → session use <name> or pass --session |
session_not_found | session list → copy exact name, retry |
model_required | list_opened → retry with explicit --model |
model_not_found | list_opened → open or create the model first |
block_not_found | scan or find to locate valid block path |
param_not_found | inspect --param All to list available parameters |
subsystem_not_found | Shallow root scan → select valid subsystem |
inactive_parameter | Use --resolve-effective or --strict-active |
precondition_failed | Rerun dry-run to refresh, replay new apply_payload |
set_param_failed | Inspect target/value constraints; prefer rollback if write may have occurred |
verification_failed | Inspect target again or use rollback payload |
model_already_loaded | Use a different name or close existing model |
model_save_failed | Check file permissions and disk space |
source_not_found | Verify library source path; use find to browse available library blocks |
block_already_exists | Use a different destination name or inspect existing block |
model_dirty | model_save first, or retry with force: true to discard changes |
line_already_exists | Check existing connections with connections; use a different port |
line_not_found | Verify src/dst block and port names with connections; confirm the line exists before deleting |
simulation_failed | Check model for errors with model_update; fix unconnected ports or type mismatches, then retry |
update_failed | Check model for errors (unconnected ports, type mismatches); fix with set_param or line_add, retry |
eval_failed | Check MATLAB code syntax and referenced variables/functions; retry with corrected code |
eval_timeout | Increase timeout or simplify the code; avoid infinite loops |
state_write_failed / state_clear_failed | Check plugin state-file permissions or pass explicit --session |
invalid_json / json_conflict / unknown_parameter / invalid_input | Correct request payload per schema, retry |
find returns empty | Broaden name pattern, try different block_type, widen scope |
Recipes for tasks that combine multiple actions. These patterns use existing CLI capabilities — no additional tools required.
The signal names live in the InputSignals parameter, which is populated only after model compilation:
model_update — compile the model diagram.inspect with --target MyModel/BusSel --param InputSignals — returns the comma-separated signal list.Library paths vary by toolbox. block_add auto-loads the library root on first use, so you only need the correct path:
simulink/Math Operations/Gain, simulink/Sources/Steppowerlib/powergui, spsUniversalBridgeLib/Universal Bridgesimulink/Signal\nRouting/Mux. In JSON mode use the \n escape.When source_not_found persists after auto-load, verify the path in MATLAB documentation or via find_system('<library>', 'Type', 'block').
SPS (Simscape / Specialized Power Systems) blocks use physical ports (LConn1, RConn1, etc.) instead of numbered signal ports. line_add supports these directly:
{"action": "line_add", "model": "MyModel", "src_block": "DC_Source", "src_port": "LConn1", "dst_block": "Inverter", "dst_port": "LConn1"}
Use connections on a block to discover its physical port names — they appear in physical_neighbors with "type": "physical".
matlab_eval accepts multi-line code as a single JSON string. Use \n for line breaks in the JSON payload:
{"action": "matlab_eval", "code": "x = 42;\nfprintf('value = %d\\n', x);\ndisp(x)"}
Key points:
evalc — both disp() and fprintf() output appear in the output field.\n in fprintf format strings must be double-escaped in JSON: \\n (so MATLAB receives \n).timeout to guard long-running code (default: 30s).After simulate runs, the SimulationOutput object is stored in the base workspace as sl_sim_result. Use matlab_eval to query it:
{"action": "matlab_eval", "code": "signals = sl_sim_result.logsout.getElementNames; for i=1:numel(signals), fprintf('%s\\n', signals{i}); end"}
For detailed waveform analysis, dispatch the sim-analyst agent (see Responsibility & Handoff).
To understand how a block is wired:
connections with the block as target — returns upstream/downstream signal edges and physical neighbors."type": "signal" with numeric port indices. SPS physical connections carry "type": "physical" and appear in physical_neighbors (direction-agnostic).inspect --param PortNames or related mask parameters.Current CLI capability boundaries. For operations beyond these limits, use direct MATLAB Engine access or run_matlab (when available):
| Limitation | Impact | Workaround |
|---|---|---|
| No workspace access | Cannot read/write base workspace variables or simulation results. | evalin/assignin via matlab_eval |
--json / --json-file) is first-class and mutually exclusive with flag-mode arguments.--json.reference.md