User manual › Coding agents — letting Claude Code, Codex and others edit your model
kind: manual#agents#claude#codex#gemini#mcp#terminal#icore-cli#automation#recipe#manual#crash#sandbox#check

Coding agents — letting Claude Code, Codex and others edit your model#

A coding agent such as Claude Code, Codex, Gemini CLI or Cursor can change the model you have open in ICore Blocks. It edits the project's own files, in the project's own folder, and then tells the application to reload the project from its folder, so the change appears in the window you are working in. The project file is plain text, the same recipe statements the application uses everywhere (Recipes and templates — recording, replaying and reusing diagrams), so an agent edits it like any other source file.

The workflow an agent follows#

  1. The agent checks that the application has this project open (icore status).
  2. It edits the files in the project folder in place, mainly <Project>.iproj (the model) and solver.ini (the simulation settings).
  3. It checks the folder (icore check): a separate copy of ICore Blocks, with no window, loads the files and simulates them, and answers GREEN or RED. The agent fixes what a RED check names and checks again.
  4. It pulls the reload trigger (icore reload). The application checks the folder the same way itself, and only when that check is GREEN does it re-read the folder and replace what the window shows.
  5. It reads the answer: the blocks and links now loaded, or, on a RED check, why nothing changed.

The agent never makes a new project or works on a copy: the change is always to the project you have open. The instructions the agent reads, in AGENTS.md, say so.

You can pull the same trigger yourself: Reload from Project Folder in the project menu, or reloadProject in the command window.

What keeps your work safe#

  • Autosave waits for the reload. When the project file on disk changes outside the application, autosave pauses instead of writing the window's model over the change, and a notification says so. A reload, or a save you make yourself, ends the pause.
  • Nothing on screen is lost. Before every reload the model on screen is written to .icore/before-reload.iproj in the project folder, so an edit you made in the window while an agent was editing the file can still be recovered.
  • An agent's icore save refuses while an edit is waiting to be loaded, because saving would overwrite it with what the window shows.
  • A file that does not load in full is not loaded at all. The background check refuses it and lists the lines, and the window keeps the model it had.
  • Undo history does not survive a reload, as it does not survive opening a project.

Background checks: a model an agent writes cannot crash your application#

