Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Convert RVT files to IFC format. Support IFC2x3, IFC4, IFC4.3 with customizable export settings.
.claude/skills/datadrivenconstruction-rvt-to-ifc/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-04 | ✗→✓ | ▲ Improved | 271% | 0% |
| case-05 | ✗→✓ | ▲ Improved | 72% | 0% |
| case-06 | ✗→✓ | ▲ Improved | 201% | 0% |
| case-07 | ✗→✓ | ▲ Improved | 90% | 0% |
| case-09 | ✗→✓ | ▲ Improved | 53% | 0% |
> Note: RVT is the file format. IFC is an open standard by buildingSMART International.
IFC is the open BIM standard for interoperability, but:
RVT2IFCconverter.exe converts Revit files to IFC offline, without licenses, with full control over export settings.
bashRVT2IFCconverter.exe <input.rvt> [<output.ifc>] [preset=<name>] [config="..."]
| Version | Use Case | |---------|----------| | IFC2x3 | Legacy compatibility, most software | | IFC4 | Enhanced properties, modern BIM | | IFC4.3 | Infrastructure, latest standard |
| Preset | Description | |--------|-------------| | standard | Default balanced export | | extended | Maximum detail and properties | | custom | User-defined configuration |
bash# Standard IFC export RVT2IFCconverter.exe "C:\Projects\Building.rvt" # IFC4 with extended settings RVT2IFCconverter.exe "C:\Projects\Building.rvt" preset=extended # Custom output path RVT2IFCconverter.exe "C:\Projects\Building.rvt" "D:\Export\model.ifc" # Custom configuration RVT2IFCconverter.exe "C:\Projects\Building.rvt" config="ExportBaseQuantities=true; SitePlacement=Shared"
pythonimport subprocess from pathlib import Path from typing import List, Optional, Dict, Any from dataclasses import dataclass from enum import Enum class IFCVersion(Enum): """IFC schema versions.""" IFC2X3 = "IFC2x3" IFC4 = "IFC4" IFC4X3 = "IFC4x3" class ExportPreset(Enum): """Export presets.""" STANDARD = "standard" EXTENDED = "extended" CUSTOM = "custom" @dataclass class IFCExportConfig: """IFC export configuration.""" ifc_version: IFCVersion = IFCVersion.IFC4 export_base_quantities: bool = True site_placement: str = "Shared" split_walls_and_columns: bool = False include_steel_elements: bool = True export_2d_elements: bool = False export_linked_files: bool = False export_rooms: bool = True export_schedules: bool = True def to_config_string(self) -> str: """Convert to CLI config string.""" parts = [ f"ExportBaseQuantities={str(self.export_base_quantities).lower()}", f"SitePlacement={self.site_placement}", f"SplitWallsAndColumns={str(self.split_walls_and_columns).lower()}", f"IncludeSteelElements={str(self.include_steel_elements).lower()}", f"Export2DElements={str(self.export_2d_elements).lower()}", f"ExportLinkedFiles={str(self.export_linked_files).lower()}", f"ExportRooms={str(self.export_rooms).lower()}" ] return "; ".join(parts) class RevitToIFCConverter: """Convert Revit files to IFC format.""" def __init__(self, converter_path: str = "RVT2IFCconverter.exe"): self.converter = Path(converter_path) if not self.converter.exists(): raise FileNotFoundError(f"Converter not found: {converter_path}") def convert(self, rvt_file: str, output_path: Optional[str] = None, preset: ExportPreset = ExportPreset.STANDARD, config: Optional[IFCExportConfig] = None) -> Path: """Convert Revit file to IFC.""" rvt_path = Path(rvt_file) if not rvt_path.exists(): raise FileNotFoundError(f"Revit file not found: {rvt_file}") # Build command cmd = [str(self.converter), str(rvt_path)] # Add output path if specified if output_path: cmd.append(output_path) # Add preset cmd.append(f"preset={preset.value}") # Add custom config if provided if config: cmd.append(f'config="{config.to_config_string()}"') # Execute result = subprocess.run(cmd, capture_output=True, text=True) if result.returncode != 0: raise RuntimeError(f"Conversion failed: {result.stderr}") # Return output path if output_path: return Path(output_path) return rvt_path.with_suffix('.ifc') def batch_convert(self, folder: str, output_folder: Optional[str] = None, preset: ExportPreset = ExportPreset.STANDARD, config: Optional[IFCExportConfig] = None) -> List[Dict[str, Any]]: """Convert all Revit files in folder.""" folder_path = Path(folder) results = [] for rvt_file in folder_path.glob("**/*.rvt"): try: # Determine output path if output_folder: out_dir = Path(output_folder) out_dir.mkdir(parents=True, exist_ok=True) output_path = str(out_dir / rvt_file.with_suffix('.ifc').name) else: output_path = None ifc_path = self.convert(str(rvt_file), output_path, preset, config) results.append({ 'input': str(rvt_file), 'output': str(ifc_path), 'status': 'success' }) print(f"✓ Converted: {rvt_file.name}") except Exception as e: results.append({ 'input': str(rvt_file), 'output': None, 'status': 'failed', 'error': str(e) }) print(f"✗ Failed: {rvt_file.name} - {e}") return results def validate_output(self, ifc_file: str) -> Dict[str, Any]: """Basic validation of generated IFC.""" ifc_path = Path(ifc_file) if not ifc_path.exists(): return {'valid': False, 'error': 'File not found'} # Basic file checks file_size = ifc_path.stat().st_size if file_size < 1000: return {'valid': False, 'error': 'File too small'} # Read header with open(ifc_file, 'r', errors='ignore') as f: header = f.read(1000) # Check IFC format if 'ISO-10303-21' not in header: return {'valid': False, 'error': 'Not a valid IFC file'} # Detect version version = 'Unknown' if 'IFC4X3' in header: version = 'IFC4.3' elif 'IFC4' in header: version = 'IFC4' elif 'IFC2X3' in header: version = 'IFC2x3' return { 'valid': True, 'file_size': file_size, 'ifc_version': version } class IFCQualityChecker: """Check quality of IFC exports.""" def __init__(self, converter: RevitToIFCConverter): self.converter = converter def compare_presets(self, rvt_file: str) -> Dict[str, Any]: """Compare different export presets.""" results = {} for preset in [ExportPreset.STANDARD, ExportPreset.EXTENDED]: try: output = Path(rvt_file).with_suffix(f'.{preset.value}.ifc') self.converter.convert(rvt_file, str(output), preset) validation = self.converter.validate_output(str(output)) results[preset.value] = { 'file_size': validation.get('file_size', 0), 'valid': validation.get('valid', False) } except Exception as e: results[preset.value] = {'error': str(e)} return results # Convenience functions def convert_revit_to_ifc(rvt_file: str, converter_path: str = "RVT2IFCconverter.exe") -> str: """Quick conversion of Revit to IFC.""" converter = RevitToIFCConverter(converter_path) output = converter.convert(rvt_file) return str(output) def batch_convert_to_ifc(folder: str, converter_path: str = "RVT2IFCconverter.exe") -> List[str]: """Batch convert all Revit files to IFC.""" converter = RevitToIFCConverter(converter_path) results = converter.batch_convert(folder) return [r['output'] for r in results if r['status'] == 'success']
python# Initialize converter converter = RevitToIFCConverter("C:/DDC/RVT2IFCconverter.exe") # Basic conversion ifc = converter.convert("building.rvt") print(f"Created: {ifc}") # With custom config config = IFCExportConfig( ifc_version=IFCVersion.IFC4, export_base_quantities=True, export_rooms=True ) ifc = converter.convert("building.rvt", preset=ExportPreset.CUSTOM, config=config)
pythonconverter = RevitToIFCConverter() results = converter.batch_convert( folder="C:/Projects", output_folder="C:/IFC_Export", preset=ExportPreset.EXTENDED ) print(f"Converted {len([r for r in results if r['status'] == 'success'])} files")
pythonvalidation = converter.validate_output("model.ifc") print(f"Valid: {validation['valid']}, Version: {validation['ifc_version']}")
pythonchecker = IFCQualityChecker(converter) comparison = checker.compare_presets("building.rvt") print(comparison)
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | fail→fail | 16,911 | 12,756 | -25% | 1 | 1 | 0% | 3,153 | 5,289 | +68% | 0 | 0 | — |
case-02 | fail→fail | 21,785 | 11,616 | -47% | 1 | 1 | 0% | 3,971 | 5,251 | +32% | 0 | 0 | — |
case-03 | fail→fail | 17,069 | 10,492 | -39% | 1 | 1 | 0% | 3,176 | 4,922 | +55% | 0 | 0 | — |
case-04 | fail→pass | 4,967 | 2,696 | -46% | 1 | 1 | 0% | 852 | 3,161 | +271% | 0 | 0 | — |
case-05 | fail→pass | 12,684 | 4,153 | -67% | 1 | 1 | 0% | 2,024 | 3,487 | +72% | 0 | 0 | — |
case-06 | fail→pass | 16,362 | 2,815 | -83% | 1 | 1 | 0% | 1,063 | 3,195 | +201% | 0 | 0 | — |
case-07 | fail→pass | 9,084 | 2,292 | -75% | 1 | 1 | 0% | 1,666 | 3,171 | +90% | 0 | 0 | — |
case-08 | pass→pass | 13,946 | 1,618 | -88% | 1 | 1 | 0% | 2,239 | 2,951 | +32% | 0 | 0 | — |
case-09 | fail→pass | 15,211 | 5,896 | -61% | 1 | 1 | 0% | 2,538 | 3,895 | +53% | 0 | 0 | — |
case-10 | fail→pass | 8,181 | 1,767 | -78% | 1 | 1 | 0% | 1,427 | 3,051 | +114% | 0 | 0 | — |
case-11 | fail→pass | 4,332 | 4,469 | +3% | 1 | 1 | 0% | 735 | 3,613 | +392% | 0 | 0 | — |
case-12 | fail→pass | 27,346 | 2,753 | -90% | 1 | 1 | 0% | 1,773 | 3,174 | +79% | 0 | 0 | — |
case-13 | pass→pass | 7,101 | 3,536 | -50% | 1 | 1 | 0% | 1,159 | 3,361 | +190% | 0 | 0 | — |
case-14 | fail→pass | 9,821 | 3,702 | -62% | 1 | 1 | 0% | 1,569 | 3,433 | +119% | 0 | 0 | — |
case-15 | fail→pass | 11,338 | 4,526 | -60% | 1 | 1 | 0% | 2,063 | 3,554 | +72% | 0 | 0 | — |
case-16 | fail→pass | 12,332 | 5,416 | -56% | 1 | 1 | 0% | 1,986 | 3,737 | +88% | 0 | 0 | — |
case-17 | fail→pass | 12,188 | 2,178 | -82% | 1 | 1 | 0% | 2,075 | 3,087 | +49% | 0 | 0 | — |
case-18 | fail→pass | 9,566 | 3,120 | -67% | 1 | 1 | 0% | 1,550 | 3,256 | +110% | 0 | 0 | — |
case-19 | pass→pass | 11,468 | 5,123 | -55% | 1 | 1 | 0% | 1,803 | 3,612 | +100% | 0 | 0 | — |
case-20 | pass→pass | 12,553 | 5,989 | -52% | 1 | 1 | 0% | 2,219 | 3,790 | +71% | 0 | 0 | — |
case-21 | pass→pass | 11,863 | 10,267 | -13% | 1 | 1 | 0% | 2,217 | 4,766 | +115% | 0 | 0 | — |
case-22 | pass→pass | 4,416 | 4,506 | +2% | 1 | 1 | 0% | 813 | 3,632 | +347% | 0 | 0 | — |
case-23 | pass→pass | 17,696 | 14,549 | -18% | 1 | 1 | 0% | 3,179 | 5,546 | +74% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 23 cases were attempted, and 21 counted toward the lift figure. The other 2 produced results that are not comparable between the two arms, so they are excluded from the headline rather than averaged into it. The headline lift of +57 percentage points is the difference between those two pass rates over the 21 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.