# bim-revit > Revit automation via an in-process add-in. Executes C# against the live Revit API, reads/writes model data, and controls the Revit session from a terminal. ## How the connection works bim-revit communicates with a Revit add-in (`revit-cli`) over a local TCP socket. The port is assigned dynamically at add-in startup and stored in `%LOCALAPPDATA%\bim-cli\instances\revit-.json`. Every `bim revit` command reads that file to find the port, sends a JSON request, and returns JSON. **Revit must be running with the add-in loaded.** Check with `bim revit status`. If the add-in is not loaded, `bim doctor --json` returns a `fix` field with the exact command to install it. ## Requirements - Windows 10/11 - Revit 2022, 2024, 2025, or 2026 installed and licensed - bim-revit add-in loaded (installed via `bim revit install`) ## Verb reference ### Session control - `bim revit instances` — list all live Revit sessions: pid, year, port, active document. Call this first when multiple Revit versions or copies are running. - `bim revit status` — running instance, open model path, Revit year, port, add-in loaded flag - `bim revit status --detailed` — adds `checks[]` array: revit-installed, addin-installed, addin-version (PE metadata check), port-responding - `bim revit launch [--path MODEL] [--timeout 300]` — launch Revit and wait for the add-in to come up; streams NDJSON progress lines to stdout; optionally opens a model after launch - `bim revit kill [--pid PID]` — terminate a specific Revit instance and remove its registry entry - `bim revit kill --all` — terminate all registered Revit instances - `bim revit open --path FILE [--detached] [--timeout 60]` — open a .rvt in the running session; `--detached` opens a local copy of a workshared model - `bim revit install` — extract add-in DLL and write the .addin manifest to Revit's add-ins folder (run once per Revit version) - `bim revit rvt-version ` — sniff the Revit version a .rvt was saved by; no Revit required, reads the OLE compound document header ### Code execution - `bim revit exec --code "C# snippet"` — run inline C# against the live Revit API; returns JSON - `bim revit exec --file script.cs` — run a .cs file; preferred for code longer than a few lines - `bim revit exec --no-transaction` — skip wrapping in a Revit Transaction; works even without an open document (use for read-only or document-independent code) - `bim revit exec --timeout 60` — override execution timeout (default 30s) - `bim revit exec --pid ` — target a specific Revit instance when multiple are running (get pid from `instances`) ### API reference - `bim revit api search "FilteredElementCollector"` — full-text search across Revit API XML docs; returns matching members with type signatures - `bim revit api type "Autodesk.Revit.DB.Wall"` — all members of a type - `bim revit api describe "M:Autodesk.Revit.DB.Element.get_Parameter"` — full detail for a member ID ### Export - `bim revit export [--sheet "A-101,A-102"] [--all-sheets] [--output DIR] [--bim] [--orientation auto|portrait|landscape]` — export Revit sheets to PDF - Without `--bim`: standard PDF output only - With `--bim`: PDF + 6 JSON sidecars written alongside each PDF: - `.elements.json` — all elements on the sheet: id, category, mark, level, family, type - `.marks.json` — element bounding boxes in PDF coordinate space (for overlay alignment) - `.rooms.json` — room boundaries, names, numbers, areas - `.levels.json` — level names and elevations - `.properties.json` — all parameters for every element on the sheet - `.views.json` — viewports and their crop regions - `--sheet` accepts a comma-separated list of sheet numbers: `--sheet "A-101,A-102,S-100"` - `--all-sheets` exports every sheet in the model - Output per sheet: `{ "path": "output/A-101.pdf", "sheet_number": "A-101", "sheet_name": "First Floor Plan", "sidecar_count": 6 }` **Export one sheet with BIM data:** ``` bim revit export --sheet "A-101" --bim --output ./output # ./output/A-101.pdf -- opens in any PDF viewer (Acrobat, Bluebeam, browser) # ./output/A-101.elements.json -- structured element data; query without live Revit # ./output/A-101.marks.json -- element positions in PDF space # ./output/A-101.rooms.json -- room data # ./output/A-101.levels.json -- level data # ./output/A-101.properties.json -- all element parameters # ./output/A-101.views.json -- viewport geometry ``` **Export full drawing set:** ``` bim revit export --all-sheets --bim --output ./output ``` **Query elements after export (no Revit required):** After export, an agent can read `elements.json` directly to answer questions about the sheet without a live Revit session. The PDF and sidecars are self-contained. ## exec globals These variables are pre-injected into every `exec` snippet. You do not declare them. | Variable | Type | Available when | |----------|------|----------------| | `uiApp` | `Autodesk.Revit.UI.UIApplication` | always | | `app` | `Autodesk.Revit.ApplicationServices.Application` | always | | `doc` | `Autodesk.Revit.DB.Document` | when a document is open | | `uiDoc` | `Autodesk.Revit.UI.UIDocument` | when a document is open | | `linkedDocs` | `IEnumerable` | when a document is open | | `allDocs` | `IEnumerable` | when a document is open (active + linked) | `doc` and `uiDoc` are null when no document is open. Use `uiApp` or `app` for document-independent work. Common namespaces available without import: `Autodesk.Revit.DB`, `Autodesk.Revit.UI`, `System.Linq`, `System.Collections.Generic`. See https://bimcli.com/revit-api-namespaces for the full namespace reference. ## exec patterns **Read — no transaction needed:** ``` bim revit exec --no-transaction --code " return new FilteredElementCollector(doc) .OfCategory(BuiltInCategory.OST_Doors) .WhereElementIsNotElementType() .Select(e => new { id = e.Id.Value, mark = e.get_Parameter(BuiltInParameter.ALL_MODEL_MARK)?.AsString() }) .ToList(); " ``` **Write — transaction required:** ``` bim revit exec --code " using (var tx = new Transaction(doc, \"set mark\")) { tx.Start(); var el = doc.GetElement(new ElementId(1234567)); el.get_Parameter(BuiltInParameter.ALL_MODEL_MARK).Set(\"D-01-REVISED\"); tx.Commit(); } return true; " ``` **Use --file for longer scripts (avoids shell quoting issues):** ``` bim revit exec --file script.cs ``` **Use api search to find the right class before exec:** ``` bim revit api search "sheet number parameter" bim revit api type "Autodesk.Revit.DB.ViewSheet" ``` ## Workflow patterns **Bootstrap from scratch:** ``` bim revit launch --path "C:\Projects\tower.rvt" bim revit status bim revit exec --no-transaction --code "return doc.Title;" ``` **Kill a frozen Revit and restart:** ``` bim revit kill --all bim revit launch ``` **Check add-in installation and version:** ``` bim revit status --detailed ``` **Resolve PDF element IDs back to model:** ``` bim pdf marked drawings.pdf > marks.ndjson bim revit exec --file resolve-marks.cs ``` ## Gotchas - Revit must be running before any `bim revit` command other than `status`, `install`, `launch`, and `rvt-version` - `exec` wraps code in a Transaction by default, which requires an open document. Use `--no-transaction` for read-only queries or document-independent code (e.g. `app.VersionNumber`). Forgetting the transaction on write operations throws a Revit API exception. - `uidoc.ActiveView = view` throws `InvalidOperationException` inside the auto-transaction. Fix: add `--no-transaction`. - `exec` cannot import external assemblies or NuGet packages — only Revit's own assemblies and the standard library are available - The add-in runs in Revit's main thread; long-running `exec` calls block the UI. Use `--timeout` to bound execution. A StatusOverlay window appears during exec so Revit's unresponsiveness is visible. - `open` on a workshared model opens the central file by default. Use `--detached` for a local copy that won't affect the central model. - Use `--file` for inline code longer than ~50 chars — shell quoting with embedded quotes, braces, and line breaks is fragile. Write to a temp .cs file and pass the path. - Version mismatch between the installed add-in and the running Revit silently fails. Run `bim revit status --detailed` to check `addin-version`. ## Related pages - https://bimcli.com/revit-api-namespaces — namespace reference and pre-injected globals - https://bimcli.com/revit-api-versions — version-specific API quirks (ElementId, ProjectPosition, etc.) - https://bimcli.com/headless-revit — setup guide and automation patterns - https://bimcli.com/bulk-edit-revit-parameters — parameter read/write with exec - https://bimcli.com/pdf/llms.txt — pdf driver docs (for pairing with marked)