agentsclimarketplace

Bim scripting

Skill marcinfinitesimal533/Claude-skills-for-Computational-Designers/skills/bim-scripting

Build Claude Code skills for computational design, parametric modeling, simulation, BIM scripting, and fabrication in AEC

Install
npx -y skills add marcinfinitesimal533/Claude-skills-for-Computational-Designers --skill bim-scripting

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 2 stars2 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Revit API fundamentals, Dynamo for Revit, pyRevit framework, IFC schema and openBIM, model checking, automated documentation, clash detection, and BIM interoperability tools for AEC computational design

SKILL.md

43.0 KB, as published. Nobody here has run it

BIM Scripting

Comprehensive reference for automating Building Information Modeling workflows through scripting, API access, and interoperability platforms. This skill covers the full spectrum of BIM automation --- from visual programming with Dynamo through deep Revit API scripting, pyRevit extension development, IFC/openBIM data exchange, model checking, automated documentation, and cross-platform interoperability via Speckle, BHoM, and Rhino.Inside.Revit.


1. BIM Automation Philosophy

Why Script BIM

BIM models are databases disguised as 3D geometry. Every wall, door, room, and duct segment carries structured data --- type, dimensions, material, cost code, fire rating, acoustic class, phase, workset, design option. Manual manipulation of that data does not scale. A 200-unit residential project may contain 40,000+ elements, each with 30--80 parameters. Changing a naming convention, verifying parameter completeness, or exporting coordinated drawing sets by hand is not just slow --- it is error-prone and unrepeatable.

Scripting BIM means treating the model as a programmable data source:

  • Read element properties at scale (audit, validate, report).
  • Write parameter values in batch (standards enforcement, data enrichment).
  • Create elements procedurally (repetitive layouts, adaptive placement).
  • Transform geometry computationally (facade panelization, structural optimization).
  • Export deliverables automatically (sheets to PDF, models to IFC, data to dashboards).

Manual vs. Automated BIM Workflows

WorkflowManual ApproachAutomated ApproachTime Savings
Parameter QAOpen each element, check valueScript scans all elements, flags violations95%
Sheet creationPlace views, adjust crops, add tags one by oneScript generates sheets from template rules90%
Clash detectionVisual inspection in section viewsNavisworks / script-based interference check85%
Export to IFCFile > Export > IFC, configure, repeat per modelBatch script exports all linked models with preset mappings80%
Room finish scheduleManual schedule, manual formattingAPI-generated schedule with conditional formatting75%
Design option comparisonDuplicate views, switch options, compareScript generates comparison report with metrics90%
Naming convention enforcementManual review of browser treeFilteredElementCollector + regex validation98%

ROI of BIM Automation

The return on investment for BIM scripting follows a clear pattern:

  1. First script --- 2-8 hours to develop, saves 1-4 hours per use. Break-even after 2-3 uses.
  2. Script library (20-50 tools) --- 200-500 hours to develop, saves 10-30 hours per project. Break-even within 1-2 projects.
  3. Custom application --- 500-2000 hours to develop, saves 50-200 hours per project. Break-even within 3-5 projects.
  4. Enterprise platform --- 2000-10,000 hours to develop, transforms entire practice workflow.

The Automation Spectrum

Level 1: Visual Programming (Dynamo, Grasshopper)
  - Lowest barrier to entry
  - Best for designers who think visually
  - Limited scalability and version control
  - Good for: one-off design explorations, parameter mapping, geometry generation

Level 2: Scripting (Python in Dynamo, pyRevit, RevitPythonShell)
  - Moderate barrier to entry
  - Full API access with Python convenience
  - Version-controllable, shareable
  - Good for: batch operations, custom tools, data workflows

