bim-revit

Drive a running Revit session from the command line. Export sheets to PDF with BIM sidecars, read schedules, write parameters across hundreds of elements, list model warnings, run arbitrary code against the open document. The kind of work that takes a half-hour for someone fluent in visual scripting, and a full afternoon by hand.

Revit automation via an in-process add-in. Every command is a JSON request over localhost — no keyboard, no mouse, no Revit window in focus required.

Requires: Revit 2024, 2025, or 2026 running with the revit-cli add-in loaded. Run bim revit install once to register the add-in, then restart Revit.

How it works

The revit-cli add-in binds to a dynamic port at startup and writes it to %LOCALAPPDATA%\bim-cli\instances\revit-<pid>.json. bim-revit reads that file, sends JSON requests, and the add-in executes them in Revit's main thread. Multiple Revit instances are supported — use bim revit instances to list them and --pid to target one.

exec globals

These variables are pre-injected into every bim revit exec snippet:

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<Document> when a document is open
allDocs IEnumerable<Document> when a document is open (active + linked)
failuresPreprocessor BimFailuresPreprocessor when --failures is set

Common namespaces available without import: Autodesk.Revit.DB, Autodesk.Revit.UI, System.Linq, System.Collections.Generic. See namespace reference for the full list.

Failure handling with --failures

Revit scripts that batch element edits frequently encounter failures (warnings or errors) that would otherwise pop a modal dialog and block headless execution. The --failures flag installs a failure preprocessor that handles these automatically:

bim revit exec --failures delete-warnings --code "..."
bim revit exec --failures rollback        --code "..."

delete-warnings suppresses all warning-level failures and lets the transaction commit normally. rollback additionally rolls back the transaction when any error-level failure occurs.

Auto-wrapped transactions

When your script does not open its own Transaction, bim-cli wraps it in one automatically. With --failures set, that wrapper transaction gets the preprocessor installed:

bim revit exec --failures rollback --code "
    // This code runs inside a Transaction that has failuresPreprocessor installed.
    // If Revit raises an error, the transaction rolls back automatically.
    var wall = new FilteredElementCollector(doc)
        .OfClass(typeof(Wall))
        .FirstElement() as Wall;
    wall.Name = \"Renamed\";
    return failuresPreprocessor.Messages;
"

The result is the list of failure messages collected by the preprocessor (empty on success). The exit code is non-zero if the transaction was rolled back.

Script-managed transactions

When your script opens its own Transaction (detected automatically from the source, or when --no-transaction is set), bim-cli injects the BimFailuresPreprocessor class and a failuresPreprocessor variable without wrapping the transaction. Attach it to your transaction via SetFailuresPreprocessor:

// Run with: bim revit exec --failures rollback --no-transaction --file script.cs
var tx = new Transaction(doc, "batch-edit");
tx.GetFailureHandlingOptions()
    .SetFailuresPreprocessor(failuresPreprocessor);  // attach before Start()
tx.Start();

// ... batch edits ...

tx.Commit();
return new {
    committed = tx.GetStatus() == TransactionStatus.Committed,
    warnings  = failuresPreprocessor.Messages,
};

failuresPreprocessor.Messages collects all failure descriptions seen during the transaction, whether or not the transaction committed. This lets callers report failures without losing the return value.

No-regression note

Omitting --failures leaves all transaction behavior unchanged from the default: failures surface as Revit dialogs (blocked in headless sessions) and the preprocessor variable is not injected.

Verbs

