Tandem Browser
hydro13/tandem-browser
Use Tandem Browser's MCP server (local and remote agents) or HTTP API (local and remote agents) to inspect, browse, and interact with the user's shared browser safely.
Recipe for running Modelica models and building experiments/graphs in lunica (LunCoSim), driven from the HTTP API with curl.
$ npx skills add LunCoSim/lunco-sim --skill run-modelica -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install LunCoSim/lunco-sim run-modelica --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/LunCoSim/lunco-sim.git skills-src && mkdir -p .claude/skills && cp -r skills-src/skills/run-modelica .claude/skills/run-modelica && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "run-modelica" agent skill from https://github.com/LunCoSim/lunco-sim/tree/main/skills/run-modelica into .claude/skills/run-modelica/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "run-modelica", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/LunCoSim/lunco-sim/tree/main/skills/run-modelicaType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add LunCoSim/lunco-sim --skill run-modelica -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install LunCoSim/lunco-sim run-modelica --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/LunCoSim/lunco-sim.git skills-src && mkdir -p .agents/skills && cp -r skills-src/skills/run-modelica .agents/skills/run-modelica && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "run-modelica" agent skill from https://github.com/LunCoSim/lunco-sim/tree/main/skills/run-modelica into .agents/skills/run-modelica/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "run-modelica", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add LunCoSim/lunco-sim --skill run-modelica -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install LunCoSim/lunco-sim run-modelica --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/LunCoSim/lunco-sim.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/skills/run-modelica .cursor/skills/run-modelica && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "run-modelica" agent skill from https://github.com/LunCoSim/lunco-sim/tree/main/skills/run-modelica into .cursor/skills/run-modelica/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "run-modelica", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/LunCoSim/lunco-sim.git --path skills/run-modelica--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add LunCoSim/lunco-sim --skill run-modelica -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install LunCoSim/lunco-sim run-modelica --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/LunCoSim/lunco-sim.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/skills/run-modelica .gemini/skills/run-modelica && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "run-modelica" agent skill from https://github.com/LunCoSim/lunco-sim/tree/main/skills/run-modelica into .gemini/skills/run-modelica/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "run-modelica", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install LunCoSim/lunco-sim run-modelicaInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add LunCoSim/lunco-sim --skill run-modelica -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/LunCoSim/lunco-sim.git skills-src && mkdir -p .github/skills && cp -r skills-src/skills/run-modelica .github/skills/run-modelica && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "run-modelica" agent skill from https://github.com/LunCoSim/lunco-sim/tree/main/skills/run-modelica into .github/skills/run-modelica/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "run-modelica", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add LunCoSim/lunco-sim --skill run-modelica -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install LunCoSim/lunco-sim run-modelica --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/LunCoSim/lunco-sim.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/skills/run-modelica .opencode/skills/run-modelica && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "run-modelica" agent skill from https://github.com/LunCoSim/lunco-sim/tree/main/skills/run-modelica into .opencode/skills/run-modelica/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "run-modelica", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
run-modelicaRecipe for running Modelica models and building experiments/graphs in lunica (LunCoSim), driven from the HTTP API with curl.
Run Modelica is an agent skill from LunCoSim/lunco-sim. Recipe for running Modelica models and building experiments/graphs in lunica (LunCoSim), driven from the HTTP API with curl. Trigger whenever you need to: launch the workbench, open/compile a Modelica model, run it live (interactive realtime) or as a fast batch, sweep parameters across many runs, read simulation results/trajectories, poke runtime inputs, or plot and compare runs — without asking the user to click. Covers the --api launch, the POST /api/commands envelope, the command + query catalog, run…
Its SKILL.md is about 13k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.
It sits in Agent Workflows, covering MCP servers and REST APIs. It works with Model Context Protocol. The repository describes itself as: Collaborative Multiphysics Cosimulator For Space Missions 🌎🚀🌚. The licence is Apache-2.0.
9 steps, taken from the step headings in SKILL.md.
Read from SKILL.md and the folder at commit 43f1301. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
Shell commands in SKILL.md call:
curlcargopython3From the folder's file list and the shell code blocks in SKILL.md.
No URLs in SKILL.md. Its commands use curl, which can reach the network depending on how they are called.
From URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Run Modelica loads about 13k tokens when it runs. Until then it costs about 179 tokens; SKILL.md has 5,765 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from LunCoSim/lunco-sim at commit 43f1301, republished under its Apache-2.0 licence (© LunCoSim). 5,765 words, ~13,161 tokens.
.claude/skills/run-modelica/SKILL.md (or your agent's skills folder).lunica exposes a reflect-registered command API and structured query
providers over POST /api/commands. Drive everything with curl. The
mcp__lunco__* tools mirror this API but are frequently down — use curl as
the primary surface; only fall back to MCP if a human explicitly asks.
Modelica runs inside any app that embeds LunCoApiPlugin + the Modelica
workbench. Build the named binary in the current worktree, then invoke it
directly. The API server only exists when you pass --api. Default port is
4101 (lunco_api_contracts::DEFAULT_API_PORT).
Before creating a new Modelica file, inventory the maintained package roots and the closest composed USD network in the current checkout. Reuse existing component classes through USD or the generated wrapper when their equations and public contract fit; add a new mission/vehicle model only when the equation or interface is genuinely absent. An isolated Modelica compile proves neither USD wiring nor runtime physics.
Compile admission preserves an existing participant/vehicle name; generated class identity belongs to simulation metadata. Verify a control HUD against the physical vehicle identity after compile and reload.
For shared plume calculations, reuse
LunCo.Propulsion.computePlumePhotometry. PlumePhotometry supplies named USD
ports; RCSJet calls the function directly with static nozzle parameters.
See USD-driven visuals for
the fixed-size result contract. Validate model refactors through the production
rcs_feed_starvation and rocket_engine_plume_defaults scene gates, then
measure cold solver preparation and running-step cost separately.
For material-dependent equations, use the component's typed SysML material
assignment and property source described in the
mission engineering material gate.
Keep values and units typed until the Modelica-source emission boundary, and
derive generated parameter literals from that source rather than maintaining a
second hand-edited material table in .mo. The shared material catalogue and
generic cross-domain binding are not yet established; if the current bridge
cannot provide a required property with its unit and applicability, report that
generic gap instead of substituting a copied constant.
For radiation or surface thermal models, also resolve the typed finish/coating
assigned to the analyzed face and use its sourced engineering optical/thermal
properties. UsdShade shader presets are presentation mappings only and must
not be used as Modelica property sources.
| App | Launch | Modelica surface |
|---|---|---|
lunica | "$LUNICA_BIN" --api 4101 | The Modelica workbench itself — nothing to switch to. Prefer this for pure Modelica work. |
luncosim | $LUNCOSIM_BIN --api 4101 | Ground-physics simulator; an explicit --scene launch opens View, while Modelica lives under the modelica_analyze perspective — switch to it (below) before diagrams/plots render. |
luncosim-server | $LUNCOSIM_SERVER_BIN --api 4101 | Headless LunCoSim host; use the GUI luncosim command for the workbench. |
In luncosim, switch to the Modelica view before plotting/screenshotting.
The compile/run/experiment commands and query providers work regardless (they're
headless-safe), but the diagram/plot panels only paint when their perspective is
active. Switch with:
curl -s -X POST http://127.0.0.1:4101/api/commands -H "Content-Type: application/json" \
-d '{"type":"ExecuteCommand","command":"ActivatePerspective","params":{"id":"modelica_analyze"}}'
# other ids: "sandbox_view", "rover_build". Reset a broken layout: {"type":"ExecuteCommand","command":"ResetWorkspaceLayout","params":{}}--no-ui for a headless compile/run server (no window, no GPU). The API
surface is identical; screenshots, diagrams, and 3D viz are what you lose (so
perspective switching is moot). GetExperimentResult/SnapshotVariables still
give full numeric results headless.luncosim for scene-test and visual evidence. Use
luncosim-server or luncosim --no-ui for numeric/API evidence only, and
report the binary, revision, readiness state, and evidence type separately.Exit and verify shutdown before replacing its binary.SimComponent; the
co-simulation backend owns their topology publication. Live sample changes
must not invalidate resolved handles without a structural contract change.The standalone runner is owned by lunco-modelica-execution, not
lunco-modelica-core. For a one-shot current-source compile and fixed-step
solve with CSV output:
cargo run -p lunco-modelica-execution --bin modelica_run -- \
assets/models/AnnotatedRocketStage.mo AnnotatedRocketStage.RocketStage \
--duration 30 --dt 0.001 --input valve_command=0.7 \
--record altitude,velocity --output /tmp/run.csvThis runner uses the shared compiler and solver path, but it is not a substitute for the active Twin/API test when the source depends on Twin-indexed packages, Editor state, or scene composition.
Wait for readiness with an until loop (never chained sleeps):
until curl -s -o /dev/null -X POST http://127.0.0.1:4101/api/commands \
-H "Content-Type: application/json" \
-d '{"type":"ExecuteCommand","command":"Ping","params":{}}'; do sleep 1; doneStop with the Exit command (never pkill/kill — those need user confirm):
curl -s -X POST http://127.0.0.1:4101/api/commands \
-H "Content-Type: application/json" -d '{"type":"ExecuteCommand","command":"Exit","params":{}}'For a multi-domain run, use the shared AttachProgram { doc_id, spec } command
instead of writing marker components or maintaining a separate binding table.
The spec authors the LunCoProgramAPI child, explicit scalar inputs and
outputs, and native USD connections in one journaled change set. In Rhai the
same surface is assembly_edit::attach_program(...) with
assembly_edit::program_input_connection(...),
assembly_edit::program_input_default(...), and
assembly_edit::program_output(...) helpers. Verify the
result with ListPorts, CosimStatus, and GetBrokenConnections; a source
without declared ports is reported as source-only and does not step.
Modelica packages under assets/models/<Root>/ and inside a Twin use the standard
package.mo/package.order layout and members' within declarations. A Twin may
declare [modelica].paths (Twin-relative, with "." meaning the Twin root) and
externals in twin.toml. Without that section, the Modelica owner derives roots
from the indexed Twin .mo files, so package discovery does not depend on a
hard-coded folder. A qualified reference such as LunCo.Electrical.Battery is
resolved by its root segment through the normal Modelica search-path inventory;
do not add a library-specific Rust load call. Every live compile admits its
required roots through the existing LoadSourceRoot worker path before it
sends Compile. File-backed source assets carry root requirements from their
prepared AST interface, document compiles derive them from the primary and
sibling ASTs, and a generated policy's source_roots list is its required root
manifest. The worker commits root preparations in admission order before
compilation, rejects unadmitted roots, and reports failed roots without retrying
synchronous discovery. Synchronous compiler helpers remain for CLI and batch
callers.
The worker's successful load acknowledgement carries the authored top-level
namespaces parsed by that exact source-set operation. The registry retains those
names on the scoped owner entry, and compile admission resolves each qualified
namespace to its unique source-set ID. Missing or ambiguous namespace ownership
is a terminal diagnostic. Failed or stale acknowledgements cannot publish Ready
or recreate a retired namespace; Twin close removes the entry and its names.
Verify Twin package admission through the existing authored
path_interoperability.rhai namespace assertions: load a Twin package, compile a
separate wrapper using its qualified member, inspect the solved output, then
verify a missing namespace produces a terminal compile error.
An unqualified source asset already present in an admitted root compiles the
root-owned class only when its exact source CID is in the admitted content
closure. Changed or conflicting source text is rejected; update and readmit
the source root before compiling it. This prevents a second URI from duplicating
the same root definition while preserving the root's authority.
The policy list does not replace composed USD facts for member-class
discovery. The worker's prepared-solve cache keys library state from the
revisions that ModelicaCompiler records while admitting source roots. Its
source key is captured from the successful strict compiler's participating-source
closure before clearing user overlays. Generated class/network-title identity is
normalized; equations, parameters, initial values, participating siblings, and
contributing library bytes remain structural. Unrelated sibling edits and runtime
document IDs do not invalidate prepared solve IR. The captured key remains with
the immutable DAE through shared reuse and resets; the precompile DAE cache uses
the full submitted input set until the strict closure is known. It does not scan
the complete Modelica tree during the first live stepper build.
For preparation evidence, use actual owner INFO logs: cache=memory-hit at
in-memory admission, cache=disk-hit after persistent lookup, and cache=miss
when lowering runs. Disk preparation includes lookup, lowering, and total
duration plus the source key. Stepper construction is not evidence of cache reuse.
Generated USD networks compile their complete synthesized source plus admitted
source roots; unrelated editor documents are not sibling inputs. The reserved
bundled generated/ filename namespace drives provenance and structural cache
classification. Verify repeat-load cache reuse while changing document-open
order; authored Modelica documents retain their multi-document source sets.
Domain discovery does not resynthesize ordinary scene-owned networks when a content prim receives its GID: that identity does not enter their namespace. Instance-scoped identities and unsettled provenance remain discovery inputs, alongside prim paths, stage revisions, wiring, and member-source events.
Initial network results may publish as a bounded four-root prefix only while their own fixed-clock admission hold is present and no prior projection is installed. Live replacements remain one per Update; repeated results for a root wait for ECS publication. Worker completion never bypasses the oldest request or its Twin/stage/instance validation.
On native runs, one dedicated Rumoca actor owns the mutable session and shared
DAE cache. Source-root installation, Compile, Reset, parameter updates, and
cache-invalidating Step auto-init share a FIFO. The worker commits results in
submission order after entity-session and library-generation checks; a Step
that needs a rebuild resumes only after its initialization commits. These
continuations leave the Modelica command owner free to service other entities,
and actor requests plus solve preparations share bounded admission. Persistent
solve-cache reads and writes run with DAE lowering in the preparation pool; the
native owner thread does not perform cache I/O or fall back to synchronous
lowering. Wasm keeps compilation inside its Modelica Web Worker.
Shared immutable RAM caches use the captured
lunco_modelica_runtime::ModelicaCacheLimits resource: positive compiled and
prepared entry capacities, each defaulting to 64 per worker. Follow the
Modelica cache contract for
configuration timing, FIFO reuse, and browser startup/respawn admission. Entry
caps bound graph count rather than heap bytes; eviction preserves live owners.
Run the generic immutable_reuse_cache_ tests and compile the browser worker
bundle when changing configuration transport. Do not infer Twin teardown from
shared immutable cache contents.
For shared browser worker transport changes, run the generic worker_lifecycle_
tests in a real browser and compile both Modelica execution and DEM bake
consumers. Replacement must release the old handlers, including replacement
inside an executing callback; failed replacement leaves an empty slot.
For native compiler heartbeat changes, run the generic compile_heartbeat_
lifetime tests; ensure normal, error, and unwind exit interrupt the wait and
release the owned thread.
Native optional solve-cache reuse captures the cache-owned
lunco_modelica_worker::worker::PreparedSolveDiskLimits resource before
ModelicaExecutionPlugin starts the worker. Defaults are 32 retained records, 64 MiB compressed,
256 MiB decoded, and a 64 MiB zstd window; see
the cache ownership contract for
valid ranges and configuration timing. Missing records are cache misses;
rejected existing records warn and recompute admitted equations. Invalid limits
are a typed worker startup failure. For decode changes, run the generic
prepared_solve_disk_cache_ tests; do not substitute repository models for the
inline-storage boundary fixtures.
For publication/retention changes, also run persistent_solve_cache_ and storage
cache_directory_transaction_ tests, including the native Windows CI path.
Keep heavy encoding outside the storage transaction; never remove its lock
file or broaden retention beyond the owned cache namespace. Optional publication
failures warn while preserving the admitted solver result.
On native desktop startup, cache-miss solve-IR lowering runs in the worker's
bounded preparation pool because the DAE input and solve options are immutable.
The worker alone commits the resulting solve model and constructs the live
stepper; Step, Reset, parameter updates, and source-root changes remain
ordered behind that commit. Persistent solve-IR entries are keyed by structural
source identity, the content-sensitive admitted-library revision, solver, and
parameter overrides. A source-root change clears worker-local prepared models
while retaining disk entries for future matching revisions. Readiness is still
the completion barrier, so
physics must not be started before /api/ready reports ready=true,
world_hold=false, and pending_count=0.
Bundled and workspace source roots are parsed to completion before admission and installed as one parsed source set. A failed member therefore keeps the root out of the Rumoca session; do not treat a nonzero parsed count as readiness.
The registry marks each root as Application- or Twin-owned. Twin root IDs include
the stable Twin ID. TwinClosed removes only that Twin's source sets and queues
ordered unloads to the Rumoca actor; other Twin and application roots remain.
Twin closure also retires its open Modelica documents through the core
CloseDocument owner, including linked execution entities. Workspace replacement
closes every editor document before TwinAdded; unfinished UI preparations are
canceled and file-read completions are fenced by their admitted runtime owner.
Individual document closure also cancels parse preparation, save-close
continuations, and document-owned modals before retiring the editor state.
Reopening the same Twin starts fresh. RestartScene leaves editable documents
resident while rebuilding their scene-owned execution.
Operation IDs fence an in-flight file read from installing a source set after its owner closes. If the worker has not created its channel yet, pending unloads stay queued and are sent before a later Twin load. A disconnected channel is a terminal unload failure: it reports a runtime fault, retains the queued operation, and blocks later Twin root admission instead of retrying on every update.
For policy-owned generated models, keep contract assertions in authored
assets/scenarios/tests/*.rhai scenes; standalone live probes may use
assets/scripting/tests/*.rhai. Rust should provide the composed facts and
invoke the registered policy; Rhai should assert the generated source,
topology, layout, and UI metadata. The policy result is strict: it must return
source, units, layout.units, layout.members, source_roots, and
member_output_aliases (the last may be an explicit empty array). Missing or
invalid fields are projection errors; do not add a Rust-side generated-model
fallback. layout.units uses root-diagram coordinates, while each entry in
layout.members is local to the owning unit diagram; member overlaps are
checked within that unit coordinate system.
On native development checkouts, the active prelude and policy files are read
from assets/scripting/ at startup, so Rhai edits require a restart rather than
a Rust rebuild. A present editable directory is authoritative: unreadable or
empty directories and parse failures are errors. Packaged/wasm builds use their
compiled-in asset set because no editable source tree is available.
When reviewing a generated diagram, click its generated browser row first. A
single-unit network opens the unit-level class and shows its real members;
multi-unit networks open the root wrapper. Use FitCanvas after drill-in when
the tab was opened alongside the root, since navigation is scoped to the
focused Modelica tab.
For electrical generated networks, verify the unit diagram's labelled power
bus and follow at least one routed connect(...) branch through the rail. The
Rhai policy uses readable network_system/network_unit_N unit instances and a
topology-derived hub with adaptive branch lanes, so inspect a larger network
with FitCanvas rather than assuming the six-member demo's geometry scales.
Components that need directional presentation apply
LunCoModelicaTopologyAPI with source, storage, or load; this metadata
does not alter acausal solver direction.
Member icons must resolve from
their native Modelica classes; a fabricated card or direct solar-to-motor wire
is a projection defect, not an acceptable fallback.
When an authored Modelica endpoint also carries InputPorts, that component is
the single public command boundary. SetPorts and Rhai writes land there, and
the generic Modelica bridge mirrors only names accepted by the compiled model
into its solver input buffer. External live SetPorts commands with a stable
producer id enter the shared next-fixed-tick queue and are captured as ordered
named writes; Simulation-clock Rhai writes remain derived behavior. Do not add a
vehicle-specific setter. External API/direct and non-Simulation Rhai
ReleasePort/ReleaseControl commands use the same producer identity and
ordered session boundary. Releases clear local holds only; Twin policy sends
explicit setpoints with SetPorts. Battery
empty events use the authored 0.1% usable-storage reserve in Battery.mo, not
a solver-epsilon comparison.
Node movement has two valid outcomes. On an editable .mo document, drag a
component and verify that the standard annotation(Placement(...)) changes in
the source and survives a re-projection. On a generated document, the canvas
is intentionally read-only because USD plus the Rhai policy owns the source;
use Duplicate to edit, then perform the same placement check. A drag that
appears to work but disappears on reload is a product bug, not an acceptable
generated-model editing mode.
Use the shared AST strip_within_prefix for qualified lookup and editing;
similarly spelled package prefixes must not match an authored within package.
Reuse the AST's qualified_name_segments and parent_qualified for class paths;
quoted identifiers containing dots remain one segment. Extraction checks do not
prove the compiler accepts that qualified name: validate compilation separately
through its actual command/error boundary.
For class source extraction, reuse lunco-modelica-ast::ast_extract::class_full_text_span
from the same parsed bytes. Its inline seam test covers same-line enclosing
declarations and class qualifiers; do not derive declaration bounds by scanning
backward through arbitrary identifiers.
Read-only library views also require exact qualified identity. The generic
library extraction seam checks sibling leaf names and a missing sibling without
reading repository fixtures.
Duplicate admission pins its original target scope and resident source snapshot.
Check an exact nested qualified class when sibling packages share a short name;
known-source errors must report failure without installing a substitute document.
Closing the source or target lifetime during preparation must cancel publication
and release pending names, tabs and status. Use inline parser tests for span and
rewrite boundaries, and authored Rhai commands/queries for these public lifecycle
outcomes. assets/scenarios/tests/modelica_duplicate_lifecycle.rhai exercises
qualified siblings and quoted names, error diagnostics and exact-name reuse,
observed pending source-close cancellation, original-target Twin replacement
without retagging, and a valid successor. Run it in a UI-capable host with
Application/Retain lifetime and API-authored root_a, root_b, entry_scene
fixtures. Asynchronous folder scanning permits a duplicate to install while its
old Twin is live; the gate preserves that valid retained-source outcome. Exact
Twin/connection retirement of never-ready tasks belongs to the generic resource
seam test, since public folder replacement cannot force that worker boundary.
Native preparation runs on the existing task pool; browser Bevy tasks
retain the browser editor's deferred parsing contract.
Projection must remain responsive while a native package or inherited icon is
being resolved. Verify that /api/ready stays responsive, the canvas shows an
explicit loading/error state, and the completion event reprojects the authored
icons. Do not add a synchronous parse, mutex wait, invented icon, or domain
specific visual retry path to hide a miss.
Energy-flow animation is generic Modelica behavior, not generated-policy code:
LunCo.Electrical.Pin.i is a standard flow Real, just like the rocket and
lander FluidPort flow variables. Confirm the connector projection reports the
flow variable and that a non-zero live instance.p.i moves dots along the
rendered edge; zero current must remain visually idle. If dots are absent,
inspect the flow metadata and node-state keys at the shared canvas owner before
adding any policy-specific renderer.
Everything is one endpoint: POST /api/commands. The JSON shape is always
{"type":"ExecuteCommand","command":"<Name>","params":{...}}. Always include params even when
empty ("params":{}) — this keeps every request explicit and discoverable.
curl -s -X POST http://127.0.0.1:4101/api/commands \
-H "Content-Type: application/json" \
-d '{"type":"ExecuteCommand","command":"<Name>","params":{ ... }}'Two kinds of command share this envelope:
{"data":{"accepted":true}}; result-returning commands put their command-specific payload in the same data envelope.
Invalid parameters return HTTP 422. A deferred command may complete its
command acknowledgement later on the same request; that acknowledgement is
not necessarily completion of the domain work. In particular,
RunExperiment returns its exact experiment_id once the run is registered,
while the numerical solve continues asynchronously.{"runs":[...]}. ListRuns, GetExperimentResult, DescribeModel,
SnapshotVariables, CompileStatus, GetDiagnostics, ListCompileCandidates,
ListBundled, ListOpenDocuments, FindModel are all query providers —
invoked with the same tagged ExecuteCommand form. Built-in discovery and
entity listing use their own explicit type values.doc_id: 0 always means "the active document/tab".
| Interactive (live) | Batch (Fast Run / Experiment) | |
|---|---|---|
| Verb | RunActiveModel | FastRunActiveModel / RunExperiment |
| Pace | wall-clock realtime, steps forever | as fast as possible, t_start→t_end, then stops |
| Use for | inspection, physics-in-loop, 3D viz, possession | parameter sweeps, regression, "what if I bump this constant?" |
| Read results | SnapshotVariables (live), ReadPorts/WatchPorts | GetExperimentResult (full trajectory) |
| Poke inputs | SetModelInput (admitted for the next fixed tick in a live session) | overrides baked into the run request |
| Stored as | live stepping model | first-class Experiment in the registry (plot/compare) |
API=http://127.0.0.1:4101/api/commands
post(){ curl -s -X POST $API -H "Content-Type: application/json" -d "$1"; }
# 1. Open a model. Prefer the unified opener (bundled example / qualified source-library name / path):
post '{"type":"ExecuteCommand","command":"Open","params":{"uri":"bundled://SpringMass.mo"}}'
# bundled://Name.mo | Modelica.Blocks.Examples.PID_Controller | /abs/path.mo | mem://Untitled
# List embedded examples first: {"type":"ExecuteCommand","command":"ListBundled","params":{}}
# 2. Wait for the AST parse (background). Poll CompileStatus until ast_parsed:true:
post '{"type":"ExecuteCommand","command":"CompileStatus","params":{"doc_id":0}}' # -> {state, ast_parsed, candidates, picker_pending, ...}
# Read parser/compiler/lint findings and actionable Rumoca suggestions.
# Poll while complete is false; pending is not a clean result.
post '{"type":"ExecuteCommand","command":"GetDiagnostics","params":{"doc_id":0}}' # -> {state,complete,channels[],diagnostics:[{domain,source,code,severity,message,uri,line,column,suggestion}]}
# 3. Compile + play. class REQUIRED if the file has >1 non-package class
# (the GUI picker can't be shown over the API). Discover choices:
post '{"type":"ExecuteCommand","command":"ListCompileCandidates","params":{"doc_id":0}}' # -> {candidates:[{qualified,short}]}
post '{"type":"ExecuteCommand","command":"RunActiveModel","params":{"doc_id":0,"class":"SpringMass"}}'
# 4. Read live values (t + parameters + inputs + variables). Filter with names:
post '{"type":"ExecuteCommand","command":"SnapshotVariables","params":{"doc_id":0,"names":["x","v"]}}'
# 5. Poke a runtime input live (no recompile, admitted for the next fixed tick):
# For an open workbench model, use doc_id and keep producer_id stable.
post '{"type":"ExecuteCommand","command":"SetModelInput","params":{"doc_id":0,"name":"F","value":10.0,"producer_id":4101}}'
# For a live Twin participant, use its stable target_gid from ListEntities
# and leave doc_id at 0; do not pass both selectors.
post '{"type":"ExecuteCommand","command":"SetModelInput","params":{"doc_id":0,"target_gid":123456,"name":"throttle","value":0.5,"producer_id":4101}}'
# 6. Pause / Resume / Reset / Restart:
post '{"type":"ExecuteCommand","command":"PauseActiveModel","params":{"doc_id":0}}'
post '{"type":"ExecuteCommand","command":"RestartActiveModel","params":{"doc_id":0}}' # reset t=0 then runRunActiveModel = compile-if-stale then play. If already compiled & clean it
just unpauses (no recompile). CompileModel compiles only (stays paused);
ResumeActiveModel unpauses only.
If a live compile fails on an unbalanced DAE, its ordinary Modelica Error event
in Recent status events explains why simulation did not start and lists the
unknowns Rumoca's structural matcher could not pair with equations, plus their
categories and referencing equation rows. Selecting the row expands the full
message. GetDiagnostics also returns the explanation with the structured
compiler findings. Those names identify values the current equations cannot
determine; add or correct independent equations or constraints. The diagnostic
DAE is never simulated.
RunExperiment is the agent-facing sweep verb: overrides come from the
command, not the UI, so you can sweep parameters without touching source.
Each run is stored as an Experiment. Its command acknowledgement contains
the exact experiment_id after registration; the acknowledgement is not a
completed numeric result. Retain that id, poll RunStatus with it, and read the
trajectory with GetExperimentResult using the same id. Do not identify a run
by its label or by whichever run is newest.
Runs capture their exact ExperimentOrigin at admission: a pinned local document
runtime lifetime or an authenticated replicated connection/mount. Presentation
grouping never determines ownership. Definition replay under another origin
rejects before mutation; same-origin replay preserves terminal history. Closing that Twin
cancels unfinished runs and retires late updates and playback signals; completed
results stay queryable within the bounded history. Loose-document runs have
application lifetime. A run's execution definition freezes when its registry
row becomes Queued, before runner admission. Change bounds, parameters, or
inputs by creating a new run; retained results keep the definition that produced
them. An identical definition replay preserves later display labels and results,
and conflicting replay is rejected visibly.
A completion must match its immutable pending-handle origin before registry
publication. A completion from an inactive Twin cannot automatically
select the replacement Twin's plot, and a different pinned experiments document
cannot receive its automatic plot selection. Registry deletion and bounded
eviction also remove the retained document/owner attribution and plot visibility.
Closing a Twin retires its document pins and archived plot selections. A run
receives immutable source text at admission, and annotations are read from its
current document; a same-name model in another Twin cannot supply either. Native cancellation uses the admitted run flag at evaluation and simulation-driver
checkpoints. An executing numerical kernel returns before its next checkpoint;
no cancelled trajectory publishes, and worker exit releases the scheduler slot.
For a production lifecycle regression, admit a run from a Twin document and
queue another behind it, replace the Twin, then query both exact run ids for
Cancelled. Verify the replacement's plot and playback signals receive no old
completion. Include an application-owned loose-document run as a negative
ownership case, plus a completed run whose retained result remains readable.
For the same-name source/bounds regression, launch
RunScenarioAsset with source_asset: "lunco://scenarios/tests/modelica_run_admission_isolation.rhai" in an owned
UI-capable Modelica host. Its bounded asynchronous gate uses two scratch
documents, the ordinary RunExperiment acknowledgements and exact run ids,
and verifies that the unannotated document keeps the one-second default and
each trajectory retains its own admitted source. Require the authored
MODELICA_RUN_ADMISSION_ISOLATION verdict; launch acceptance alone is insufficient.
# One run with a parameter override + custom bounds + a label:
post '{"type":"ExecuteCommand","command":"RunExperiment","params":{
"doc_id":0, "class":"RocketStage",
"overrides":[{"name":"Isp","value":"300"}],
"inputs":[{"name":"throttle","value":"1.0"}],
"t_start":0, "t_end":120, "n_intervals":600,
"solver":"bdf", "tolerance":1e-6,
"label":"Isp=300"
}}'Sweep = loop the same call with different overrides + labels (one run each):
for isp in 280 300 320 340; do
post "{\"type\":\"ExecuteCommand\",\"command\":\"RunExperiment\",\"params\":{\"doc_id\":0,\"class\":\"RocketStage\",
\"overrides\":[{\"name\":\"Isp\",\"value\":\"$isp\"}],
\"t_end\":120,\"n_intervals\":600,\"label\":\"Isp=$isp\"}}"
doneoverrides / inputs are [{name, value}] with string values (string
injection, v1). overrides = top-level parameter literals; inputs =
runtime input variables.
t_start / t_end — sim horizon (seconds). Default from model annotation.dt — output Interval (seconds between samples). Mutually exclusive with…n_intervals — output NumberOfIntervals: emits n+1 evenly-spaced
samples. Takes precedence over dt when set.tolerance — solver tolerance.solver — family: "bdf"|"dassl"|"ida" → BDF; "esdirk34"|"rk"|"dopri"|"trbdf2"
→ ESDIRK34; "auto"/omit → backend default (BDF).h0 — initial step size (seconds).experiment(...) annotation, then
the backend default.Bounds admission rejects nonfinite or non-increasing horizons, nonpositive
explicit dt, tolerance, or h0, and output grids exceeding 200,000
intervals. n_intervals must be positive. Rejection returns the owning error
without registering a run or changing the requested grid. A used authored
NumberOfIntervals must also be a finite positive integer within that limit;
only authored Interval=0 has the documented omitted-spacing meaning.
QueryExperimentBounds reports invalid annotation bounds as a query error.
Production regression: attach
lunco://scenarios/tests/modelica_run_bounds_admission.rhai with
RunScenarioAsset to an addressable loaded scene root in an owned Modelica
host. It checks rejected explicit and authored bounds leave no experiment
rows, then requires a valid successor to complete.
FastRunActiveModel is the same batch engine but reads bounds from the UI
"Simulation Setup" draft instead of the command — prefer RunExperiment for
scripted/agent runs so everything is explicit.
For Rhai callers, cmd("RunExperiment", ...) can return a pending command
record while the deferred acknowledgement is being assembled. Poll
command_result(command_id) only until that acknowledgement supplies the
experiment_id; then poll RunStatus by that exact experiment id. The
modelica_editor::experiment_ticket / poll_experiment_ticket helpers wrap
both phases in a bounded, non-blocking caller-owned ticket. Keep the returned
ticket across ticks, and do not block the Editor/Rhai thread in a wait loop.
The ticket also binds readback to the explicit Modelica document and source
generation so a changed model cannot be mistaken for the solved source.
# List runs (newest first). Optional {"doc_id":N} filter. Each row is self-describing:
# experiment_id, name, state (Pending|Queued|Running|Done|Failed|Cancelled),
# wall_time_ms, the overrides that produced it, and the bounds it ran under.
post '{"type":"ExecuteCommand","command":"ListRuns","params":{}}'
# Pull a full trajectory: times + series (dotted Modelica path -> samples).
# For an explicit RunExperiment, always use its exact experiment_id:
post '{"type":"ExecuteCommand","command":"GetExperimentResult","params":{
"experiment_id":"<id returned by RunExperiment>",
"variables":["altitude","velocity"], "max_points":500
}}'
# max_points = strided downsample, final sample always kept. Omit = uncapped.
# Returns {state:"Done", times:[...], series:{"altitude":[...], ...}} or an
# error if the run is not Done (Pending/Running/Failed-without-partial).RunStatus is the query provider for one run's progress and terminal state:
post '{"type":"ExecuteCommand","command":"RunStatus","params":{"experiment_id":"<exact id>"}}'Poll until done, failed, or cancelled; only request the trajectory after
done. ListRuns is useful for discovery and UI review, not as a substitute
for retaining the id returned by the dispatch you just made.
A native worker panic, thread-admission failure, or disconnect without a
terminal result produces failed with its cause and retires the handle.
Live-worker startup or transport failure produces a worker-wide typed diagnostic,
holds the affected simulation, and rejects subsequent live compiles. Scene reload
does not restart a failed application worker; restart the owned app after resolving
the reported startup problem.
The scheduler releases the worker slot on every exit. A compiler poisoned by a
panic rejects subsequent compilation visibly; treat that diagnostic as a
failed run rather than polling indefinitely.
Cancel / clean up:
post '{"type":"ExecuteCommand","command":"CancelExperiment","params":{"all":true}}' # or {"experiment_id":"<uuid>"}
post '{"type":"ExecuteCommand","command":"DeleteExperiment","params":{"all":true}}' # terminal runs only
post '{"type":"ExecuteCommand","command":"RenameExperiment","params":{"experiment_id":"<uuid>","name":"baseline"}}'The Experiments panel is the comparison view — unlike Dymola/OMEdit you
don't juggle .mat filenames. It's one multi-series plot that draws a curve
for every visible run × every picked variable. So:
altitude, velocity) = which series shape.Done — no re-plotting.Two pickers live on the panel header (GUI): ▾ Variables N/M (which signals) and ▾ Runs (which completed runs to overlay). Y-axis auto-groups by unit.
API=http://127.0.0.1:4101/api/commands
post(){ curl -s -X POST $API -H "Content-Type: application/json" -d "$1"; }
# Open a plot tab seeded with the variables to compare across runs.
# source=0 = fresh panel; source=<VizId> = clone another plot's signal set + picks.
post '{"type":"ExecuteCommand","command":"NewPlotPanel","params":{"title":"Ascent","signals":["altitude","velocity"],"source":0}}'
# Add another signal to an existing plot (plot=0 = the default graph):
post '{"type":"ExecuteCommand","command":"AddSignalToPlot","params":{"plot":0,"signal":"mass"}}'signals in NewPlotPanel become the plot's picked variables; every
completed run then contributes those series. Run one sweep (§4), open the plot
once with the variables you care about, and each new run lands on the same axes.
# 1. sweep 4 runs (see §4 loop) with labels Isp=280..340
# 2. open the comparison plot on the variable of interest
post '{"type":"ExecuteCommand","command":"NewPlotPanel","params":{"title":"Isp sweep","signals":["altitude"],"source":0}}'
# 3. confirm the runs landed, then screenshot for the human
post '{"type":"ExecuteCommand","command":"ListRuns","params":{}}'
curl -s -X POST $API -H "Content-Type: application/json" \
-d '{"type":"ExecuteCommand","command":"CaptureScreenshot","params":{}}' -o /tmp/sweep.png # then Read the PNGGetExperimentResult (§5). Raw times+series;
compare runs by fetching each experiment_id and diffing arrays. Never scrape
a plot widget for values.CaptureScreenshot (needs the UI build, not --no-ui).GetExperimentResult;
for scripted export just persist the GetExperimentResult JSON yourself.Discovery / docs
| command | params | returns / effect |
|---|---|---|
Ping | {} | readiness check |
CreateNewScratchModel | {source, name} | create a Modelica Editor document and return its exact doc_id |
ListBundled | {} | embedded example models (bundled:// URIs) |
FindModel | {query, limit?} | fuzzy search examples/Twin/source libraries/open docs → URIs |
Open | {uri} | open bundled/source-library/path/mem into a tab |
ListOpenDocuments | {} | doc_id, title, kind, origin, dirty, active per tab |
DescribeModel | {doc, class?} | AST: components, connections, inputs, parameters, outputs (pre-compile) |
CompileStatus | {doc} | state, ast_parsed, candidates, picker_pending, drilled_in_class |
GetDiagnostics | exactly one of {doc_id} or {scope} | shared parser/compiler/lint diagnostics; poll complete, then read channel states, stable codes, source locations, and suggestions. scope is loaded_stages or twin |
ListCompileCandidates | {doc} | {candidates:[{qualified,short}]} — the picker choices |
Compile & run
| command | params | effect |
|---|---|---|
CompileModel | {doc, class?, force?, resume_after_compile?} | compile only (stays paused) |
RunActiveModel | {doc, class?} | compile-if-stale + play (live) |
PauseActiveModel / ResumeActiveModel / ResetActiveModel | {doc} | live stepping control |
RestartActiveModel | {doc} | reset t=0 then run |
FastRunActiveModel | {doc, class?, t_end?, dt?, n_intervals?, tolerance?, solver?, h0?} | batch, bounds from UI draft |
RunExperiment | {doc, class?, overrides[], inputs[], t_start?, t_end?, dt?, n_intervals?, tolerance?, solver?, h0?, label?} | dispatch a batch run; acknowledgement returns exact experiment_id |
SetModelInput | {doc_id, target_gid?, name, value, producer_id?} | select an editor model by doc_id or a live Twin participant by target_gid; live API, direct typed, and actorless Rhai callers need a stable nonzero producer_id |
ConfirmClassPicker | {qualified?, cancel?} | only if a picker modal opened in the GUI |
Results & viz
| command | params | returns / effect |
|---|---|---|
SnapshotVariables | {doc, names?} | one-shot live {t, parameters, inputs, variables} |
ListRuns | {doc?} | experiment rows (newest first) |
RunStatus | {experiment_id} | one run's progress/terminal state |
GetExperimentResult | {experiment_id? | doc, variables?, max_points?} | full trajectory {times, series} |
CancelExperiment / DeleteExperiment / RenameExperiment | see §5 | run lifecycle |
NewPlotPanel / AddSignalToPlot | see §6 | plotting |
CaptureScreenshot | {} | raw PNG bytes (save -o, then Read) |
Direction-to-joint controller: write the coordinate contract before changing equations: world direction, inverse mount frame, joint axes/order, and the mesh's physical boresight. A compiling model or its own zero error is insufficient; inspect the live direction inputs, setpoints, measured joint angles, and rendered mechanism after a full scene reload.
Missing params → silent no-op. Always send "params":{}.
Multi-class file → compile/run need class. Without it, if >1
non-package class the run aborts with picker_pending (the GUI would show a
modal). Call ListCompileCandidates first, pass the short or qualified name.
Fire before parse → no compilable top-level class. Poll CompileStatus
until ast_parsed:true before compiling/running a just-opened doc.
GetExperimentResult errors unless the run is Done (or Failed with a
partial). Check ListRuns state first; a big sweep runs async.
Unified opening: prefer Open{uri}. OpenClass resolves a Modelica
class through the source-aware document/library path; OpenFile resolves a
filesystem URI.
File lifetime: native file opens pin canonical local/replicated root ownership before installation; browser mounted files read OPFS, while picker/private saves have Application lifetime. Closing the admitted owner retires file work even when the source remains in the editor registry. Dirty source cannot transfer owners through a path reopen; save or close it before a clean explicit reopen. Alias reopens resolve source and resident identities on the file worker. Their captured owner/generation must still match at install, so a late read cannot replace a concurrently changed or newly installed different-owner source.
Browser imports and saves: shared picker results carry request-owned bytes into the existing asynchronous file-load pipeline; same-name picks create distinct pathless Application documents. Browser Save marks the document saved only after download admission succeeds. Verify cancellation/read failure, same-name overlapping reads and App teardown through the shared picker browser tests; see the picker owner contract.
Portable Twin saves: Save All and Save As Twin preflight generated filenames
with the shared lunco-assets-path component validator before any save or manifest
command. Reserved device names (even with .mo), final dots/spaces and forbidden
characters reject visibly; no replacement filename hides invalid state. Rename
uses lossless command paths and confines the actual source parent through Storage.
Verify name algebra with the asset-path tests and source scope through the authored
modelica_save_all_scope.rhai production gate; these prove different boundaries.
Complete result admission: finite ordered times, matching series/metadata
lengths, and finite values are required before a trajectory is marked Done.
experiments.result_limits supplies the shared budgets; defaults are 8,000,000
scalar values and 256 MiB artifact bytes. Failed partial streams may retain
explicit missing-value holes. A malformed optional artifact warns without
replacing a valid runtime result.
Native and browser Fast Runs capture the same limits at admission. Actual
lowered output dimensions and the requested grid are checked before batch
trajectory allocation; event samples also consume the scoped recorder budget.
Exercise modelica_output_budget.rhai with the documented default value cap
and max_parallel=1 to prove visible rejection and valid successor completion.
Durable batch history: completed Twin-owned results persist asynchronously
with their immutable definition and actual compiler source CID. Application
runs have no Twin destination. Inspect source_cid and restored_history in
GetExperimentResult; an archived result never claims the currently edited
source or starts playback. Parsed-only contributing libraries without source
bytes warn that persistence is unavailable while the run remains valid.
Exercise modelica_artifact_history.rhai in fresh seed/restore sessions and
verify the UUID artifact is durable before stopping the seed session. Seed
creates a fresh Twin around its API-authored scene; restore opens the saved
Twin through OpenTwin. Include
a corrupt optional artifact and changed same-name source; history must retain
its original CID and values. See the artifact owner contract.
File diagnostics: GetFile acknowledges asynchronous read admission. It
uses the same captured native/OPFS source path as document opens; inspect its
log text or structured read-error diagnostic. Closing the admitted Twin or
replicated lifetime retires the pending request before publication.
Live ≠ batch: SnapshotVariables reads the live stepping model;
GetExperimentResult reads a stored batch run. They are different objects.
Blank plot/diagram in luncosim → the Modelica perspective
isn't active. ActivatePerspective{"id":"modelica_analyze"} before capturing
(§0). In lunica it's already the whole app. Commands/results don't need it —
only the visible panels do.
Don't restart to "start clean" — drive the API to add the state you need.
MCP fallback: if the user insists on MCP, every command above maps to an
mcp__lunco__* tool (compile_model, run_scenario→rhai only, set_input,
snapshot_variables, read_ports, describe_model, find_model,
open_uri, list_bundled, list_open_documents). Batch experiment verbs
(RunExperiment/ListRuns/GetExperimentResult) have no dedicated MCP
tool — use curl (or the generic mcp__lunco__execute_command).
Use the reusable components/power/solar_panel.usda probe and Sun-direction
connections. A generated assembly exposes target_mount_x/y/z boundary inputs
from the panel's Environment.outputs:sun_mount_* source; inherit the panel's
input wiring. Keep parameters:area as a parameter and author only inputs that
the current Modelica source declares.
Observe delivered power together with generated current and shared terminal voltage. The panel's public voltage/current/available-power channels target its physical USD prim and resolve through the generated participant. Bus voltage can remain positive at night while solar current is zero. To verify charging, use an owned session with a temporary partly discharged battery and observe SOC rising; a full pack cannot rise above 100%. Do not persist diagnostic battery overrides.
Omitted inputs retain the owning Modelica library's defaults, including nested components in generated USD networks. Explicit authored inputs take precedence. The worker's initialized solver observation supplies runtime readback; do not copy defaults into each Twin to compensate for a lifecycle bridge replacing unbound slots with zero. Verify after advancing physics, not only at compile time.
Rumoca owns these defaults as qualified DAE input initialization expressions;
internal and connected bindings remain equation-owned. Verify class and instance
isolation, override, reset, batch execution, and invalid-default diagnostics with
modelica_scoped_input_defaults.rhai in an owned production session.
Run the focused production regression after building the normal luncosim:
LUNCOSIM_BIN=target/debug/luncosim LUNCOSIM_EPHEMERAL_SETTINGS=1 \
LUNCOSIM_ISOLATED_RUN=1 python3 scripts/api/run_editor_scene_test.py \
--port 4261 --timeout 90 --scene scenes/fixtures/usd_query_api/site.usda \
--scenario lunco://scenarios/tests/modelica_scoped_input_defaults.rhai \
--log target/modelica-scoped-input-defaults.logThe fixture admits a Twin owner; the runner attaches the observer to that owner, requires a real Rhai verdict, then verifies API Exit and port release.
Modelica index warming reads LUNCOSIM_WARM_DIRS as the operating system's
path list: colon-separated on Unix and semicolon-separated on Windows, so
Windows drive letters remain intact. Shipped package roots use the fallible
asset-library resolver; root failures are reported before admitting sources.
USD participant/network source loads use the stage's prepared typed load
address, retaining literal filenames and native reference admission during
initial load and parameter recompilation.
Program format selection preserves # in named/native filenames; HTTP source
URLs use their path component when selecting the executor.
Twin Modelica directories may use . to designate the admitted Twin root;
the directory resolver preserves this manifest semantic without permitting
parent traversal or using it as a concrete file address.
© LunCoSim, Apache-2.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
Just SKILL.md in skills/run-modelica of LunCoSim/lunco-sim.
Open the folder on GitHubat commit 43f1301
Run Modelica next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Run Modelica this skillLunCoSim/lunco-sim | 107 | — | ~13k | Automated safety check: Pass | Apache-2.0 | |
| Tandem Browserhydro13/tandem-browser | 616 | — | ~9.1k | Automated safety check: Pass | MIT | |
| MCP Apps Builderawslabs/cli-agent-orchestrator | 1.4k | — | ~1.7k | Automated safety check: Pass | Apache-2.0 | |
| Openmaopenma-ai/open-managed-agents | 315 | — | ~854 | Automated safety check: Pass | Apache-2.0 | |
| Pixiu MCP Gatewayapache/dubbo-go-pixiu | 567 | — | ~3.1k | Automated safety check: Pass | Apache-2.0 | |
| Test MCPtomaspavlin/rohlik-mcp | 121 | — | ~593 | Automated safety check: Notes | MIT |
hydro13/tandem-browser
Use Tandem Browser's MCP server (local and remote agents) or HTTP API (local and remote agents) to inspect, browse, and interact with the user's shared browser safely.
awslabs/cli-agent-orchestrator
Load the official MCP Apps builder skills (create-mcp-app, migrate-oai-app, add-app-to-server, convert-web-app) from github.com/modelcontextprotocol/ext-apps.
openma-ai/open-managed-agents
Use the openma platform to build, deploy, and manage AI agents.
apache/dubbo-go-pixiu
Creates and validates dubbo-go-pixiu MCP gateway conf.yaml. An agent skill from apache/dubbo-go-pixiu.
tomaspavlin/rohlik-mcp
Build and test MCP tools using direct API calls or MCP Inspector.
BarneyD66/clipmivo-tools
Create and manage AI video tasks through ClipmivoAI using its MCP server, CLI or REST API.
LunCoSim/lunco-sim
Generate concise LunCoSim nightly GitHub release notes with platform downloads, installation guidance, an AI-agent mission prompt, and a changelog link.
LunCoSim/lunco-sim
Build or repair a reusable scene component through a live LunCoSim Editor session.
LunCoSim/lunco-sim
Build or review a componentized LunCoSim USD assembly with a realistic, dimensionally checkable presentation.
LunCoSim/lunco-sim
Author and review LunCoSim behavioral, asset-backed, component, mission, visual, and requirements-verification tests.
LunCoSim/lunco-sim
Create, extend, register, or debug a reusable LunCoSim Rhai tool library for live USD authoring, component linting, inspection, or test support.
LunCoSim/lunco-sim
Author an interactive tutorial, guided lesson, onboarding flow, coach-mark tour, or objectives checklist in LunCoSim.
Works with
Categories
Recipe for running Modelica models and building experiments/graphs in lunica (LunCoSim), driven from the HTTP API with curl. Run Modelica is an agent skill from LunCoSim/lunco-sim. Recipe for running Modelica models and building experiments/graphs in lunica (LunCoSim), driven from the HTTP API with curl.
Run Modelica fits situations like: ever you need to: launch the workbench; open/compile a Modelica model; run it live (interactive realtime); as a fast batch.
Run `npx skills add LunCoSim/lunco-sim --skill run-modelica -a claude-code`. Or copy the skill folder (skills/run-modelica in LunCoSim/lunco-sim) into .claude/skills/run-modelica in your project. Claude Code loads it when a task matches its description.
Run `npx skills add LunCoSim/lunco-sim --skill run-modelica -a codex`. Or copy the skill folder (skills/run-modelica in LunCoSim/lunco-sim) into .agents/skills/run-modelica in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add LunCoSim/lunco-sim --skill run-modelica -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/run-modelica, .gemini/skills/run-modelica, .github/skills/run-modelica and .opencode/skills/run-modelica in your project.
Going by SKILL.md and its folder, Run Modelica needs the command-line tools its instructions call (curl, cargo and python3).
SKILL.md contains no URLs. Its commands use curl, which can reach the network depending on how they are called. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
Run Modelica is published under the Apache-2.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 13k tokens (SKILL.md is roughly 53k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
Skills that share tags, products or a category with Run Modelica: Tandem Browser (hydro13/tandem-browser, 616 stars), MCP Apps Builder (awslabs/cli-agent-orchestrator, 1.4k stars), Openma (openma-ai/open-managed-agents, 315 stars) and Pixiu MCP Gateway (apache/dubbo-go-pixiu, 567 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
LunCoSim (a GitHub organization) maintains it in LunCoSim/lunco-sim, which has 107 GitHub stars. The repository holds 40 skills in this directory. The repository was last updated on October 10, 2026.
Source: LunCoSim/lunco-sim on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.