The command window — the command engine for a user#
The command window is the text way into ICoreBlocks. One line typed at its
prompt can be a calculator expression over matrices and transfer functions
(y = x*[1 2; 3 4]), a recipe statement that creates, wires or configures a
block on the open diagram (g = block(Gain)), or a named command
(modelConfig, templates, gitStatus). The same evaluator runs a line
headlessly: ICoreBlocks --console "<line>" prints the result and exits 0 or 1.
This page explains the engine — how a line is read, where variables live, what
Tab and the arrow keys do, and how the console reaches the canvas. The roster of
what you can type is Command glossary — console commands, verbs, functions; the recipe language, .iscript
files and templates are on Recipes and templates — recording, replaying and reusing diagrams; words such as handle,
recipe and subsystem are defined in User glossary — the vocabulary of using ICoreBlocks.
Where it is#
- In the editor: the left panel page Quick Code (menu Code Engine →
Scripting → Quick Code, or the panel strip). It is a transcript on top, a
status row (
A- 13pt A+text-size control,● ready/● busy) and the prompt below, placeholder textEnter Command. The transcript is also reachable as View → Loggers → Command History. - Headless:
ICoreBlocks --console "<line>". The line runs 1.5 s after startup through the very same function the panel calls (ICoreCommandWindow::evaluateLine, wired insrc/ICoreSDK/Shell/Application.cpp); output goes to stdout on success, stderr on failure, and the process exit code is 0/1 by the line's verdict. A bare--consolewith no line never exits. - The Script Runner (Code Engine → Scripting → Script Runner) feeds a whole
.iscriptfile to the same evaluator one line at a time — see below.
The rules the engine enforces#
- A line is split into statements on top-level
;— a;inside(...),[...]or<...>is not a separator, which is what lets[1 2; 3 4]stay one matrix literal. Statements run in order and stop at the first failure. - A statement ending in
;is silent when it succeeds (MATLAB's rule). Failures are always printed; silencing never hides an error. - Each statement is classified in this order, first match wins:
- a recipe statement —
block(...),subsystem(...),connect(...),area/image/textbox(...),plot(...),selectionModel(),clearDiagram(...),handle.method(...), or a bare handle name; - an assignment
name = rhs; - a bare name that is a defined variable (echoes it);
- an expression — a number, a
[...]literal, or anything carrying an operator (+ - * / | & ' ( )); - a registered command: first word is the command, the rest are its
arguments;
name()is accepted asname. Nothing matched →unknown command: <first word>and the line fails.
- a recipe statement —
- A command name is never shadowed. A variable named like a command is not
echoed by its bare name, and an expression whose first word is a command
(
reverse a+b,clear()) is dispatched as that command. - A block handle beats a variable of the same name in
name.method(...); a name that is only a variable falls through to the math grammar (h.values(),G.step(10)), which is how time series and transfer functions get their members. - Results are annotated with their type —
7 # Integer,0.333333 # Double,[[3, 6], [9, 12]] # Matrix of Double, and likewise# Polynomial,# Transfer Function,# State Space,# Time Series,# String. The annotation is the variable system's real type name; a scalar whose value is whole prints asInteger. - Only one line runs at a time. While a line runs the prompt is disabled and
the status shows
● busy; a second line cannot slip in underneath.
The variables space#
- Create:
x = 3,A = [1 2; 3 4],label = hello,G = tf([1],[1,2,1]). The right-hand side is either a literal (stored as typed), a bare name (copies an existing variable, otherwise stores the word as a string), or an expression (evaluated, then stored). The reply echoes the stored value:x = 3 # Integer. - Types are derived from the stored text:
Integer,Double,Matrix of Double,String,Transfer Function,State Space,Polynomial,Time Series(src/ICoreSDK/ICoreMath/ICoreVariable.cpp). Matrices print in Python list form; the stored form is MATLAB syntax. - Read: the bare name echoes it; use it in any expression.
- List: the left panel page Variables is the table view of the same store. There is no console command that lists all variables (checked 2026-08-17 against the roster in Command glossary — console commands, verbs, functions).
- Clear:
clearVariablesSpaceempties the store;clearAllalso wipes the logs and the recipe handles. - One store, project-wide. There is exactly one variables space; blocks in
every subsystem see it. Its variables are saved with the project: the
.iprojfile is recipe text and its first lines arename = value;declarations (generateRecipeshows exactly what will be written; see the run below). A headless--consoleprocess starts with an empty store and an unsaved project, so nothing carries from one invocation to the next. - A block can read a console variable. Type a variable's name into a
block parameter (
Gain Value=K). When the run starts the block's configuration is loaded and every parameter whose text is not itself a number or matrix is looked up by name in the variables space; a numeric hit supplies the matrix, a miss leaves the text as a string (ICoreBlockSolverEnvironment::loadBlockConfig,src/ICoreSDK/ICoreModel/SolverEnvironments/). The lookup happens at run start, so changeKand re-run; the block does not track it live. v = handle.get(prop)/v = handle.getConfig(name)store a numeric snapshot as an ordinary variable — later block edits do not updatev, and text properties refuse to bind.
Things that surprise users#
(More symptoms, beyond the console, are collected on Troubleshooting — the messages you will meet and what to do.)
unknown command: xfor a variable you just made — each--consoleprocess is fresh, andclearVariablesSpace/clearAllempty the store; a bare name that is not a variable, a handle or a command falls all the way through to the command dispatcher, whose message this is. Same cause for a typo in a variable name.unknown command: 2^3— there is no power operator. The engine decides a statement is an expression by seeing one of+ - * / | & ' ( )outside brackets;^is not one, so the text is tried as a command. Use the matrix functions in Command glossary — console commands, verbs, functions (pow(A,n)element-wise,mpower(A,n),inv(A), …) instead. Bounds and precision of the evaluator: Numerics — what the solver will and will not do.- A chained line printed only its last result — every statement you closed
with
;was silent by design; only the unterminated tail speaks. error: division by zerostops the rest of the line — statements after the failing one do not run; the exit code is 1.- A variable named like a command will not echo —
clear,help,echoand every other registered name are dispatched as commands first; such a variable is reachable only inside an expression. Pick another name. - Tab completed nothing — completion only offers at a statement head, right
after
=, or right after a.(ICoreCompletion::tokenStart); mid-argument it stays quiet, and it completes names from the glossary only (commands, matrix functions, recipe verbs) — not your variables, not block types. - The suggestion popup ate my Enter — with the popup open, Enter on an entry you arrowed onto takes the entry; Enter with nothing highlighted closes the list and submits the line exactly as typed.
- Up arrow recalls last week's commands — history is on disk (below).
- The
.iprojgrew aK = 2.5;line — that is the variables space being saved with the project. It is intended.
Tab, the popup, and history#
- Tab completes the current token from the glossary (case-insensitive prefix match): the longest common prefix is filled in, and if more than one name is still open the popup lists them (at most 8 visible, scrolling). If an entry is already highlighted, Tab takes it exactly as Enter does.
- The popup appears as you type at a completable position and filters by prefix. Up/Down move inside it; Enter takes the highlighted entry; clicking an entry does the same.
- Up/Down with the popup closed walk the submitted-line history (newest first); the half-typed draft is kept and comes back at the bottom.
- History is persisted in
commandHistory.txtinside the app's data folder (on macOS~/Library/Application Support/ICore Blocks/), appended on every submit — a crash loses nothing. Settings → Editor → Command Console → Command History Kept sets how many lines Up can reach (default 500, max 5000; 0 stops recording without erasing).clearCommandHistorydeletes the file and empties the in-memory list. glossaryprints the full catalog the popup draws from;helplists the registered commands only.- Ctrl+wheel / Ctrl+plus/minus / Ctrl+0 zoom the transcript;
clsorclearwipe it;clearAllLogswipes every output log.
Scripts#
A script is a plain-text file with the extension .iscript, one console line
per line; blank lines and lines starting with # are skipped. It may contain
anything the prompt accepts — recipe statements, assignments, expressions,
commands. Scripts live in <project folder>/scripts and are run from the
Script Runner panel (Run for the open script, Run All for every script
in the folder, name order); a script stops at its first failing line and the
panel reports which line. The recorded form of a diagram is itself an .iscript
(Import Diagram, generateRecipe, saveTemplate/useTemplate) — the whole
story is on Recipes and templates — recording, replaying and reusing diagrams. There is no console command that runs a
script file by name (checked 2026-08-17).
The console and the canvas#
Recipe statements act on the open project: block(Type, Parent) creates a
block in a subsystem (parent defaults to Home), connect(a<1>, b<0>) links
output port 1 of a to input port 0 of b, .setConfig(name, value),
.move, .rename, .delete edit it, .info and .listConfig report it, and
generateRecipe [path] prints the recipe that reproduces a whole level.
Handles (g, s) are names for live objects and are listed in the Objects
Tracker panel; .delete is permanent (no trash, no undo). Headlessly "the open diagram"
is the empty, unsaved project the app starts with — the run below creates a
block at ICore Blocks/Home/Gain — so a --console recipe is a way to test a
line, not a way to edit a saved project (open it in the editor for that, or use
the Script Runner). Verbs are listed under Recipe verbs in Command glossary — console commands, verbs, functions.
Real runs#
Binary build-mac/ICoreBlocks.app built 2026-08-16 23:39 (source at
approximately commit 2e126fbf). Every run below is one process,
HOME=<scratch> QT_QPA_PLATFORM=offscreen ICoreBlocks --console "<line>", with
the toolkit's startup noise removed; exit= is the process exit code.
(a) Arithmetic and variables
>>> x = 3; y = x*[1 2; 3 4]; y
y = [[3, 6], [9, 12]] # Matrix of Double
exit=0
>>> A = [1 2; 3 4]; A' | A
[[1, 3, 1, 2], [2, 4, 3, 4]] # Matrix of Double
exit=0
>>> label = hello; label
label = 'hello' # String
exit=0
>>> x = 3; clearVariablesSpace; x
unknown command: x
exit=1
(' is transpose, | horizontal and & vertical concatenation — read in
src/ICoreSDK/ICoreMath/ICoreExpressionEvaluator.cpp.)
(b) An unknown command, and a non-operator
>>> frobnicate 3
unknown command: frobnicate
exit=1
>>> 2^3
unknown command: 2^3
exit=1
(c) Recipe verbs on the headless diagram
>>> K = 2.5; g = block(Gain); g.setConfig(Gain Value, K); g.listConfig; generateRecipe
K = 2.5;
Gain = block(Control_Systems/Base_Blocks/Gain);
Gain.rename(Gain);
Gain.move(0, 0);
Gain.resize(70, 70);
Gain.setConfig(Sampling Time (s), -1);
Gain.setConfig(Gain Value, K);
Gain.setConfig(Multiplication Type, Element-wise (K.*u)%~%Matrix (K*u)%~%Matrix (u*K)%~%Matrix (K*u) (u vector)~~Element-wise (K.*u));
subsystemTimes(ICore Blocks/Home, 1786955336275, 1786955337779);
exit=0
>>> g = block(Gain); s = block(Step); connect(s<0>, g<0>); g.getConfig(Gain Value)
Gain Value = 1
exit=0
g.info on the same block printed the full property sheet (name, type,
fullType: Control_Systems/Base_Blocks/Gain, path: ICore Blocks/Home/Gain,
size, rotation, ports and the block's description) — 60 lines, not repeated
here. Note the first line of the recipe: the console variable K is part of
what the project saves.
(d) A statement chain with and without the trailing ;
>>> x = 3; y = x*2
y = 6 # Integer
exit=0
>>> x = 3; y = x*2;
exit=0
>>> x = 3; x; x*2; 1/3
0.333333 # Double
exit=0
>>> x = 3; y = x/0; y
error: division by zero
exit=1
For contributors#
The evaluator's order of resolution is ICoreCommandWindow::evaluateLine
(src/ICoreSDK/ICoreStudio/StudioObjects/Panels/CommandWindow/), and the
console-facing invariants — result handlers, main-thread only, the ;
terminator the serializer emits, --console exit codes — are stated on the
contributor page for the command system (icorecoder), with the expression
grammar on icoremath and the --console hook on shell.