VerbWhat it does
bim revit exec [--code CODE] [--file FILE] [--no-transaction] [--allow-no-doc] [--timeout N] [--launch-timeout N] [--kill-on-launch-timeout] [--path FILE] [--revit-version N] [--pid N] [--instance INSTANCE] [--compile-only] [--args-json ARGS-JSON] [--with-active-view] [--dismiss-stale-dialogs] [--mock] [--rollback] [--expect-revision EXPECT-REVISION] [--scope SCOPE] [--failures FAILURES]Execute arbitrary C# against the Revit API. Launches Revit automatically if not running.
bim revit quit [--pid N] [--instance INSTANCE] [--all] [--idle N]Close a Revit instance. Auto-selects when exactly one instance is running.
bim revit kill [--pid N] [--instance INSTANCE] [--all] [--idle N]Terminate one or all registered Revit instances (alias for quit)
bim revit instancesList all live Revit instances
bim revit changes --since SINCE [--scope SCOPE] [--document DOCUMENT] [--revit-version N] [--pid N] [--instance INSTANCE]Host change feed (spec--host-change-feed.md), Phase C0 fingerprint mode: elements added/modified/deleted in --scope since a prior --since cursor. No Revit add-in change; diffs a coarse geometric fingerprint (id, category, typeId, rounded bbox/location/rotation/flip) collected via the same exec engine as element-list/coords.
bim revit revision [--scope SCOPE] [--revit-version N] [--pid N] [--instance INSTANCE]Host change feed (spec--host-change-feed.md): the document's current cursor for --scope, no diff computed. Cheap to poll; pass the result as `changes --since` or `exec --expect-revision`.
bim revit open --path FILE [--detached] [--timeout N] [--mode MODE] [--launch-timeout N] [--kill-on-launch-timeout] [--revit-version N] [--pid N] [--instance INSTANCE] [--activate] [--close-others] [--discard]Open a .rvt file in the active Revit instance
bim revit launch [--path FILE] [--new] [--max N] [--timeout N] [--kill-on-launch-timeout] [--revit-version N] [--wait-for-addon N] [--role ROLE] [--document FILE]Launch Revit and wait for the add-in to come up
bim revit status [--detailed] [--revit-version N] [--pid N] [--instance INSTANCE]Revit + add-in state
bim revit install [--all] [--revit-version N]Extract the add-in DLL and write the .addin manifest
bim revit rvt-version --file FILESniff the Revit version a .rvt was saved by (no Revit required)
bim revit export [--all-sheets] [--sheet-set SHEET-SET] [--sheet SHEET] [--sheets SHEETS] [--active-view] [--output FILE] [--paper-size PAPER-SIZE] [--orientation ORIENTATION] [--color COLOR] [--raster-quality RASTER-QUALITY] [--name-by NAME-BY] [--name-pattern NAME-PATTERN] [--per-sheet] [--bim] [--sidecars SIDECARS] [--no-bim] [--no-pack] [--timeout N] [--revit-version N] [--pid N] [--instance INSTANCE] [--mock] [--preflight]Export sheets as PDF (mirrors Revit Export PDF dialog). With BIM options (default), embeds element/mark/scale/level/annotation/titleblock sidecars as a PDF-BIM package.
bim revit doctorDriver health check
bim revit versionDriver version
bim revit modelModel-level queries. Requires a subverb.
bim revit coords [--revit-version N] [--pid N] [--instance INSTANCE] [--mock]Report the active document's positional reference systems: internal origin, project base point, survey point, deltas, site location, and named project locations. Read-only; requires a model open.
bim revit export-views --filter FILTER --output FILE [--format FORMAT] [--revit-version N] [--pid N] [--instance INSTANCE]Export matching sheets as PDF using a name-filter regex. Alias over exec -- no Revit Transaction required.
bim revit health [--pid N] [--instance INSTANCE]Ping one Revit instance's add-in and report whether it is responding. Read-only; never launches or restarts anything.
bim revit restart [--pid N] [--instance INSTANCE] [--timeout N]Restart one Revit instance in place: kill it and relaunch with the same year, role and document. Managed instances only -- refuses an attach-mode instance (the user's own running Revit) with kind attach-mode-instance.
bim revit aliasManage and discover exec alias scripts (builtin + user-tier from scripts dir).
bim revit sheet-list [--revit-version N] [--pid N] [--instance INSTANCE]List all non-placeholder sheets (number, name). No Revit transaction.
bim revit warnings-export [--revit-version N] [--pid N] [--instance INSTANCE]Export all Revit model warnings (description, severity, failing element IDs). No Revit transaction.
bim revit linked-models [--revit-version N] [--pid N] [--instance INSTANCE]List all linked Revit models (name, path, loaded status). No Revit transaction.
bim revit param-dump --category CATEGORY [--revit-version N] [--pid N] [--instance INSTANCE]Dump parameter names, storage types, and values for the first element in a BuiltInCategory. No Revit transaction.
bim revit export-sheets --sheets SHEETS --output FILE [--revit-version N] [--pid N] [--instance INSTANCE]Export a comma-separated set of sheet numbers to PDF. Requires an open Revit document.
bim revit rotate --id ID --angle ANGLE [--axis AXIS] [--revit-version N] [--pid N] [--instance INSTANCE]Rotate one or more elements about an axis through each element's location point. Requires a Revit transaction.
bim revit move --id ID [--dx DX] [--dy DY] [--dz DZ] [--revit-version N] [--pid N] [--instance INSTANCE]Translate one or more elements by a vector (feet). Requires a Revit transaction.
bim revit location --id ID [--revit-version N] [--pid N] [--instance INSTANCE]Read the LocationPoint of one or more elements (x, y, z in feet). No Revit transaction.
bim revit pdf-view [--output FILE] [--revit-version N] [--pid N] [--instance INSTANCE]Export the active view to PDF (PDFExportOptions). Prints the written path.
bim revit view-activate --name NAME [--revit-version N] [--pid N] [--instance INSTANCE]Activate a view by name (sets uidoc.ActiveView). No Revit transaction.
bim revit element-list --category CATEGORY [--level LEVEL] [--properties PROPERTIES] [--revit-version N] [--pid N] [--instance INSTANCE]List elements by BuiltInCategory or display name; optional level filter and extra property columns. No Revit transaction.
bim revit schedule-read --name NAME [--revit-version N] [--pid N] [--instance INSTANCE]Read a named ViewSchedule and return its rows as JSON. No Revit transaction.
bim revit material-query --name NAME [--revit-version N] [--pid N] [--instance INSTANCE]Query a material's appearance asset properties (color, shininess, transparency, smoothness, asset name). No Revit transaction.
bim revit save [--revit-version N] [--pid N] [--timeout N]Save the active Revit document. Returns the saved file path.
bim revit export-image --views VIEWS --out FILE [--px N] [--fit] [--revit-version N] [--pid N] [--timeout N]Export named views to PNG files. Unknown view names produce a per-view error without failing the entire batch.

api

VerbWhat it does
bim revit api.search --query QUERY [--limit N] [--kind KIND] [--revit-version N]Find Revit API types (or members) whose name contains a query substring. Works without Revit running.
bim revit api.type --name NAME [--members MEMBERS] [--revit-version N]Dump the public surface of one Revit API type. Works without Revit running.

family

VerbWhat it does
bim revit family.place [--family FAMILY] [--type TYPE] [--rfa FILE] --x X --y Y [--z Z] [--level LEVEL] [--host HOST] [--face FACE] [--rotation ROTATION] [--rollback] [--compile-only] [--timeout N] [--dismiss-stale-dialogs] [--revit-version N] [--pid N] [--instance INSTANCE]Place one family instance, choosing the NewFamilyInstance overload from the family's FamilyPlacementType: OneLevelBased -> point + level; OneLevelBasedHosted -> point + host (wall) + level; WorkPlaneBased -> the host's INSTANCE face reference (--host/--face), else the level's plane reference (z = 0) or a reference plane at level + z. Other placement types are refused. Arguments that cannot apply, and a z the family does not honour (measured), come back as warnings. Runs through exec's auto transaction; --rollback verifies without keeping.

workshare

VerbWhat it does
bim revit workshare.enable --path FILE --central FILE [--force] [--grid-workset GRID-WORKSET] [--workset WORKSET] [--timeout N] [--compile-only] [--dismiss-stale-dialogs] [--revit-version N] [--pid N] [--instance INSTANCE]Turn a non-workshared model into a file-based CENTRAL: open --path (in the background unless it is the active document), Document.EnableWorksharing with the default worksets, SaveAs --central with WorksharingSaveAsOptions.SaveAsCentral, relinquish everything, close. Changes how everyone opens the model from then on.
bim revit workshare.local --central FILE --local FILE [--force] [--timeout N] [--compile-only] [--dismiss-stale-dialogs] [--revit-version N] [--pid N] [--instance INSTANCE]Create a LOCAL copy of a central for the current Revit user (WorksharingUtils.CreateNewLocal). Needs a running Revit (any document, or none, active). Does not open it: an add-in cannot swap the active document, so start Revit on it with `launch --path <local>`.
bim revit workshare.sync [--comment COMMENT] [--relinquish RELINQUISH] [--compact] [--expect-local FILE] [--expect-central FILE] [--timeout N] [--compile-only] [--dismiss-stale-dialogs] [--revit-version N] [--pid N] [--instance INSTANCE]Synchronize the ACTIVE local with its central (Document.SynchronizeWithCentral): save the local before and after, relinquish all by default. Never runs on a central opened directly, a detached or non-workshared document, or while a transaction is open. Failures are typed (central-unreachable, central-locked, ownership-conflict naming the elements, ...).
bim revit workshare.status [--owned] [--check-central] [--timeout N] [--compile-only] [--dismiss-stale-dialogs] [--revit-version N] [--pid N] [--instance INSTANCE]Where the ACTIVE document stands: workshared or not, its central and local paths, detached / central-opened-directly, worksets with their owners, the last sync this driver made for it; --owned scans element ownership, --check-central asks the central whether the local is up to date.

For agent use: /revit/llms.txt

Guides

Task-focused walkthroughs for the most common Revit jobs — each with a copy-paste agent prompt and exact commands: