git clone https://github.com/svd-ai-lab/sim-cli.git
cd sim-cli
uv pip install -e ".[dev]"
pytest -q # unit tests (no solver needed)
pytest -q -m integration # integration tests (need solvers + sim serve)
ruff check src/sim testsDrop a DriverProtocol implementation under src/sim/drivers/<name>/driver.py, register it in drivers/__init__.py, and you're done. See pybamm/driver.py for the smallest reference; fluent/ for a full persistent-session driver.
The server routes all drivers through DriverProtocol — no server.py changes needed. Set supports_session = True for persistent-session drivers, False for one-shot only.
src/sim/
cli.py Click app, all subcommands
server.py FastAPI server (sim serve)
session.py HTTP client used by connect/exec/inspect
driver.py DriverProtocol + result dataclasses
compat.py Version-compat profiles + layered skill resolution
drivers/
fluent/ Reference: persistent-session driver
(driver.py + runtime.py + queries.py)
pybamm/ Reference: smallest one-shot driver
flotherm/ GUI automation driver (Win32 + UIA backend)
… one folder per registered backend
__init__.py DRIVERS registry — register new backends here
tests/ unit tests + fixtures (84 tests)
assets/ logo · banner · architecture (SVG)
docs/ translated READMEs (de · ja · zh) + architecture docs
Auto-restarts the server when source files change. Useful during driver development:
sim serve --reloadConvenience flag that tears down the session and stops the server in one call (equivalent to sim disconnect && sim stop):
sim disconnect --stop-serverGates dangerous features behind an env var. Currently:
- Flotherm
#!pythonexec — raw Python execution through the Flotherm driver is blocked unlessSIM_DEV_MODE=1is set.
Skills in sim-skills use a layered directory structure to handle SDK and solver version differences:
sim-skills/<driver>/
base/ shared — always loaded
sdk/<sdk_version>/ override when SDK API differs
solver/<solver_version>/ override when solver behavior differs
SKILL.md index
Resolution order: solver → sdk → base (last-declaring layer wins per file).
Each driver's compatibility.yaml declares active_sdk_layer and active_solver_layer per profile. The server returns these in the /connect response so the agent knows which skill layer to use.
Drivers without version-sensitive SDK content omit sdk/; drivers without solver-version differences omit solver/. The base/ layer is always present.
Cross-check: verify_skills_layout(root, profiles) in compat.py validates that every declared layer has a matching on-disk directory.
docs/architecture/version-compat.md— profile env designdocs/architecture/skills-layering-plan.md— layered skill composition design