A model can crash or hang the program that loads it — a block given a configuration it cannot handle, a feedback loop that never settles. When that program is the application you are working in, the crash takes your unsaved work with it. (The Terminal panel's shell, and an agent running in it, survive it on macOS and Linux: see "If the application crashes" below.)

So an agent's change is tried somewhere else first. Before a reload, a push, an apply, a console line (eval) or a simulation touches the model you have open, the application starts a separate copy of itself with no window, gives it a copy of the project, and has it load the change and simulate the model from its start time to its stop time. Only when that copy finishes without crashing, without hanging and without an error does the change reach your window. If the copy crashes, only the copy is gone: your model stays as it was, and the agent is told exactly what happened.

The check is RED whenThe agent is told
the model crashed the copythe step it was in (opening the project, applying the change, simulating), the signal, and the stack of functions that were running
the copy hungthe step it was in when it was stopped (after 120 seconds unless the agent asks for longer)
a line of the project file did not applyevery such line and why
the simulation failedthe run's errors and its signals

An agent can also run the check on its own, without changing anything in your window: icore check in the project folder. Real output, from a project whose model is a Step into a Gain, run on 2026-10-03 against a build of commit 63287e25 with this feature applied:

$ icore check
GREEN -- the model loaded, and it simulated without an error in a separate process.
simulated 0 to 10 s, 101 steps; 4 signal(s):
  Home/Src:out0  first 0  last 1  min 0  max 1  mean 0.90099
  Home/G1:out0  first 0  last 4  min 0  max 4  mean 3.60396
  Home/K9:out0  first 1  last 1  min 1  max 1  mean 1
  Home/FromTheFolder:out0  first 1  last 1  min 1  max 1  mean 1

and after a line naming a block type that does not exist was added to the file:

$ icore check
RED -- 1 line(s) of the project file did not apply, first: z = block(NoSuchBlockType): unknown block type 'NoSuchBlockType'. Your open model was not changed.
  did not apply: z = block(NoSuchBlockType): unknown block type 'NoSuchBlockType'
the copy that was checked: ~/Documents/ICore Blocks/Probe/.icore/check/job-1791048801840-75459-cli

(It exits with 0 for GREEN and 1 for RED.) A copy whose check was RED is kept in the project's .icore/check/ folder so the agent can look at it; the five most recent are kept.

  • Every check echoes into your Command Window, labelled agent >, like the agent's other commands, so you see each GREEN and RED as it happens.
  • Your window stays responsive while a check runs. Another agent command sent meanwhile is answered "busy", and the agent sends it again.
  • A check usually takes a few seconds, plus however long the model takes to simulate. A model set to run forever is checked over its first 10 seconds of simulated time.
  • --no-simulate makes a check only load the model, for a model that is not meant to run yet. --check-timeout SECONDS gives a long simulation more time.
  • icore check asks the running application to start the copy, so the copy runs under your licence. With no application running it starts the copy itself: then the copy needs a licence token in the ICORE_LICENSE_TOKEN environment variable, and says so if it has none. It finds the ICore Blocks program by itself (the one that ran last); --app PATH or the ICORE_APP environment variable names another, and --local skips the running application.
  • The copy is licensed by the application that starts it, which hands it the licence it is already using. The copy removes it from its environment before it runs anything of the model's, so code a model runs never sees it.

The check protects your application from the agent's model. If the application crashes for any other reason, the Terminal panel's shell survives it on macOS and Linux; see the next section.

If the application crashes: the Terminal panel's shell carries on#

On macOS and Linux the Terminal panel's shell does not run inside ICore Blocks. It runs in a small helper process of its own, so when the application crashes — or is killed — the shell, and an agent running in it, keep running. The helper keeps the last megabyte of what the shell printed.

The next time you open the Terminal panel, it takes that shell over: what the shell printed while no window was attached is shown again, a line says [reattached: this shell outlived the app that started it], and you carry on in the same shell, with the same directory, variables and running programs. An agent there can reach the application you just started with icore as before; it finds the new application by itself.

Closing the Terminal panel, or quitting ICore Blocks normally, still ends the shell, as it always did. Only a crash leaves it running.

Shells left behind by a crash that you do not want to take over can be listed and ended in the command window:

CommandWhat it does
terminalHostsLists the shells kept alive this way, and which are left behind (their application is gone)
terminalHosts end left-behindEnds every shell no running application holds
terminalHosts end <host pid>Ends one

On Windows the shell is still part of the application and ends with it; there, start a long agent session in a terminal outside the application if a crash must not stop it.

Checking the result: simulate#

An agent can run the model without anyone pressing Run. icore simulate (or simulate in the command window) runs it from its start time to its stop time with the project's solver settings — when an agent asks, in the separate copy described above, never in your window — and prints, for every sink block (Scope, Display, ...), the signal's first, last, lowest, highest and mean value, flagging any that became NaN or infinite. It also lists every error or warning the run logged, and fails with the reason when the model cannot run:

$ icore simulate
simulated 0 to 10 s, 101 steps; 1 signal(s):
  Home/Scope:in0  first 0  last 0.999879  min 0  max 0.999879  mean 0.798693

icore simulate Home/Plant, Home/Controller watches those blocks' outputs instead, and --csv results.csv also writes every sample to a file in the project folder. icore eval modelConfig shows the solver settings the run uses.

Exporting code: Deploy to Hardware targets from a script#

The Deploy to Hardware targets can be created, configured and fired from the command window or a script, so an agent can export the model's code itself. They are the same targets the Deploy to Hardware panel shows, and they are saved with the project.

t = target(C++)
t.setConfig(Source, Home/Controller)
t.setConfig(Folder, code/controller_cpp)
t.setConfig(Verification, None)
t.fire()
  • target(Language) creates one: Python, MATLAB, Java, Rust, C++, C, System Verilog, Verilog, VHDL or PLC - ST. It starts out exporting Home into code/<name> in the project folder.
  • t.setConfig(Key, Value) sets Name, Language, Source, Folder, Verification, Tolerance, Pulse Width, Amplitude Min, Amplitude Max, Seed, Compiler Scan or Compiler Path. t.listConfig shows them all with what each accepts.
  • t.fire() exports now and lists the files written. It never opens a dialog: if export verification fails, the export stops and the reason is printed.
  • getTarget(name) binds an existing target, targets lists them, and t.delete removes one. From outside the application, icore targets and icore fire <name> do the same.

Export needs a fixed-step solver, as it does from the panel.

Seeing what an agent did#

Every command an agent runs appears in your Command Window as it happens, labelled agent > in place of the prompt, with its output underneath, so you can follow along and see exactly what was done to your model.

What you get in a new project#

Every new project folder, whether empty or made from a template, gets four files that tell an agent how to work in it:

FileRead byWhat it holds
AGENTS.mdCodex, Cursor, GitHub Copilot, Amp, Jules and most othersThe instructions: edit this folder in place and reload, never a new project; the .iproj format; how to ask the application for help
CLAUDE.mdClaude CodeImports AGENTS.md (@AGENTS.md), plus a note on the MCP tools
GEMINI.mdGemini CLIImports AGENTS.md, plus how to add the MCP tools
.mcp.jsonClaude CodeRegisters the icore MCP server, so Claude Code gets icore_* tools

These files are yours once they are written. ICore Blocks never overwrites a file you changed. To add them to a project made before this feature, or to turn them off for new projects, type one of these in the command window (The command window — the command engine for a user):

CommandWhat it does
agentGuideShows which of the four files the open project has, and whether new projects get them
agentGuide writeAdds whichever of the four files are missing from the open project
agentGuide refreshAdds missing files and updates the generated ones to this version's text; a file whose first line you deleted, or that you wrote yourself, is left alone
agentGuide off / agentGuide onStops, or restarts, writing them into new projects (on by default)

Starting an agent#

The simplest way is the application's own Terminal panel. Its shell starts in the project folder and already knows where the application is, so you type claude or codex there and the agent can start working. The shell is given:

VariableValue
PATHStarts with the folder that holds the icore client, so icore works as a command
ICORE_AGENT_SOCKETWhere the running application listens
ICORE_PROJECT_DIRThe open project's folder
ICORE_AGENT_CLIThe full path of the icore client

An agent started in any other terminal works too. The client finds the running application on its own, and if more than one copy is running it picks the one whose project folder you are in.

The icore client#

The client is a single Python 3 file, icore.py, that the application writes into its own data folder every time it starts, so it always matches the version you are running. On macOS that is ~/Library/Application Support/ICore Blocks/agent/icore.py; on Windows it is %LOCALAPPDATA%\ICore Blocks\agent\icore.py. The generated AGENTS.md names the exact path for your machine, and the command that runs Python on it: python3 on macOS and Linux, and on Windows whichever of py, python and python3 your PATH has. On Windows the application also writes icore.cmd beside the client, which is what icore runs in the Terminal panel's Command Prompt or PowerShell.

CommandWhat it does
icore statusWhich application is running, which project it has open, whether an edit on disk is waiting to be loaded, and whether changes are checked first
icore check [BLOCK, ...]Loads and simulates the project folder in a separate copy of ICore Blocks with no window, and answers GREEN or RED. Changes nothing in the open application; works with none running when ICORE_LICENSE_TOKEN is set
icore reload [--file]Checks the project folder, then, if the check is GREEN, re-reads it into the open project. --file pulls the trigger through the project folder instead of the connection
icore pull [LEVEL] [-o FILE]The live diagram as recipe text. Without a level it is Home, which includes every subsystem, so it is the whole model
icore push FILE [--level LEVEL]Replaces the whole model with FILE, as one Undo step. With --level Home/Controller it replaces only that subsystem's contents and keeps its ports, so the links the level above has to it stay
icore apply FILE [--level LEVEL]Adds FILE's blocks and links to a level without clearing it, as one Undo step
icore eval CODERuns console lines, from arguments, -f FILE, or standard input
icore run NAMERuns a saved script from the project's scripts/ folder
icore simulate [--csv F] [BLOCK, ...]Runs the model and summarises every sink block's signal (or the named blocks')
icore targetsLists the Deploy to Hardware targets
icore fire NAMEExports a target's code now
icore save [--force]Saves the project. Refuses while an edit on disk is waiting to be loaded, unless forced
icore blocks [TEXT]Lists the block types whose library path contains TEXT
icore describe TYPEA block's description, including its ports and parameters
icore help [NAME]The console's own help for a command or a recipe statement

