Metadata-Version: 2.4
Name: sim-cli-core
Version: 0.3.4
Summary: Make every engineering tool agent-native — a CLI runtime that lets LLM agents launch, drive, and observe CAD/CAE software
Project-URL: Homepage, https://github.com/svd-ai-lab/sim-cli
Project-URL: Repository, https://github.com/svd-ai-lab/sim-cli
Project-URL: Issues, https://github.com/svd-ai-lab/sim-cli/issues
Project-URL: Documentation, https://github.com/svd-ai-lab/sim-cli#readme
Project-URL: Changelog, https://github.com/svd-ai-lab/sim-cli/blob/main/CHANGELOG.md
Author-email: Weiqi Ji <jiweiqi10@gmail.com>
License-Expression: Apache-2.0
License-File: LICENSE
License-File: NOTICE
Keywords: agent,agentic,cad,cae,cfd,fea,llm,out-of-tree,plugins,simulation
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Science/Research
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Scientific/Engineering
Classifier: Topic :: Scientific/Engineering :: Physics
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.10
Requires-Dist: click>=8.0
Requires-Dist: fastapi>=0.115
Requires-Dist: httpx>=0.28
Requires-Dist: lxml>=5.0
Requires-Dist: pillow>=10
Requires-Dist: psutil>=5.9; sys_platform == 'win32'
Requires-Dist: pywinauto>=0.6.8; sys_platform == 'win32'
Requires-Dist: pyyaml>=6.0
Requires-Dist: tomli>=2.0; python_version < '3.11'
Requires-Dist: uvicorn>=0.34
Provides-Extra: dev
Requires-Dist: pytest>=8.0; extra == 'dev'
Requires-Dist: ruff>=0.4; extra == 'dev'
Description-Content-Type: text/markdown

<div align="center">

<img src="assets/banner.svg" alt="sim — the container runtime for physics simulations" width="820">

<br>

**Make every engineering tool agent-native.**

*Today's CAD and CAE software was built for engineers clicking through GUIs.*
*Tomorrow's user is an LLM agent — and it needs a way in.*

<p align="center">
  <a href="#-quick-start"><img src="https://img.shields.io/badge/Quick_Start-2_min-3b82f6?style=for-the-badge" alt="Quick Start"></a>
  <a href="#-solver-registry"><img src="https://img.shields.io/badge/Solvers-growing_registry-22c55e?style=for-the-badge" alt="Growing solver registry"></a>
  <a href="https://github.com/svd-ai-lab/sim-skills"><img src="https://img.shields.io/badge/Agent_Skills-sim--skills-8b5cf6?style=for-the-badge" alt="Companion skills"></a>
  <a href="LICENSE"><img src="https://img.shields.io/badge/License-Apache_2.0-eab308?style=for-the-badge" alt="License"></a>
</p>

<p align="center">
  <img src="https://img.shields.io/badge/python-3.10--3.12-3776AB?logo=python&logoColor=white" alt="Python">
  <img src="https://img.shields.io/badge/CLI-Click_8-blue" alt="Click">
  <img src="https://img.shields.io/badge/server-FastAPI-009688?logo=fastapi&logoColor=white" alt="FastAPI">
  <img src="https://img.shields.io/badge/transport-HTTP%2FJSON-orange" alt="HTTP/JSON">
  <img src="https://img.shields.io/badge/status-alpha-f97316" alt="Status: alpha">
</p>

**English** · [Deutsch](docs/README.de.md) · [日本語](docs/README.ja.md) · [中文](docs/README.zh.md)