Level 3: Custom Tools (C# add-ins, pyRevit extensions)
  - Higher barrier to entry
  - Compiled performance, custom UI, ribbon integration
  - Deployable to teams
  - Good for: production tools, firm-wide standards enforcement

Level 4: Full Applications (standalone apps, web dashboards, microservices)
  - Highest barrier to entry
  - Complete control over UX and data pipeline
  - Cloud-scalable, multi-user
  - Good for: enterprise BIM management, cross-project analytics

When to Automate vs. When to Model Manually

Automate when:

  • The task repeats across projects or phases.
  • The task involves more than 50 elements.
  • Consistency and auditability are critical (QA/QC, code compliance).
  • The output feeds downstream processes (cost, energy, structural analysis).
  • Human error risk is high (naming, classification, spatial containment).

Model manually when:

  • The task is a one-time creative act (early concept massing).
  • Judgment and spatial intuition outweigh procedural logic.
  • The element count is small and the rules are ambiguous.
  • The cost of developing automation exceeds the cost of manual work.

BIM Maturity Levels and Automation

BIM LevelDescriptionAutomation Role
Level 02D CAD, no BIMCAD scripting (AutoLISP, VBA) for drawing automation
Level 13D modeling, 2D documentationBasic Dynamo scripts, parameter management
Level 2Federated models, structured data exchangeIFC workflows, clash detection, model checking
Level 3Integrated single model, full lifecycle dataAPI-driven analytics, real-time dashboards, AI-assisted QA
Level 4 (emerging)Digital twin, IoT-connected, predictiveContinuous model sync, ML-driven optimization, autonomous agents

2. Revit API Fundamentals

Architecture

The Revit API is a .NET framework (C# or VB.NET natively, Python via IronPython or CPython with RevitPythonShell/pyRevit). The object hierarchy:

UIApplication
  └── Application           (Revit application-level settings, version info)
       └── Document          (the .rvt file; model database)
            ├── Elements      (everything in the model)
            ├── Views         (plans, sections, 3D views, schedules)
            ├── Phases        (existing, new construction, demolition)
            ├── DesignOptions  (option sets and options)
            ├── Worksets       (worksharing partitions)
            └── Settings       (project units, line styles, fill patterns)

Element Types

Every object in a Revit model inherits from Element. Key subclasses:

ClassDescriptionExample
FamilyInstancePlaced instance of a loadable familyDoor, window, furniture, fixture
WallSystem family: wall elementBasic Wall, Curtain Wall, Stacked Wall
FloorSystem family: floor slabGeneric Floor, composite assemblies
RoofSystem family: roof elementBasic Roof, extrusion roof
CeilingSystem family: ceiling elementCompound ceiling, basic ceiling
FamilyInstance (structural)Columns, beams, bracesSteel W-shapes, concrete columns
RoomSpatial element for architectural spacesBounded by room-bounding elements
AreaSpatial element for area plansGross area, rentable area
ViewAny view in the modelViewPlan, ViewSection, View3D, ViewSheet
ViewSheetA sheet for documentationContains viewport placements
ViewScheduleA schedule/quantity takeoffTabular data extraction
GroupGrouped elementsModel groups, detail groups
LevelDatum: horizontal reference planeDefines story heights
GridDatum: vertical reference planeStructural grid lines
ReferencePlaneConstruction planeAlignment references

Categories, Families, Types, Instances

This four-level hierarchy is central to Revit:

Category        (e.g., Doors)
  └── Family      (e.g., Single-Flush)
       └── Type     (e.g., 36" x 84")
            └── Instance  (placed door #1, #2, #3...)
  • Category: broad classification (Walls, Doors, Floors, Furniture). Each has a BuiltInCategory enum.
  • Family: a parametric definition (.rfa file for loadable families; system families are built-in).
  • Type: a named set of parameter values within a family (dimensions, materials).
  • Instance: a placed occurrence with instance-specific parameters (location, room, mark).

Parameters

Parameters store all non-geometric data on elements.

Parameter KindScopeDefinitionAccess
Built-inHardcoded by RevitPredefined (e.g., WALL_BASE_OFFSET)element.get_Parameter(BuiltInParameter.WALL_BASE_OFFSET)
ProjectOne project fileDefined in Project Parameters dialogelement.LookupParameter("MyParam")
SharedAcross projects/familiesDefined in Shared Parameters file (.txt)element.get_Parameter(guid) or by name
FamilyInside .rfa familyDefined in Family EditorExposed as type or instance parameter
GlobalProject-wide valueNot element-bound; referenced by formulasGlobalParametersManager

Parameter storage types:

  • StorageType.String --- text
  • StorageType.Integer --- integers and YesNo (0/1)
  • StorageType.Double --- real numbers (always in internal units)
  • StorageType.ElementId --- reference to another element (material, type, level)

Transactions

Every model modification must occur inside a Transaction. Without it, the API throws an InvalidOperationException.

# Python (pyRevit / RevitPythonShell)
from Autodesk.Revit.DB import Transaction

doc = __revit__.ActiveUIDocument.Document
t = Transaction(doc, "Batch Update Parameters")
t.Start()

try:
    # ... modify elements ...
    t.Commit()
except Exception as e:
    t.RollBack()
    print("Error: {}".format(e))

Transaction types:

  • Transaction --- standard single transaction (most common).
  • TransactionGroup --- wraps multiple transactions; can assimilate (merge into one undo) or roll back all.
  • SubTransaction --- nested within a Transaction; can roll back independently without aborting the parent.

FilteredElementCollector

The primary mechanism for querying elements in a Revit model. It operates as a builder pattern with filters:

from Autodesk.Revit.DB import (
    FilteredElementCollector, BuiltInCategory,
    ElementCategoryFilter, ElementClassFilter
)

# All walls in the model
walls = FilteredElementCollector(doc) \
    .OfCategory(BuiltInCategory.OST_Walls) \
    .WhereElementIsNotElementType() \
    .ToElements()

# All door types (not instances)
door_types = FilteredElementCollector(doc) \
    .OfCategory(BuiltInCategory.OST_Doors) \
    .WhereElementIsElementType() \
    .ToElements()

# All family instances of a specific class
instances = FilteredElementCollector(doc) \
    .OfClass(FamilyInstance) \
    .ToElements()

# Elements in a specific view
view_elements = FilteredElementCollector(doc, view.Id) \
    .OfCategory(BuiltInCategory.OST_Walls) \
    .ToElements()

Geometry Access

Extracting geometry from Revit elements:

Element
  └── get_Geometry(Options)
       └── GeometryElement (iterable)
            ├── Solid
            │    ├── Faces (FaceArray)
            │    │    └── Face → Surface, UV domain, normal
            │    └── Edges (EdgeArray)
            │         └── Edge → Curve
            ├── GeometryInstance (for family instances)
            │    └── GetInstanceGeometry() → GeometryElement
            ├── Curve (for line-based elements)
            ├── Point
            └── PolyLine

Units

Revit internal units are always:

  • Length: feet
  • Angle: radians
  • Area: square feet
  • Volume: cubic feet

Use UnitUtils.ConvertFromInternalUnits() and UnitUtils.ConvertToInternalUnits() for conversion. In Revit 2022+, use UnitTypeId instead of DisplayUnitType.

Events

The Revit API provides application and document-level events:

  • Application.DocumentOpened / DocumentClosing / DocumentSaved
  • Application.ViewActivated
  • Application.DialogBoxShowing (intercept and auto-dismiss dialogs)
  • Document.DocumentChanged (react to element modifications)
  • UIApplication.Idling (periodic background processing)

External Commands, Applications, Events

TypePurposeLifecycle
IExternalCommandSingle button click actionRuns once per invocation
IExternalApplicationRibbon tab/panel setup, startup logicRuns at Revit startup/shutdown
IExternalDBApplicationDB-level (no UI) startup logicFor services, updaters
IExternalEventHandlerThread-safe model modification from external threadsRaised via ExternalEvent

C# vs. Python for Revit API

CriterionC#Python (IronPython/CPython)
PerformanceCompiled; fastestInterpreted; slower for large loops
DebuggingFull Visual Studio debuggerPrint statements, limited debugger
DeploymentDLL add-in; requires compilationScript file; instant edit-run cycle
Learning curveSteeper (typed language, project setup)Gentler (dynamic typing, REPL)
API coverage100%100% (same .NET API via clr)
EcosystemNuGet packages, .NET librariesPython packages (limited in IronPython)
UI creationWPF, WinForms with full designerWPF possible but harder; rpw simplifies
Best forProduction add-ins, enterprise toolsRapid prototyping, small utilities, pyRevit

3. Dynamo for Revit

Core Advantages

Dynamo is a visual programming environment integrated with Revit (ships with Revit since 2017). Key strengths:

  • Visual dataflow --- nodes connected by wires; intuitive for non-programmers.
  • Live Revit connection --- read/write model elements in real time.
  • Geometry preview --- 3D preview of computational geometry before committing to Revit.
  • Extensibility --- custom nodes in Python, C#, or DesignScript; package manager ecosystem.

Revit-Specific Nodes

Dynamo provides dedicated Revit node categories:

  • Selection: Select Model Element, Select Elements by Category, All Elements of Category
  • Create: Wall.ByCurveAndHeight, Floor.ByOutlineTypeAndLevel, FamilyInstance.ByPoint
  • Modify: Element.SetParameterByName, Element.MoveByVector, Element.OverrideColorInView
  • Query: Element.GetParameterValueByName, Element.BoundingBox, Room.Boundaries

Dynamo Player

Dynamo Player exposes Dynamo scripts as simple button-click tools for end users who do not need to understand the graph. Configure inputs as user-facing prompts. Best practice: design scripts specifically for Player with clear input labels and minimal required interaction.

Geometry Kernels

Dynamo uses two separate geometry engines:

  1. DesignScript / ASM (Autodesk Shape Manager) --- Dynamo's native geometry kernel. Creates Points, Curves, Surfaces, Solids in Dynamo's 3D preview.
  2. Revit geometry --- the actual BIM model geometry.

These are not interchangeable. A Dynamo Surface is not a Revit Face. Converting between them requires explicit nodes:

  • Surface.ByPatch (Dynamo) vs. FaceWall.Create (Revit)
  • Curve.ByPoints (Dynamo) vs. ModelCurve.ByCurve (Revit)

Common Revit Workflows in Dynamo

  1. Room-based floor finish placement --- query room boundaries, offset curves, create floor elements by outline.
  2. Adaptive component placement --- distribute families along curves or surfaces with parameter-driven spacing.
  3. Parameter read/write --- bulk read element parameters to Excel, modify, write back.
  4. View creation --- generate scope boxes, create dependent views per scope box, apply view templates.
  5. Sheet setup --- create sheets from list, place viewports at coordinates, populate titleblock parameters.
  6. Keynote management --- read keynote table, validate against model, update keynote parameters.
  7. Area analysis --- extract room areas, calculate ratios (net-to-gross, circulation percentage), color-code by metric.

Essential Packages

PackageAuthorKey Capabilities
ClockworkAndreas Dieckmann500+ utility nodes; view manipulation, element filtering, string operations
RhythmJohn PiersonRevit-focused; sheet management, view manipulation, element creation
archi-labKonrad SobonView/sheet automation, element selection, Revit API wrappers
spring nodesDimitar VenkovGeometry, mesh processing, FEM analysis integration
BimorphNodesBimorphGeometry, CAD import, mesh to solid conversion
Genius LociAlban de ChasteignerSite tools, topography, Revit element manipulation
Data-ShapesMostafa El AyoubiCustom UI nodes (forms, dropdowns, file pickers)
OrchidErik Falck JorgensenDocument management, family loading, workset operations
LunchBoxNathan MillerPaneling, geometric patterns, data management

Python Scripting in Dynamo

Python nodes in Dynamo provide full Revit API access:

import clr
clr.AddReference('RevitAPI')
clr.AddReference('RevitServices')

from Autodesk.Revit.DB import *
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager

doc = DocumentManager.Instance.CurrentDBDocument

# Start transaction
TransactionManager.Instance.EnsureInTransaction(doc)

# ... API operations ...

TransactionManager.Instance.TransactionTaskDone()

Key differences from standalone pyRevit scripts:

  • Use TransactionManager instead of raw Transaction.
  • Use DocumentManager.Instance.CurrentDBDocument instead of __revit__.
  • Inputs come from IN[0], IN[1], ...; output goes to OUT.

Performance Considerations

Dynamo becomes slow when:

  • Graphs exceed 200-300 nodes.
  • Lists contain 10,000+ items with geometry preview on.
  • Multiple levels of List.Map or List@Level create combinatorial explosions.

Alternatives when Dynamo is too slow:

  • Move heavy logic into a single Python node (avoids inter-node marshalling).
  • Use pyRevit for batch operations without geometry preview overhead.
  • Use compiled C# add-in for maximum performance.
  • Use Dynamo's Passthrough node to sequence operations and avoid unnecessary recalculation.

4. pyRevit Framework

Architecture

pyRevit is a rapid application development framework for Revit. It creates ribbon UI elements from a folder structure:

MyExtension.extension/
  ├── MyTab.tab/
  │    ├── MyPanel.panel/
  │    │    ├── MyButton.pushbutton/
  │    │    │    ├── script.py          (IronPython script)
  │    │    │    ├── icon.png           (16x16, 24x24, or 32x32)
  │    │    │    └── bundle.yaml        (tooltip, author, help URL)
  │    │    ├── MySplitButton.splitbutton/
  │    │    │    ├── Option1.pushbutton/
  │    │    │    └── Option2.pushbutton/
  │    │    └── MyPullDown.pulldown/
  │    │         ├── Item1.pushbutton/
  │    │         └── Item2.pushbutton/
  │    └── AnotherPanel.panel/
  └── lib/                             (shared Python modules)
       └── my_utils.py

Script Types

  • IronPython (.py) --- default; runs in Revit's IronPython engine. Access to .NET via clr.
  • CPython (.py with #! python3) --- runs in CPython 3.x. Access to pip packages (pandas, numpy). Cannot access UI elements directly.
  • C# (.cs) --- compiled at runtime. Full performance and type safety.

pyRevit CLI

# Install pyRevit
pyrevit install

# Clone an extension from GitHub
pyrevit extend ui MyExtension https://github.com/user/repo.git

# List installed extensions
pyrevit extensions list

# Attach to a Revit version
pyrevit attach 2024 latest

# Enable/disable extensions
pyrevit extensions enable MyExtension
pyrevit extensions disable MyExtension

# Clear caches
pyrevit caches clear --all

Built-in Tools Reference

pyRevit ships with dozens of production-ready tools:

  • Select --- select all instances of a type, select by parameter value, select linked elements.
  • Match --- match type properties, match graphic overrides between elements.
  • Keynotes --- keynote manager with live editing and project keynote file management.
  • Sheets --- batch create sheets, renumber sheets, print sheet sets.
  • Views --- batch create views, set view templates, manage scope boxes.
  • Project --- project parameter manager, shared parameter loader.
  • Toggles --- quick toggles for halftone, crop regions, annotations.

Creating Custom Extensions

Minimum viable pyRevit button:

# script.py
"""Tooltip text shown on hover."""

__title__ = "My Button"
__author__ = "Your Name"

from pyrevit import revit, DB, forms

doc = revit.doc

# Get all rooms
rooms = DB.FilteredElementCollector(doc) \
    .OfCategory(DB.BuiltInCategory.OST_Rooms) \
    .WhereElementIsNotElementType() \
    .ToElements()

# Filter rooms with no number
unnamed = [r for r in rooms if not r.get_Parameter(
    DB.BuiltInParameter.ROOM_NUMBER).AsString()]

if unnamed:
    forms.alert("{} rooms have no number assigned.".format(len(unnamed)))
else:
    forms.alert("All rooms are numbered.", title="QA Check Passed")

Transaction Handling in pyRevit

pyRevit provides a context manager for transactions:

from pyrevit import revit, DB

with revit.Transaction("Update Room Names"):
    for room in rooms:
        param = room.get_Parameter(DB.BuiltInParameter.ROOM_NAME)
        current = param.AsString()
        param.Set(current.upper())

RevitPythonShell

An interactive Python REPL inside Revit. Useful for:

  • Exploring the API interactively (inspect elements, test queries).
  • Quick one-off operations without creating a full pyRevit script.
  • Debugging: inspect element properties, test FilteredElementCollector queries.

Template Scripts

Batch parameter update:

from pyrevit import revit, DB, forms

doc = revit.doc
walls = DB.FilteredElementCollector(doc) \
    .OfCategory(DB.BuiltInCategory.OST_Walls) \
    .WhereElementIsNotElementType() \
    .ToElements()

with revit.Transaction("Set Wall Comments"):
    for wall in walls:
        wall.LookupParameter("Comments").Set("Reviewed")

View creation from room list:

from pyrevit import revit, DB

doc = revit.doc
rooms = DB.FilteredElementCollector(doc) \
    .OfCategory(DB.BuiltInCategory.OST_Rooms) \
    .WhereElementIsNotElementType() \
    .ToElements()

level = rooms[0].Level
vft = doc.GetDefaultElementTypeId(DB.ElementTypeGroup.ViewTypeFloorPlan)

with revit.Transaction("Create Room Views"):
    for room in rooms:
        name = room.get_Parameter(DB.BuiltInParameter.ROOM_NAME).AsString()
        view = DB.ViewPlan.Create(doc, vft, level.Id)
        view.Name = "Room - {}".format(name)

Deployment

  • Shared extension path: configure in pyRevit settings to point to a network share. All team members load extensions from the same location.
  • Version control: store extensions in Git. Use CI/CD to deploy to the shared path.
  • pyRevit CLI can install extensions from Git repositories directly.

pyRevit Hooks

pyRevit supports event hooks via specially named scripts:

  • doc-changed-[hookid].py --- fires when the document changes.
  • doc-opened-[hookid].py --- fires when a document is opened.
  • doc-saved-[hookid].py --- fires after a document is saved.
  • app-init-[hookid].py --- fires when Revit starts (before any document).

Hooks live in a hooks/ folder within the extension.


5. IFC & openBIM

IFC Schema Overview

IFC (Industry Foundation Classes) is an ISO-standard (ISO 16739) open data schema for BIM data exchange. Major versions:

VersionStatusKey Additions
IFC2x3Legacy, widely supportedMost common in practice; 650+ entities
IFC4Current standard (ISO 16739-1:2018)Improved geometry, new MEP entities, 4D/5D support
IFC4.3Released 2024Infrastructure: roads, bridges, rail, tunnels, ports

Key IFC Entities

IfcProject
  └── IfcSite
       └── IfcBuilding
            └── IfcBuildingStorey
                 ├── IfcWall / IfcWallStandardCase
                 ├── IfcSlab
                 ├── IfcBeam
                 ├── IfcColumn
                 ├── IfcDoor
                 ├── IfcWindow
                 ├── IfcSpace (equivalent of Revit Room)
                 ├── IfcCurtainWall
                 ├── IfcStair / IfcStairFlight
                 ├── IfcRamp / IfcRampFlight
                 ├── IfcRailing
                 ├── IfcRoof
                 ├── IfcCovering (finishes, ceilings)
                 ├── IfcFurnishingElement
                 └── IfcDistributionElement (MEP)
                      ├── IfcFlowSegment (pipes, ducts)
                      ├── IfcFlowTerminal (fixtures, diffusers)
                      └── IfcFlowFitting (elbows, tees)

Property Sets and Quantity Sets

IFC data is carried in standardized property sets (Psets) and quantity sets (Qtos):

  • Pset_WallCommon: Reference, Status, IsExternal, ThermalTransmittance, FireRating, AcousticRating
  • Pset_SlabCommon: Reference, Status, IsExternal, LoadBearing, AcousticRating
  • Pset_DoorCommon: Reference, FireRating, IsExternal, SecurityRating, HandicapAccessible
  • Pset_SpaceCommon: Reference, IsExternal, GrossPlannedArea, NetPlannedArea, PubliclyAccessible
  • Qto_WallBaseQuantities: Length, Width, Height, GrossVolume, NetVolume, GrossSideArea, NetSideArea
  • Qto_SlabBaseQuantities: Width, Length, Depth, Perimeter, GrossArea, NetArea, GrossVolume, NetVolume

IFC Export Settings in Revit

Critical export configuration:

  • IFC version: IFC2x3 Coordination View 2.0 (most compatible) or IFC4 Reference View.
  • Export mapping table: IFC export classes in Revit maps categories to IFC entities.
  • Property set mapping: custom .txt mapping file for project-specific Psets.
  • Phase: export only the relevant phase.
  • Base point: shared coordinates for model federation.
  • Element selection: current view vs. entire model.

MVD (Model View Definition)

MVDs define subsets of the IFC schema for specific use cases:

MVDPurposeUse Case
Coordination View 2.0Geometry + basic propertiesMulti-discipline coordination
Design Transfer ViewRich geometry + full propertiesModel handover between authoring tools
Reference ViewLightweight reference geometryLightweight context for coordination
Quantity Takeoff ViewProperties + quantitiesCost estimation data exchange

BCF (BIM Collaboration Format)

BCF (ISO 21597) is a structured format for communicating issues in BIM:

  • BCF XML: file-based (.bcfzip). Contains viewpoints (camera position, component visibility), comments, and issue metadata.
  • BCF API: REST API for real-time issue sync between platforms.
  • Workflow: reviewer opens federated model, creates BCF issue with snapshot, assigns to responsible party, tracks resolution.

IFC Tools

ToolLanguageCapabilities
IfcOpenShellPython/C++Read/write/validate IFC; geometry processing; most mature open-source
IFC.jsJavaScriptWeb-based IFC viewer/parser; WebGL rendering
xBIMC# (.NET)Read/write IFC; geometry meshing; WPF viewer
BIMserverJavaModel server; IFC storage; version control; plugin architecture
SolibriDesktop appModel checking; clash detection; rule-based validation
BIMcollabWeb/DesktopBCF management; cloud collaboration; issue tracking
BlenderBIMPythonFull IFC authoring in Blender; IfcOpenShell-based

openBIM Coordination Workflow

Architect (Revit) ──export IFC──> Coordination Platform
Structural (Tekla) ──export IFC──>     (Solibri, BIMcollab,
MEP (Revit MEP) ──export IFC──>        Navisworks, or custom)
                                            │
                                    Federated Model
                                            │
                              ┌─────────────┼─────────────┐
                        Clash Detection   QA/QC       4D Planning
                              │             │             │
                         BCF Issues    Validation    Schedule Link
                              │          Report           │
                        ──BCF──> Author fixes ──re-export──>

6. Model Checking & Validation

Rule-Based Checking

Model checking verifies that a BIM model meets predefined rules. Categories:

  1. Data completeness --- required parameters are filled.
  2. Naming conventions --- element names follow organizational standards.
  3. Spatial containment --- elements are properly hosted on levels/rooms.
  4. Classification compliance --- elements have correct Uniclass/OmniClass codes.
  5. Geometric validity --- no zero-thickness walls, no overlapping elements.
  6. Design standards --- minimum room sizes, maximum corridor lengths, accessibility clearances.

Clash Detection Types

TypeDescriptionToleranceExample
Hard clashPhysical intersection of elements0 mmDuct passing through beam
Soft clash (clearance)Insufficient clearanceVariable (50-300 mm typical)Pipe too close to electrical cable tray
Workflow clash (4D)Time-based conflictSchedule overlapTwo trades occupying same zone simultaneously
DuplicateSame element modeled twicePosition toleranceTwo identical walls overlapping

Navisworks Clash Detection Setup

  1. Append all models (Revit NWC, IFC, DWG).
  2. Create selection sets by discipline (Arch, Struct, MEP), system, or zone.
  3. Configure clash tests: set A vs. set B, tolerance, clash type.
  4. Apply rules: ignore clashes between connected elements, within same system, or by specific parameter match.
  5. Group results by grid intersection, level, or element type.
  6. Generate report: HTML, XML, or BCF for distribution.

Custom Model Checking with Revit API

from pyrevit import revit, DB, forms, output

doc = revit.doc
out = output.get_output()

# Check: All rooms must have a number and name
rooms = DB.FilteredElementCollector(doc) \
    .OfCategory(DB.BuiltInCategory.OST_Rooms) \
    .WhereElementIsNotElementType() \
    .ToElements()

issues = []
for room in rooms:
    number = room.get_Parameter(DB.BuiltInParameter.ROOM_NUMBER).AsString()
    name = room.get_Parameter(DB.BuiltInParameter.ROOM_NAME).AsString()
    area = room.get_Parameter(DB.BuiltInParameter.ROOM_AREA).AsDouble()

    if not number:
        issues.append(("Room {} has no number".format(room.Id), room.Id))
    if not name:
        issues.append(("Room {} has no name".format(room.Id), room.Id))
    if area == 0:
        issues.append(("Room {} is not bounded (0 area)".format(room.Id), room.Id))

out.print_md("## Room QA Report")
out.print_md("**Total rooms**: {}".format(len(rooms)))
out.print_md("**Issues found**: {}".format(len(issues)))
for msg, eid in issues:
    out.print_md("- {} [Click to select](revit://select?eid={})".format(msg, eid))

LOD/LOI Verification

BIM Execution Plans specify required Level of Development (LOD) and Level of Information (LOI) at each project stage. Automated verification:

  • LOD 100: massing volumes present; check that IfcBuildingElementProxy exists.
  • LOD 200: approximate geometry; check that elements have correct category but allow generic types.
  • LOD 300: precise geometry; verify element dimensions match design intent; all parameters from EIR filled.
  • LOD 350: coordination geometry; verify connections between disciplines; MEP clearances maintained.
  • LOD 400: fabrication-ready; verify manufacturer data, part numbers, installation instructions.

IFC Validation with IfcOpenShell

import ifcopenshell
import ifcopenshell.validate

model = ifcopenshell.open("model.ifc")

# Schema validation
logger = ifcopenshell.validate.json_logger()
ifcopenshell.validate.validate(model, logger)

for error in logger.statements:
    print(error)

# Custom validation: all walls must have Pset_WallCommon
for wall in model.by_type("IfcWall"):
    psets = ifcopenshell.util.element.get_psets(wall)
    if "Pset_WallCommon" not in psets:
        print(f"Wall #{wall.id()} missing Pset_WallCommon")

7. Automated Documentation

View Creation Automation

Programmatic view generation eliminates the tedious manual setup of project views. Common patterns:

  • Floor plans per level --- create architectural, structural, MEP, and fire safety plans for every level.
  • Dependent views per scope box --- subdivide large floor plates into manageable sheets.
  • Sections at every grid intersection --- structural section cuts for detailing.
  • Enlarged plans per room --- interior elevations and enlarged plans keyed to room boundaries.
  • 3D views per zone --- isometric views for coordination reviews.

Sheet Layout Automation

from pyrevit import revit, DB

doc = revit.doc

# Get titleblock type
tb_type = DB.FilteredElementCollector(doc) \
    .OfCategory(DB.BuiltInCategory.OST_TitleBlocks) \
    .WhereElementIsElementType() \
    .FirstElement()

# Get all floor plan views
views = DB.FilteredElementCollector(doc) \
    .OfClass(DB.ViewPlan) \
    .WhereElementIsNotElementType() \
    .ToElements()

with revit.Transaction("Create Sheets"):
    for i, view in enumerate(views):
        if view.IsTemplate or view.Name.startswith("{"):
            continue
        # Create sheet
        sheet = DB.ViewSheet.Create(doc, tb_type.Id)
        sheet.SheetNumber = "A{:03d}".format(i + 1)
        sheet.Name = view.Name

        # Place viewport at center of sheet
        center = DB.XYZ(1.375, 0.875, 0)  # center of A1 sheet in feet
        DB.Viewport.Create(doc, sheet.Id, view.Id, center)

Tag and Annotation Automation

  • Room tags: iterate rooms, place IndependentTag at room location point.
  • Door tags: iterate doors, place tag at door midpoint with leader if needed.
  • Dimension strings: create Dimension objects along gridlines or wall faces.
  • Keynotes: assign keynote values to elements, place keynote tags in views.

Export Automation

from pyrevit import revit, DB

doc = revit.doc

# Batch PDF export (Revit 2022+)
sheets = DB.FilteredElementCollector(doc) \
    .OfClass(DB.ViewSheet) \
    .ToElements()

pdf_options = DB.PDFExportOptions()
pdf_options.FileName = "ExportedSheets"
pdf_options.Combine = False  # separate PDF per sheet
pdf_options.PaperFormat = DB.ExportPaperFormat.Default
pdf_options.ZoomType = DB.ZoomType.FitToPage

sheet_ids = [s.Id for s in sheets if s.CanBePrinted]
doc.Export("C:/Output/", sheet_ids, pdf_options)

Drawing List Management

Automate the drawing list schedule:

  • Ensure all sheets have correct sheet number, name, revision, status.
  • Generate a ViewSchedule of sheets via API with required fields.
  • Export drawing list to Excel for transmittals.
  • Validate sheet numbering against organizational standard (e.g., A-101, S-201, M-301).

8. BIM Interoperability Platforms

Speckle

Speckle is an open-source data platform for AEC that treats 3D model data as versionable, streamable, and queryable:

  • Connectors: Revit, Rhino, Grasshopper, Blender, AutoCAD, Civil3D, Unity, Unreal, Excel, Power BI, QGIS.
  • Streams: persistent data channels. Push model data to a stream; any connected app can receive it.
  • Commits: every push creates a versioned commit. Full history, branching, diffing.
  • Web viewer: browser-based 3D viewer with filtering, measurement, section cuts.
  • GraphQL API: programmatic access to all data. Query elements, filter by properties.
  • Speckle Automate: serverless functions triggered on new commits. Use for automated QA/QC, data enrichment, notifications.

When to use Speckle: cross-platform model sharing, design review with non-BIM stakeholders, automated data pipelines, custom dashboards from model data.

BHoM (Buildings and Habitats object Model)

BHoM is an open-source collaborative computational framework for the built environment:

  • Object model: unified .NET object definitions for structural, environmental, architectural, and planning objects.
  • Adapters: bidirectional data exchange with analysis software:
    • Structural: Robot, GSA, ETABS, SAP2000, Lusas
    • Environmental: IES, EnergyPlus, Ladybug
    • BIM: Revit, IFC
    • Geometry: Rhino, Grasshopper
  • Engine: computational methods that operate on BHoM objects (structural analysis queries, environmental calculations, geometry operations).
  • UI: Grasshopper components and Excel plugin for accessible interaction.

When to use BHoM: multi-software structural analysis workflows, computational design pipelines that span multiple analysis tools, when you need a unified object model across disciplines.

Rhino.Inside.Revit

Rhino.Inside.Revit runs the full Rhino and Grasshopper environment inside the Revit process, enabling:

  • Grasshopper → Revit: create Revit elements (walls, floors, roofs, adaptive components) from Grasshopper geometry.
  • Revit → Grasshopper: query Revit elements, extract geometry, read parameters.
  • Bidirectional live link: changes in Grasshopper update Revit elements; changes in Revit reflect in Grasshopper.
  • Rhino geometry in Revit views: use Rhino's superior NURBS engine for complex geometry, bake to Revit as DirectShape or native elements.

Use cases:

  • Complex facade panelization designed in GH, built as Revit curtain panels.
  • Parametric roof geometry from GH, exported as Revit roof-by-face.
  • Site grading and landscape computed in GH, placed as Revit topography.
  • Structural optimization in GH (Karamba3D), results pushed to Revit structural model.

Comparison Table

FeatureSpeckleBHoMRhino.Inside.Revit
Primary useData exchange & versioningComputational workflowsGeometry & design
ArchitectureCloud-based streams.NET object model + adaptersIn-process (runs inside Revit)
Revit supportConnector (push/pull)Adapter (read/write)Full bidirectional live link
Rhino/GH supportConnectorGH componentsNative (Rhino is the engine)
Analysis toolsVia AutomateNative adapters (Robot, GSA, etc.)Via GH plugins (Karamba, Ladybug)
Open sourceYes (Apache 2.0)Yes (LGPL 3.0)Yes (MIT)
Best forCross-platform data flowMulti-tool analysis pipelinesComplex geometry in Revit

9. BIM Scripting Best Practices

Error Handling and Logging

from pyrevit import revit, DB, forms
import traceback

doc = revit.doc
errors = []
success_count = 0

with revit.Transaction("Batch Operation"):
    for element in elements:
        try:
            # operation that might fail
            param = element.LookupParameter("Target Param")
            if param and not param.IsReadOnly:
                param.Set(new_value)
                success_count += 1
            else:
                errors.append("Element {}: parameter not found or read-only".format(element.Id))
        except Exception as e:
            errors.append("Element {}: {}".format(element.Id, str(e)))

# Report results
msg = "Processed: {}\nErrors: {}".format(success_count, len(errors))
if errors:
    msg += "\n\n" + "\n".join(errors[:20])  # limit error display
forms.alert(msg, title="Operation Complete")

Performance Best Practices

  1. Minimize FilteredElementCollector calls --- collect once, filter in Python.
  2. Use quick filters (OfClass, OfCategory) before slow filters (WherePasses with parameter filter).
  3. Disable regeneration when not needed: doc.Regenerate() only when required.
  4. Batch element creation --- create elements in a single transaction, not one transaction per element.
  5. Avoid Element.Geometry in loops --- geometry extraction is expensive. Cache results.
  6. Use ElementId sets for fast lookups instead of element lists.
  7. Turn off warning suppression wisely --- FailureHandlingOptions can skip dialog boxes during batch operations.

User Input Patterns

from pyrevit import forms

# Simple alert
forms.alert("Operation complete.", title="Success")

# Yes/No prompt
if forms.alert("Continue with operation?", yes=True, no=True):
    # proceed
    pass

# Select from list
selected = forms.SelectFromList.show(
    options,
    title="Select Elements",
    multiselect=True
)

# Text input
value = forms.ask_for_string(
    prompt="Enter new parameter value:",
    title="Parameter Update"
)

Transaction Management

PatternUse CaseUndo Behavior
Single TransactionMost operationsOne undo step
TransactionGroup (assimilate)Multi-step that should appear as one undoOne undo step
TransactionGroup (no assimilate)Multi-step with individual undoMultiple undo steps
SubTransactionTentative changes within a transactionRoll back sub-changes without aborting main transaction

Version Compatibility

Key API changes across Revit versions:

VersionNotable API Changes
2021ForgeTypeId begins replacing UnitType and DisplayUnitType
2022UnitTypeId fully replaces DisplayUnitType; PDF export API added
2023Toposolid replaces TopographySurface; analytical model API overhaul
2024Document.GetUnusedElements() added; Element.IsHidden() improvements
2025ParameterFilterElement improvements; enhanced schedule API

Code Organization

my_extension.extension/
  ├── lib/
  │    ├── __init__.py
  │    ├── config.py           (settings, constants)
  │    ├── collectors.py       (reusable FilteredElementCollector wrappers)
  │    ├── param_utils.py      (parameter read/write helpers)
  │    ├── geom_utils.py       (geometry extraction helpers)
  │    ├── export_utils.py     (PDF, DWG, IFC export wrappers)
  │    └── report.py           (HTML report generation)
  ├── MyTab.tab/
  │    ├── QA.panel/
  │    │    ├── CheckRooms.pushbutton/
  │    │    ├── CheckNaming.pushbutton/
  │    │    └── CheckParams.pushbutton/
  │    ├── Export.panel/
  │    │    ├── BatchPDF.pushbutton/
  │    │    └── BatchIFC.pushbutton/
  │    └── Data.panel/
  │         ├── ParamWriter.pushbutton/
  │         └── ExcelSync.pushbutton/
  └── hooks/
       └── doc-opened-[audit].py

Testing Strategies

  1. Test on a dedicated test model --- a small .rvt file with representative elements of every category.
  2. Log extensively during development --- use print() or pyRevit's output module.
  3. Test edge cases --- empty parameters, zero-area rooms, unplaced rooms, design options, phases, linked models.
  4. Version test --- verify scripts work across target Revit versions (2022, 2023, 2024, 2025).
  5. Performance test --- run scripts on the largest project model to identify bottlenecks.
  6. User acceptance test --- deploy to 2-3 users before firm-wide rollout; collect feedback.
  7. Regression test --- after Revit updates, re-run all scripts to verify continued functionality.

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.