It exits with 0 on success, 1 when the application refused, a check was RED or a line failed (the message says which), and 2 when no running application could be reached. reload, push, apply and check take --no-simulate, and those and eval and simulate take --check-timeout SECONDS, both for the background check.

A real session, run on 2026-09-25 against a build of commit 8ad88242 with this feature applied. The project was made from the First-Order Lag template, and the gain was then edited in the pulled file:

$ icore status
ICore Blocks 1.0.3 (pid 94647, protocol 1)
project: LagDemo
folder:  ~/Documents/ICore Blocks/LagDemo
$ icore pull -o model.icore
wrote model.icore
$ icore push model.icore
model replaced (Undo reverts it): 4 block(s), 3 link(s)
$ icore eval 'getBlock(Home/Kp).getConfig(Gain Value)'
_ = block 'Kp' in ICore Blocks/Home
Gain Value = 2.5
$ icore eval 'getBlock(Home/Gain1)'
line 1: getBlock(Home/Gain1)
getBlock(): no block 'Gain1' in ICore Blocks/Home -- it holds: Kp, Out, Step, Transfer Function

The last command exits with status 1, and its message lists what the level holds so the agent can correct itself.

To edit a block that already exists, bind a handle to it by its path with getBlock:

icore eval 'getBlock(Home/Controller/Kp).setConfig(Gain Value, 2.5)'