[Why sim](#-why-sim) · [Quick Start](#-quick-start) · [Solvers](#-solver-registry) · [Commands](#-commands) · [Skills](https://github.com/svd-ai-lab/sim-skills)

</div>

---

## 🤔 Why sim?

LLM agents already know how to write simulation scripts — training data is full of them. What they *don't* have is a standard way to **launch a solver, drive it step by step, and observe what happened** before deciding the next move.

Today, the choices are awful:

- **Fire-and-forget scripts** — agent writes 200 lines, runs the whole thing, an error at line 30 surfaces as garbage at line 200, no introspection, no recovery.
- **Bespoke wrappers per solver** — every team rebuilds the same launch / exec / inspect / teardown loop in a different shape.
- **Closed proprietary glue** — vendor SDKs that don't compose, don't share a vocabulary, and don't speak HTTP.

`sim` is the missing layer:

- **One CLI**, one HTTP protocol, **a growing driver registry** spanning CFD, multiphysics, thermal, pre-processing, and beyond.
- **Persistent sessions** the agent introspects between every step.
- **Remote-by-default** — the CLI client and the live solver can sit on different machines (LAN, Tailscale, HPC head node).
- **Companion agent skills** that teach an LLM how to drive each backend safely.

> Like a container runtime standardized how Kubernetes talks to containers, **sim** standardizes how agents talk to solvers.

---

## 🏛 Architecture

<div align="center">
  <img src="assets/architecture.svg" alt="sim architecture: CLI client over HTTP/JSON to a sim serve FastAPI process holding a live solver session" width="900">
</div>

Two execution modes from the same CLI, sharing the same `DriverProtocol`:

| Mode | Command | When to use it |
|---|---|---|
| **Persistent session** | `sim serve` + `sim connect / exec / inspect` | Long, stateful workflows the agent inspects between steps |
| **One-shot** | `sim run script.py --solver X` | Whole-script jobs you want stored as a numbered run in `.sim/runs/` |

For the full driver protocol, server endpoints, and execution pipeline see [CLAUDE.md](CLAUDE.md).

---

## 🚀 Quick Start

> **Names at a glance:** repo `svd-ai-lab/sim-cli` · PyPI distribution `sim-cli-core` · console command `sim` · import `import sim`. Yes, three different strings — the repo name predates the PyPI publish; the rest follow Python packaging convention.

Prereq: [`uv`](https://docs.astral.sh/uv/) — install with `curl -LsSf https://astral.sh/uv/install.sh | sh` (macOS / Linux) or `irm https://astral.sh/uv/install.ps1 | iex` (Windows PowerShell).

**macOS / Linux:**

```bash
# 1. On the host that has the solver installed, install sim core only
#    — no driver choice yet:
uv pip install sim-cli-core

# 2. Install the plugin for the solver you actually want:
sim plugin install sim-plugin-ltspice

# 3. Tell sim to look at this machine and pick the right SDK profile:
sim check <solver>
# → reports detected installs of <solver> and the profile they resolve to

# 4. Bootstrap that profile env (creates .sim/envs/<profile>/ with the
#    pinned SDK; or pass --auto-install to step 5 to do it inline):
sim env install <profile>

# 5. Start the server (only needed for remote / cross-machine workflows):
sim serve --host 0.0.0.0          # FastAPI on :7600

# 6. From the agent / your laptop / anywhere on the network:
sim --host <server-ip> connect --solver <solver> --mode solver --ui-mode gui
sim --host <server-ip> inspect session.versions   # ← always do this first
sim --host <server-ip> exec "<solver-specific snippet>"
sim --host <server-ip> screenshot -o shot.png
sim --host <server-ip> disconnect
```

**Windows (PowerShell):**

```powershell
# 1. On the host that has the solver installed, install sim core only
#    — no driver choice yet:
uv pip install sim-cli-core

# 2. Install the plugin for the solver you actually want:
sim plugin install sim-plugin-ltspice

# 3. Tell sim to look at this machine and pick the right SDK profile:
sim check <solver>

# 4. Bootstrap that profile env (or pass --auto-install to step 5):
sim env install <profile>

# 5. Start the server (only needed for remote / cross-machine workflows):
sim serve --host 0.0.0.0          # FastAPI on :7600

# 6. From the agent / your laptop / anywhere on the network:
sim --host <server-ip> connect --solver <solver> --mode solver --ui-mode gui
sim --host <server-ip> inspect session.versions   # ← always do this first
sim --host <server-ip> exec "<solver-specific snippet>"
sim --host <server-ip> screenshot -o shot.png
sim --host <server-ip> disconnect
```

That's the full loop: **detect → bootstrap → launch → drive → observe → tear down** — with the engineer optionally watching the solver GUI in real time.

> **Why the bootstrap step?** Each `(solver, SDK, driver, skill)` combo is
> its own compatibility universe — different solver releases may want
> different SDK versions, and those SDK versions can't always coexist in
> one Python env. sim treats each combo as an isolated "profile env" so
> you can keep multiple versions on one machine without dependency
> conflicts. The contract is in
> [`docs/architecture/version-compat.md`](docs/architecture/version-compat.md).

---

## 📦 Plugin sources

`sim plugin install <source>` accepts explicit install sources only:

- Exact package specs, such as `sim-plugin-ltspice` or `sim-plugin-ltspice==0.2.3`
- Package specs plus private indexes, such as `sim-plugin-mechanical --extra-index-url https://example.com/simple/`
- Direct wheel/sdist URLs, such as `https://example.com/sim_plugin_ltspice-0.2.3-py3-none-any.whl`
- Git URLs, such as `git+https://github.com/<org>/sim-plugin-<name>`
- Local plugin directories, wheels, and sdists

Discovery is separate from installation:

```bash
sim plugin catalog              # official plugins (display + copy-paste install string)
sim plugin list                 # installed/registered plugins on this machine
```

Short solver aliases such as `ltspice` are catalogue names, not install sources. Run `sim plugin catalog` to find the recommended install string for each plugin, then pass it to `sim plugin install`.

---

## 🧪 Solver registry

`sim-cli` core is **fully solver-agnostic** — it ships with **zero built-in drivers**. Every solver is reached through a **plugin package** registered via the `sim.drivers` entry-point group. Adding a new backend is a ~200-LOC `DriverProtocol` implementation in its own `sim-plugin-<name>` repo.

`sim` is most useful for **GUI-heavy solvers** — COMSOL, ANSYS Mechanical, ANSYS Fluent, MATLAB Simulink, Abaqus, Flotherm — where every agent iteration would otherwise mean clicking through dialog boxes.

Install from a discovered package, then list what is installed locally:

```bash
sim plugin catalog              # discover what's available + install strings
sim plugin install sim-plugin-ltspice
sim plugin list                 # show installed plugins
```

Reference implementation to read for shape: [`sim-plugin-ltspice`](https://github.com/svd-ai-lab/sim-plugin-ltspice).

**Private plugins** (vendor-IP-sensitive backends) install through explicit URLs, private repos, or private Python indexes — same `sim plugin install` flow:

```bash
sim plugin install git+https://github.com/<org>/sim-plugin-<name>
# (you need read-access to the repo; without it, git clone returns 401)

sim plugin install sim-plugin-mechanical --extra-index-url https://example.com/simple/
# standard PEP 503/private-index path for commercial wrappers
```

Per-solver protocols, snippets, and demo workflows live in [`sim-skills`](https://github.com/svd-ai-lab/sim-skills) and the per-plugin repos.

---

## ✨ Features

### 🧠 Built for agents
- **Persistent sessions** that survive across snippets — never restart the solver mid-task
- **Step-by-step introspection** with `sim inspect` between every action
- **Pre-flight `sim lint`** catches missing imports and unsupported APIs before launch
- **Numbered run history** in `.sim/runs/` for one-shot jobs, browsable via `sim logs`

### 🔌 Solver-agnostic
- **One protocol** (`DriverProtocol`) — every driver is ~200 LOC, shipped as its own `sim-plugin-<name>` package via Python entry points
- **Persistent + one-shot** from the same CLI — no separate client per mode
- **Plugin discovery + explicit installs** — `sim plugin catalog` discovers available plugins; `sim plugin install` accepts exact package specs, private indexes, direct URLs, git URLs, and local artifacts
- **Companion skills** in [`sim-skills`](https://github.com/svd-ai-lab/sim-skills) so an LLM picks up each new backend without prior context

### 🌐 Remote-friendly
- **HTTP/JSON transport** — runs anywhere `httpx` runs
- **Client / server split** — agent on a laptop, solver on an HPC node, GUI on a workstation
- **Tailscale-ready** — designed for cross-network mesh deployments

---

## ⚙️ Commands

| Command | What it does | Analogy |
|---|---|---|
| `sim plugin catalog` | Discover available solver plugins | `npm search` |
| `sim plugin list / install / uninstall` | Manage installed plugins from explicit install sources | `npm install` |
| `sim check <solver>` | Detect installations + resolve a profile | `docker info` |
| `sim env install <profile>` | Bootstrap a profile env (venv + pinned SDK) | `pyenv install` |
| `sim env list [--catalogue]` | Show bootstrapped envs (and the full catalogue) | `pyenv versions` |
| `sim env remove <profile>` | Tear down a profile env | `pyenv uninstall` |
| `sim serve` | Start the HTTP server (for cross-machine use) | `ollama serve` |
| `sim connect` | Launch a solver, open a session | `docker start` |
| `sim exec` | Run a Python snippet inside the live session | `docker exec` |
| `sim inspect` | Query live session state (incl. `session.versions`) | `docker inspect` |
| `sim ps` | Show the active session and its profile | `docker ps` |
| `sim screenshot` | Grab a PNG of the solver GUI | — |
| `sim disconnect` | Tear down the session | `docker stop` |
| `sim stop` | Stop the sim-server process | `docker rm -f` |
| `sim run` | One-shot script execution | `docker run` |
| `sim lint` | Pre-flight static check on a script | `ruff check` |
| `sim logs` | Browse stored run history | `docker logs` |

Every command that touches a host (`check`, `env`, `connect`, `exec`, `inspect`, `disconnect`) accepts `--host <ip>` and runs against a remote `sim serve` instead of the local machine.

Environment: `SIM_HOST`, `SIM_PORT` for the client; `SIM_DIR` (default `.sim/`) for run storage and profile envs.

### Choosing a profile

You don't usually have to. `sim check <solver>` tells you which profile your installed solver maps to, and `sim connect ... --auto-install` will bootstrap it for you on first use. The escape hatches:

- **Pin a specific profile:** `sim connect --solver <solver> --profile <profile>`
- **Skip the profile env entirely (legacy / tests):** `sim connect --solver <solver> --inline`
- **Power-user single-env install:** install the matching plugin package directly into your current venv (e.g. `pip install <plugin-package>`). Skips `sim env` entirely; OK when you only need one solver version on this machine.

The full design is in [`docs/architecture/version-compat.md`](docs/architecture/version-compat.md).

---

## 🆚 Why not just run scripts?

| Fire-and-forget script | sim |
|---|---|
| Write the whole thing, run, hope it converges | Connect → execute → observe → decide next step |
| An error at step 2 surfaces at step 12 | Each step verified before the next is sent |
| Agent has no view of solver state | `sim inspect` between every action |
| Solver restarts on every iteration | One persistent session, snippets at will |
| GUI invisible to the human | Engineer watches the GUI while the agent drives |
| Output parsing reinvented per project | `driver.parse_output()` returns structured fields |

---

## 🛠 Development

See [`docs/DEVELOPMENT.md`](docs/DEVELOPMENT.md) for setup, project layout, adding drivers, dev flags, and the layered skill system.

---

## 🌐 Remote deployment

When the solver lives on a different machine (an HPC login node, a lab box, or any host with the solver installed) and you want to drive it from your laptop, a notebook, or an LLM agent — install `sim-cli-core` on **both** ends and run `sim serve` on the remote.

```bash
# On the solver host (the machine with the solver installed)
ssh user@solver-host
pip install sim-cli-core
sim serve --host 0.0.0.0 --port 7600     # bind to all interfaces

# On your local control machine
sim --host <solver-host-ip> connect --solver <solver> --mode <mode>
sim --host <solver-host-ip> exec "<solver-specific snippet>"
sim --host <solver-host-ip> inspect session.summary
sim --host <solver-host-ip> disconnect
sim --host <solver-host-ip> stop          # shut down the remote server when done
```

That is the entire setup — same `sim-cli-core` package on both sides, same wire protocol whether it is talking to a local or a remote server. Bind `--host 0.0.0.0` only on networks you trust (Tailscale, VPN, LAN behind a firewall); there is **no auth layer** on `/connect` and `/exec` execute arbitrary Python.

---

## 🔗 Related projects

- **[`sim-skills`](https://github.com/svd-ai-lab/sim-skills)** — agent skills, snippets, and demo workflows for each supported solver
- **[`sim-ltspice`](https://github.com/svd-ai-lab/sim-ltspice)** — standalone Python API for LTspice file formats (used by `sim-plugin-ltspice`)

---

## 📄 License

Apache-2.0 — see [LICENSE](LICENSE).

### Third-party solver SDKs

`sim-cli` is a thin wrapper/runtime — it does **not** bundle or redistribute any vendor solver or vendor SDK. Each solver backend is reached through a third-party SDK that the user installs separately via `sim env install` or as an optional extra.

Users are responsible for obtaining a valid license for each underlying solver and for complying with the license, copyright, and EULA of every third-party SDK they choose to install alongside `sim-cli`. See [`NOTICE`](NOTICE) for the list of optional SDK dependencies and their upstream locations.

### Trademarks

`sim-cli` is an independent open-source project and is **not affiliated with, endorsed by, or sponsored by** any solver vendor. Product, solver, and company names referenced anywhere in this repository remain the property of their respective owners:

- **OpenFOAM®** is a registered trademark of **OpenCFD Ltd.**
- **ParaView®** is a trademark of **Kitware, Inc.**
- All other solver and product names are trademarks of their respective owners.