MCP tools#

icore mcp runs the same client as an MCP server, the standard way agents take tools. It offers icore_check, icore_reload, icore_simulate, icore_status, icore_pull, icore_push, icore_apply, icore_eval, icore_blocks, icore_describe, icore_help and icore_save. icore_pull can write straight to a file and icore_push can read from one, so an agent edits a real file between the two.

  • Claude Code reads .mcp.json in the project folder and asks you once to approve the icore server.
  • Codex keeps its MCP servers in its own settings, so add it once: codex mcp add icore -- python3 "<path to icore.py>" mcp (on Windows, the command AGENTS.md names instead of python3), and approve the tool calls when Codex asks.
  • Gemini CLI: add the same command under mcpServers in ~/.gemini/settings.json.

If the agent cannot reach the application#

An agent that runs its shell commands in a sandbox may not be allowed to open the application's local socket; Codex's default sandbox is one. The reload still works: icore reload then pulls the trigger through the project folder instead. It creates .icore/reload, the application (which watches the open project's folder for that file) checks and reloads, and the answer appears in .icore/reload-result.json. icore check can do without the connection too, by starting its own copy of ICore Blocks, when ICORE_LICENSE_TOKEN is set. The other icore commands need the connection. For those, use the MCP tools, which Codex runs outside its sandbox, or start Codex with local connections allowed:

codex -c sandbox_workspace_write.network_access=true

Claude Code runs icore without a sandbox unless you have turned one on.

What an agent can and cannot do#

  • Edits reach the window by a reload. An agent edits the project's files and then reloads; until then the window shows the model as it was.
  • A push replaces the whole model. Blocks, links, positions, parameters and solver settings come from the file. Scope traces and simulation results are cleared.
  • An apply only adds. Use it to put new blocks into one subsystem without touching the rest.
  • Edits wait for a running script. While a script in the ICore Script IDE is paused or running, and while code export is running, the application refuses edits and says why. Try again when it has finished.
  • Scripts are ordinary files. An agent can edit scripts/*.icore directly. The Script IDE reloads a changed script on its own, and icore run NAME runs it.

Turning it off#

The switches are in Settings ▸ Project ▸ Coding Agents:

  • Agent Instructions in New Projects decides whether a new project gets the four files. Existing projects are never changed by it.
  • Let Coding Agents Reach This App closes or opens the connection at once. Off, the application stops listening and stops watching the project folder for the reload trigger, and it stays off in later sessions until you turn it back on.
  • Check Agent Changes in the Background First is the check described above. It is on by default. Off, an agent's change is applied to your model directly, as typing it in the command window would be, and a model that crashes takes the application down.

agentGuide on|off, agentBridge on|off and agentBridge check on|off in the command window do the same. Reload from Project Folder in the project menu works either way. agentBridge on its own shows whether it is on, where it listens, and where the client is. The connection point is a local socket that only your own user account can open.

Without a window#

ICoreBlocks --console "agentServe 0 --project <folder>" opens a project with no window and serves the same commands until a client asks it to stop, which is useful on a build machine. A number instead of 0 stops it after that many seconds. The background check is the console command agentCheck, which the application and icore check run; it is not meant to be typed.