Synchronize construction digital twins with real-time data. An agent skill from datadrivenconstruction/DDC_Skills_for_AI_Agents_in_Construction.

MITAuto-check passed

Install Digital Twin Sync

skills CLI
$ npx skills add datadrivenconstruction/DDC_Skills_for_AI_Agents_in_Construction --skill digital-twin-sync -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install datadrivenconstruction/DDC_Skills_for_AI_Agents_in_Construction digital-twin-sync --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/datadrivenconstruction/DDC_Skills_for_AI_Agents_in_Construction.git skills-src && mkdir -p .claude/skills && cp -r skills-src/5_DDC_Innovative/digital-twin-sync .claude/skills/digital-twin-sync && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
digital-twin-sync
GitHub stars
344
Used in
1 other repo
Token cost
~6.3k tokens
SKILL.md length
118 words
Files
3
Skills in repo
43
Repo updated
First seen
Licence
MIT

At a glance

Synchronize construction digital twins with real-time data. An agent skill from datadrivenconstruction/DDC_Skills_for_AI_Agents_in_Construction.

  • SKILL.md covers Overview, Quick Start, Comprehensive Digital Twin… and Quick Reference, plus 2 more sections
  • Instructions only: no scripts, shell commands, URLs or credentials in SKILL.md

What it does

Digital Twin Sync is an agent skill from datadrivenconstruction/DDC_Skills_for_AI_Agents_in_Construction. Synchronize construction digital twins with real-time data. Connect BIM models with IoT sensors, progress updates, and field data for live project visualization and monitoring.

Its SKILL.md is about 6.3k tokens, which your agent loads only when the skill is triggered. The skill folder holds 2 other files (for example `claw.json` and `instructions.md`).

The repository describes itself as: 221 AI skills for construction: BIM analysis, cost estimation, scheduling, document control, and automation with Claude Code. The licence is MIT.

Example prompts

  • “/digital-twin-sync”

Requirements

  • Python 3

What it can do on your machine

Read from SKILL.md and the folder at commit ce45bbf. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    No scripts in the folder and no shell commands in SKILL.md (its code samples are python).

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    Links to these hosts (documentation or services it may open):

    • digitaltwinconsortium.org
    • buildingsmart.org
    • datadrivenconstruction.io

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Digital Twin Sync loads about 6.3k tokens when it runs. Until then it costs about 49 tokens; SKILL.md has 118 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~49
When it runs · the whole SKILL.md, loaded when a task matches
~6.3k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from datadrivenconstruction/DDC_Skills_for_AI_Agents_in_Construction at commit ce45bbf, republished under its MIT licence (© datadrivenconstruction). 118 words, ~6,346 tokens.

Download SKILL.mdSave it as .claude/skills/digital-twin-sync/SKILL.md (or your agent's skills folder). This skill also uses 2 other files; get the full folder from GitHub.
name
digital-twin-sync
description
Synchronize construction digital twins with real-time data. Connect BIM models with IoT sensors, progress updates, and field data for live project visualization and monitoring.
homepage
https://datadrivenconstruction.io

Digital Twin Synchronization

Overview

This skill implements digital twin synchronization for construction projects. Connect BIM models with real-time sensor data, progress updates, and field information to create a living digital representation.

Capabilities:

  • BIM-IoT data binding
  • Real-time status updates
  • Historical data tracking
  • Anomaly detection
  • Predictive analytics
  • Multi-source data fusion

Quick Start

python
from dataclasses import dataclass, field
from datetime import datetime
from typing import Dict, List, Optional, Any
from enum import Enum
import json

class ElementStatus(Enum):
    PLANNED = "planned"
    IN_PROGRESS = "in_progress"
    COMPLETED = "completed"
    ISSUE = "issue"

@dataclass
class TwinElement:
    element_id: str
    ifc_guid: str
    element_type: str
    status: ElementStatus
    properties: Dict[str, Any] = field(default_factory=dict)
    sensor_bindings: List[str] = field(default_factory=list)
    last_updated: datetime = field(default_factory=datetime.now)

@dataclass
class SensorData:
    sensor_id: str
    value: float
    unit: str
    timestamp: datetime
    quality: float = 1.0

class SimpleTwin:
    """Simple digital twin implementation"""

    def __init__(self, project_id: str):
        self.project_id = project_id
        self.elements: Dict[str, TwinElement] = {}
        self.sensor_data: Dict[str, List[SensorData]] = {}

    def add_element(self, element: TwinElement):
        self.elements[element.element_id] = element

    def bind_sensor(self, element_id: str, sensor_id: str):
        if element_id in self.elements:
            self.elements[element_id].sensor_bindings.append(sensor_id)

    def update_sensor(self, data: SensorData):
        if data.sensor_id not in self.sensor_data:
            self.sensor_data[data.sensor_id] = []
        self.sensor_data[data.sensor_id].append(data)

        # Update linked elements
        for elem in self.elements.values():
            if data.sensor_id in elem.sensor_bindings:
                elem.properties[f'sensor_{data.sensor_id}'] = data.value
                elem.last_updated = data.timestamp

    def get_element_state(self, element_id: str) -> Dict:
        elem = self.elements.get(element_id)
        if not elem:
            return {}

        state = {
            'element_id': elem.element_id,
            'status': elem.status.value,
            'properties': elem.properties,
            'last_updated': elem.last_updated.isoformat()
        }

        # Add latest sensor values
        for sensor_id in elem.sensor_bindings:
            if sensor_id in self.sensor_data and self.sensor_data[sensor_id]:
                latest = self.sensor_data[sensor_id][-1]
                state[f'sensor_{sensor_id}'] = {
                    'value': latest.value,
                    'unit': latest.unit,
                    'timestamp': latest.timestamp.isoformat()
                }

        return state

# Example
twin = SimpleTwin("PROJECT-001")
twin.add_element(TwinElement(
    element_id="WALL-001",
    ifc_guid="2O2Fr$t4X7Zf8NOew3FLOH",
    element_type="IfcWall",
    status=ElementStatus.IN_PROGRESS
))
twin.bind_sensor("WALL-001", "TEMP-001")
twin.update_sensor(SensorData("TEMP-001", 22.5, "°C", datetime.now()))
print(twin.get_element_state("WALL-001"))

Comprehensive Digital Twin System

Core Twin Model
python
from dataclasses import dataclass, field
from datetime import datetime, timedelta
from typing import Dict, List, Optional, Any, Callable
from enum import Enum
import json
import threading
from queue import Queue
import time

class DataSource(Enum):
    BIM = "bim"
    IOT = "iot"
    SCHEDULE = "schedule"
    FIELD = "field"
    DRONE = "drone"
    MANUAL = "manual"

@dataclass
class PropertyValue:
    value: Any
    unit: Optional[str]
    timestamp: datetime
    source: DataSource
    confidence: float = 1.0
    history: List[Dict] = field(default_factory=list)

@dataclass
class DigitalTwinElement:
    element_id: str
    ifc_guid: str
    element_type: str
    name: str
    status: ElementStatus = ElementStatus.PLANNED
    properties: Dict[str, PropertyValue] = field(default_factory=dict)
    sensor_bindings: Dict[str, str] = field(default_factory=dict)  # property_name -> sensor_id
    geometry_ref: Optional[str] = None
    parent_id: Optional[str] = None
    children_ids: List[str] = field(default_factory=list)
    schedule_activity_id: Optional[str] = None
    created_at: datetime = field(default_factory=datetime.now)
    updated_at: datetime = field(default_factory=datetime.now)

    def update_property(self, name: str, value: Any, unit: str = None,
                       source: DataSource = DataSource.MANUAL,
                       confidence: float = 1.0):
        """Update property with history tracking"""
        now = datetime.now()

        if name in self.properties:
            # Store previous value in history
            prev = self.properties[name]
            prev.history.append({
                'value': prev.value,
                'timestamp': prev.timestamp.isoformat(),
                'source': prev.source.value
            })
            # Keep only last 100 values
            prev.history = prev.history[-100:]

            prev.value = value
            prev.unit = unit or prev.unit
            prev.timestamp = now
            prev.source = source
            prev.confidence = confidence
        else:
            self.properties[name] = PropertyValue(
                value=value,
                unit=unit,
                timestamp=now,
                source=source,
                confidence=confidence
            )

        self.updated_at = now

@dataclass
class TwinEvent:
    event_id: str
    event_type: str  # property_update, status_change, alert, etc.
    element_id: str
    timestamp: datetime
    data: Dict
    source: DataSource

class DigitalTwinCore:
    """Core digital twin management system"""

    def __init__(self, project_id: str, project_name: str):
        self.project_id = project_id
        self.project_name = project_name
        self.elements: Dict[str, DigitalTwinElement] = {}
        self.events: List[TwinEvent] = []
        self.event_handlers: Dict[str, List[Callable]] = {}
        self.update_queue: Queue = Queue()
        self._running = False

    def import_from_ifc(self, ifc_data: List[Dict]):
        """Import elements from IFC data"""
        for elem_data in ifc_data:
            element = DigitalTwinElement(
                element_id=elem_data.get('id', f"ELEM-{len(self.elements)}"),
                ifc_guid=elem_data.get('guid', ''),
                element_type=elem_data.get('type', 'IfcBuildingElement'),
                name=elem_data.get('name', 'Unknown'),
                geometry_ref=elem_data.get('geometry_ref')
            )

            # Import properties
            for prop_name, prop_value in elem_data.get('properties', {}).items():
                element.update_property(
                    prop_name,
                    prop_value.get('value'),
                    prop_value.get('unit'),
                    DataSource.BIM
                )

            self.elements[element.element_id] = element

    def bind_sensor_to_property(self, element_id: str, property_name: str,
                               sensor_id: str, transform: Callable = None):
        """Bind IoT sensor to element property"""
        element = self.elements.get(element_id)
        if element:
            element.sensor_bindings[property_name] = sensor_id
            # Store transform function if needed
            if transform:
                element.sensor_bindings[f'{property_name}_transform'] = transform

    def process_sensor_update(self, sensor_id: str, value: float,
                             unit: str, timestamp: datetime = None):
        """Process incoming sensor data"""
        timestamp = timestamp or datetime.now()

        # Find all elements bound to this sensor
        for element in self.elements.values():
            for prop_name, bound_sensor in element.sensor_bindings.items():
                if bound_sensor == sensor_id and not prop_name.endswith('_transform'):
                    # Apply transform if exists
                    transform_key = f'{prop_name}_transform'
                    if transform_key in element.sensor_bindings:
                        transform = element.sensor_bindings[transform_key]
                        value = transform(value)

                    element.update_property(prop_name, value, unit, DataSource.IOT)

                    # Create event
                    self._emit_event('property_update', element.element_id, {
                        'property': prop_name,
                        'value': value,
                        'sensor_id': sensor_id
                    }, DataSource.IOT)

    def update_status(self, element_id: str, status: ElementStatus,
                     source: DataSource = DataSource.FIELD):
        """Update element construction status"""
        element = self.elements.get(element_id)
        if not element:
            return

        old_status = element.status
        element.status = status
        element.updated_at = datetime.now()

        self._emit_event('status_change', element_id, {
            'old_status': old_status.value,
            'new_status': status.value
        }, source)

    def _emit_event(self, event_type: str, element_id: str,
                   data: Dict, source: DataSource):
        """Emit twin event"""
        event = TwinEvent(
            event_id=f"EVT-{len(self.events):06d}",
            event_type=event_type,
            element_id=element_id,
            timestamp=datetime.now(),
            data=data,
            source=source
        )

        self.events.append(event)

        # Notify handlers
        for handler in self.event_handlers.get(event_type, []):
            try:
                handler(event)
            except Exception as e:
                print(f"Event handler error: {e}")

    def on_event(self, event_type: str, handler: Callable):
        """Register event handler"""
        if event_type not in self.event_handlers:
            self.event_handlers[event_type] = []
        self.event_handlers[event_type].append(handler)

    def get_element_snapshot(self, element_id: str) -> Dict:
        """Get current state snapshot of element"""
        element = self.elements.get(element_id)
        if not element:
            return {}

        return {
            'element_id': element.element_id,
            'ifc_guid': element.ifc_guid,
            'type': element.element_type,
            'name': element.name,
            'status': element.status.value,
            'properties': {
                name: {
                    'value': prop.value,
                    'unit': prop.unit,
                    'timestamp': prop.timestamp.isoformat(),
                    'source': prop.source.value,
                    'confidence': prop.confidence
                }
                for name, prop in element.properties.items()
            },
            'updated_at': element.updated_at.isoformat()
        }

    def get_project_snapshot(self) -> Dict:
        """Get full project state snapshot"""
        status_counts = {}
        for elem in self.elements.values():
            status = elem.status.value
            status_counts[status] = status_counts.get(status, 0) + 1

        return {
            'project_id': self.project_id,
            'project_name': self.project_name,
            'timestamp': datetime.now().isoformat(),
            'element_count': len(self.elements),
            'status_summary': status_counts,
            'recent_events': [
                {
                    'event_id': e.event_id,
                    'type': e.event_type,
                    'element': e.element_id,
                    'timestamp': e.timestamp.isoformat()
                }
                for e in self.events[-10:]
            ]
        }
Real-Time Synchronization
python
import asyncio
from typing import Dict, List, Callable
import websockets
import json

class TwinSynchronizer:
    """Real-time twin synchronization service"""

    def __init__(self, twin: DigitalTwinCore):
        self.twin = twin
        self.subscribers: Dict[str, List[websockets.WebSocketServerProtocol]] = {}
        self.sync_interval = 1.0  # seconds

    async def start_server(self, host: str = 'localhost', port: int = 8765):
        """Start WebSocket server for real-time updates"""
        async with websockets.serve(self._handle_connection, host, port):
            print(f"Twin sync server running on ws://{host}:{port}")
            await asyncio.Future()  # Run forever

    async def _handle_connection(self, websocket, path):
        """Handle WebSocket connection"""
        try:
            async for message in websocket:
                data = json.loads(message)
                await self._process_message(websocket, data)
        except websockets.exceptions.ConnectionClosed:
            pass
        finally:
            # Remove from all subscriptions
            for element_id in list(self.subscribers.keys()):
                if websocket in self.subscribers[element_id]:
                    self.subscribers[element_id].remove(websocket)

    async def _process_message(self, websocket, data: Dict):
        """Process incoming message"""
        msg_type = data.get('type')

        if msg_type == 'subscribe':
            element_id = data.get('element_id', '*')
            if element_id not in self.subscribers:
                self.subscribers[element_id] = []
            self.subscribers[element_id].append(websocket)

            # Send current state
            if element_id == '*':
                state = self.twin.get_project_snapshot()
            else:
                state = self.twin.get_element_snapshot(element_id)

            await websocket.send(json.dumps({
                'type': 'state',
                'data': state
            }))

        elif msg_type == 'update':
            # Handle incoming update from field
            element_id = data.get('element_id')
            updates = data.get('updates', {})

            for prop_name, value in updates.items():
                element = self.twin.elements.get(element_id)
                if element:
                    element.update_property(prop_name, value, source=DataSource.FIELD)

            # Broadcast update
            await self._broadcast_update(element_id)

        elif msg_type == 'status_update':
            element_id = data.get('element_id')
            status = ElementStatus(data.get('status'))
            self.twin.update_status(element_id, status, DataSource.FIELD)
            await self._broadcast_update(element_id)

    async def _broadcast_update(self, element_id: str):
        """Broadcast element update to subscribers"""
        state = self.twin.get_element_snapshot(element_id)
        message = json.dumps({
            'type': 'update',
            'element_id': element_id,
            'data': state
        })

        # Send to specific element subscribers
        for ws in self.subscribers.get(element_id, []):
            try:
                await ws.send(message)
            except:
                pass

        # Send to wildcard subscribers
        for ws in self.subscribers.get('*', []):
            try:
                await ws.send(message)
            except:
                pass

    def setup_sensor_integration(self, mqtt_client):
        """Setup MQTT integration for IoT sensors"""
        def on_message(client, userdata, msg):
            try:
                data = json.loads(msg.payload.decode())
                self.twin.process_sensor_update(
                    sensor_id=data.get('sensor_id'),
                    value=data.get('value'),
                    unit=data.get('unit'),
                    timestamp=datetime.fromisoformat(data.get('timestamp'))
                )
            except Exception as e:
                print(f"Sensor message error: {e}")

        mqtt_client.on_message = on_message
        mqtt_client.subscribe("sensors/#")
Schedule Integration
python
from datetime import date, datetime

@dataclass
class ScheduleActivity:
    activity_id: str
    name: str
    planned_start: date
    planned_end: date
    actual_start: Optional[date] = None
    actual_end: Optional[date] = None
    percent_complete: float = 0
    element_ids: List[str] = field(default_factory=list)

class ScheduleTwinIntegrator:
    """Integrate schedule with digital twin"""

    def __init__(self, twin: DigitalTwinCore):
        self.twin = twin
        self.activities: Dict[str, ScheduleActivity] = {}

    def import_schedule(self, schedule_data: List[Dict]):
        """Import schedule activities"""
        for act_data in schedule_data:
            activity = ScheduleActivity(
                activity_id=act_data['id'],
                name=act_data['name'],
                planned_start=date.fromisoformat(act_data['start']),
                planned_end=date.fromisoformat(act_data['end']),
                element_ids=act_data.get('elements', [])
            )
            self.activities[activity.activity_id] = activity

            # Link elements to activity
            for elem_id in activity.element_ids:
                if elem_id in self.twin.elements:
                    self.twin.elements[elem_id].schedule_activity_id = activity.activity_id

    def update_activity_progress(self, activity_id: str, percent_complete: float,
                                actual_start: date = None, actual_end: date = None):
        """Update activity progress"""
        activity = self.activities.get(activity_id)
        if not activity:
            return

        activity.percent_complete = percent_complete
        if actual_start:
            activity.actual_start = actual_start
        if actual_end:
            activity.actual_end = actual_end

        # Update linked elements
        status = self._determine_status(percent_complete)
        for elem_id in activity.element_ids:
            self.twin.update_status(elem_id, status, DataSource.SCHEDULE)

    def _determine_status(self, percent: float) -> ElementStatus:
        """Determine element status from progress percentage"""
        if percent == 0:
            return ElementStatus.PLANNED
        elif percent < 100:
            return ElementStatus.IN_PROGRESS
        else:
            return ElementStatus.COMPLETED

    def calculate_schedule_variance(self) -> Dict:
        """Calculate schedule performance"""
        today = date.today()
        variances = []

        for activity in self.activities.values():
            planned_duration = (activity.planned_end - activity.planned_start).days
            if planned_duration == 0:
                continue

            if activity.actual_start:
                start_variance = (activity.actual_start - activity.planned_start).days
            else:
                start_variance = None

            if activity.actual_end:
                end_variance = (activity.actual_end - activity.planned_end).days
            else:
                end_variance = None

            # Calculate expected progress
            if today >= activity.planned_end:
                expected_progress = 100
            elif today <= activity.planned_start:
                expected_progress = 0
            else:
                elapsed = (today - activity.planned_start).days
                expected_progress = elapsed / planned_duration * 100

            progress_variance = activity.percent_complete - expected_progress

            variances.append({
                'activity_id': activity.activity_id,
                'name': activity.name,
                'planned_start': activity.planned_start.isoformat(),
                'planned_end': activity.planned_end.isoformat(),
                'actual_progress': activity.percent_complete,
                'expected_progress': expected_progress,
                'progress_variance': progress_variance,
                'start_variance_days': start_variance,
                'status': 'ahead' if progress_variance > 0 else 'behind' if progress_variance < -5 else 'on_track'
            })

        return {
            'date': today.isoformat(),
            'activities': variances,
            'on_track_count': sum(1 for v in variances if v['status'] == 'on_track'),
            'ahead_count': sum(1 for v in variances if v['status'] == 'ahead'),
            'behind_count': sum(1 for v in variances if v['status'] == 'behind')
        }
Anomaly Detection
python
import numpy as np
from collections import deque

class TwinAnomalyDetector:
    """Detect anomalies in digital twin data"""

    def __init__(self, twin: DigitalTwinCore, window_size: int = 100):
        self.twin = twin
        self.window_size = window_size
        self.value_windows: Dict[str, deque] = {}  # key: element_id:property
        self.thresholds: Dict[str, Dict] = {}

    def set_threshold(self, element_id: str, property_name: str,
                     min_value: float = None, max_value: float = None,
                     std_multiplier: float = 3.0):
        """Set threshold for property monitoring"""
        key = f"{element_id}:{property_name}"
        self.thresholds[key] = {
            'min': min_value,
            'max': max_value,
            'std_multiplier': std_multiplier
        }

    def check_value(self, element_id: str, property_name: str, value: float) -> Dict:
        """Check value for anomalies"""
        key = f"{element_id}:{property_name}"

        # Initialize window if needed
        if key not in self.value_windows:
            self.value_windows[key] = deque(maxlen=self.window_size)

        window = self.value_windows[key]

        anomaly = {
            'is_anomaly': False,
            'type': None,
            'severity': 'normal',
            'details': {}
        }

        # Check against thresholds
        if key in self.thresholds:
            thresh = self.thresholds[key]

            if thresh['min'] is not None and value < thresh['min']:
                anomaly['is_anomaly'] = True
                anomaly['type'] = 'below_minimum'
                anomaly['severity'] = 'warning'
                anomaly['details']['threshold'] = thresh['min']
                anomaly['details']['value'] = value

            if thresh['max'] is not None and value > thresh['max']:
                anomaly['is_anomaly'] = True
                anomaly['type'] = 'above_maximum'
                anomaly['severity'] = 'warning'
                anomaly['details']['threshold'] = thresh['max']
                anomaly['details']['value'] = value

        # Statistical anomaly detection
        if len(window) >= 10:
            mean = np.mean(window)
            std = np.std(window)

            if std > 0:
                z_score = abs(value - mean) / std
                if z_score > 3:
                    anomaly['is_anomaly'] = True
                    anomaly['type'] = 'statistical_outlier'
                    anomaly['severity'] = 'critical' if z_score > 5 else 'warning'
                    anomaly['details']['z_score'] = z_score
                    anomaly['details']['mean'] = mean
                    anomaly['details']['std'] = std

        # Add to window
        window.append(value)

        return anomaly

    def monitor_element(self, element_id: str) -> List[Dict]:
        """Monitor all properties of an element for anomalies"""
        element = self.twin.elements.get(element_id)
        if not element:
            return []

        anomalies = []
        for prop_name, prop in element.properties.items():
            if isinstance(prop.value, (int, float)):
                result = self.check_value(element_id, prop_name, prop.value)
                if result['is_anomaly']:
                    result['element_id'] = element_id
                    result['property'] = prop_name
                    result['timestamp'] = prop.timestamp.isoformat()
                    anomalies.append(result)

        return anomalies

Quick Reference

Data SourceUpdate FrequencyReliability
BIM ModelOn changeHigh
IoT SensorsReal-timeVariable
ScheduleDailyHigh
Field UpdatesEvent-drivenMedium
Drone SurveysPeriodicHigh

Resources

Next Steps

  • See material-tracking-iot for IoT integration
  • See 4d-simulation for schedule visualization
  • See bim-validation-pipeline for model validation

© datadrivenconstruction, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

SKILL.md and 2 other files in 5_DDC_Innovative/digital-twin-sync of datadrivenconstruction/DDC_Skills_for_AI_Agents_in_Construction.

  • SKILL.md
  • claw.json
  • instructions.md

Open the folder on GitHubat commit ce45bbf

Used in 1 other repository

We found 1 copy of this SKILL.md (exact, near-identical or edited) in other folders, from 1 other GitHub owner. This page covers the copy in datadrivenconstruction/DDC_Skills_for_AI_Agents_in_Construction, which our catalogue first saw on October 7, 2026.

Compare with similar skills

Digital Twin Sync next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Digital Twin Sync compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Digital Twin Sync this skilldatadrivenconstruction/DDC_Skills_for_AI_Agents_in_Construction3441 repos~6.3kAutomated safety check: PassMIT
ConnectComposioHQ/awesome-claude-skills77k3 repos~987Automated safety check: PassNone
Claude-Mem Cloud Syncthedotmack/claude-mem98k1 repos~1kAutomated safety check: NotesApache-2.0
Node Connectopenclaw/openclaw392k—~1.6kAutomated safety check: PassMIT
Digital Forensicssickn33/agentic-awesome-skills47k1 repos~495Automated safety check: PassMIT
Digital Forensicszhaoxuya520/reverse-skill40k2 repos~389Automated safety check: WarnMIT

Similar skills

  • Connect

    ComposioHQ/awesome-claude-skills

    Connect Claude to any app. An agent skill from ComposioHQ/awesome-claude-skills.

    77k GitHub starsUsed in 3 repos~987 tokens
    Productivity & AutomationAuto-check passed
  • Claude-Mem Cloud Sync

    thedotmack/claude-mem

    Checks claude-mem cloud sync status and guides you through connecting a cmem.ai Pro account without the sync token ever passing through the chat.

    98k GitHub starsUsed in 1 repo~1k tokens
    Agent WorkflowsAuto-check: notes
  • Node Connect

    openclaw/openclaw

    Diagnose OpenClaw Control UI browser and native Android, iOS, or macOS node connection failures across route, auth, pairing, QR/setup-code, and reconnect states.

    392k GitHub stars~1.6k tokensUpdated today
    MobileAuto-check passed
  • Digital Forensics

    sickn33/agentic-awesome-skills

    Authorized digital forensics: memory dumps, disk timelines, PCAP investigation, artifact triage, and incident-response evidence preservation.

    47k GitHub starsUsed in 1 repo~495 tokens
    SecurityAuto-check passed
  • Digital Forensics

    zhaoxuya520/reverse-skill

    A skill your agent uses for authorized digital forensics including memory dumps, disk timelines, PCAP investigation, artifact triage, and IR evidence preservation.

    40k GitHub starsUsed in 2 repos~389 tokens
    SecurityAuto-check: warnings
  • I18n Sync

    affaan-m/ECC

    Translate and synchronize application JSON locale files using source-key usage, project terminology, and focused validation.

    275k GitHub stars~1.8k tokensUpdated 3 days ago
    Frontend & DesignAuto-check passed

More from datadrivenconstruction/DDC_Skills_for_AI_Agents_in_Construction

All 43 skills in this repo
  • AI Agent Orchestration

    datadrivenconstruction/DDC_Skills_for_AI_Agents_in_Construction

    Orchestrate multiple AI agents for construction workflows: estimator, scheduler, document, QA and safety agents coordinated by a supervisor agent, with human checkpoints.

    344 GitHub stars~679 tokensUpdated 1 mo ago
    Auto-check passed
  • Embodied Carbon Esg

    datadrivenconstruction/DDC_Skills_for_AI_Agents_in_Construction

    Estimate embodied carbon and produce ESG/climate reporting for construction: LCA per work item, material-based carbon factors, EU taxonomy and CSRD alignment.

    344 GitHub stars~664 tokensUpdated 1 mo ago
    Auto-check passed
  • Material Passports Circular

    datadrivenconstruction/DDC_Skills_for_AI_Agents_in_Construction

    Material passports and circular construction: generate per-element material inventories from BOQ/BIM, mark reuse potential and recycled content, and prepare deconstruction data.

    344 GitHub stars~634 tokensUpdated 1 mo ago
    Auto-check passed
  • Oce Cost Browser

    datadrivenconstruction/DDC_Skills_for_AI_Agents_in_Construction

    Browse and search the OpenConstructionERP cost database: classification tree, SQL and semantic search, autocomplete, certainty badges, and the resource catalog.

    344 GitHub stars~637 tokensUpdated 1 mo ago
    Auto-check passed
  • Oce Estimate Boq

    datadrivenconstruction/DDC_Skills_for_AI_Agents_in_Construction

    Create bills of quantities and estimates in OpenConstructionERP: search cost items, build BOQ sections, link BIM elements in bulk, validate the BOQ, and export GAEB/XLSX/JSON.

    344 GitHub stars~763 tokensUpdated 1 mo ago
    Auto-check passed
  • Oce Field Ops

    datadrivenconstruction/DDC_Skills_for_AI_Agents_in_Construction

    Field operations in OpenConstructionERP: punch list, daily diary, HSE observations and task tracking on site.

    344 GitHub stars~532 tokensUpdated 1 mo ago
    Auto-check passed

Questions about Digital Twin Sync

What does Digital Twin Sync do?

Synchronize construction digital twins with real-time data. An agent skill from datadrivenconstruction/DDC_Skills_for_AI_Agents_in_Construction. Digital Twin Sync is an agent skill from datadrivenconstruction/DDC_Skills_for_AI_Agents_in_Construction. Synchronize construction digital twins with real-time data.

How do I install Digital Twin Sync in Claude Code?

Run `npx skills add datadrivenconstruction/DDC_Skills_for_AI_Agents_in_Construction --skill digital-twin-sync -a claude-code`. Or copy the skill folder (5_DDC_Innovative/digital-twin-sync in datadrivenconstruction/DDC_Skills_for_AI_Agents_in_Construction) into .claude/skills/digital-twin-sync in your project. Claude Code loads it when a task matches its description.

How do I install Digital Twin Sync in Codex?

Run `npx skills add datadrivenconstruction/DDC_Skills_for_AI_Agents_in_Construction --skill digital-twin-sync -a codex`. Or copy the skill folder (5_DDC_Innovative/digital-twin-sync in datadrivenconstruction/DDC_Skills_for_AI_Agents_in_Construction) into .agents/skills/digital-twin-sync in your project. Codex loads it when a task matches its description.

Can I use Digital Twin Sync in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add datadrivenconstruction/DDC_Skills_for_AI_Agents_in_Construction --skill digital-twin-sync -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/digital-twin-sync, .gemini/skills/digital-twin-sync, .github/skills/digital-twin-sync and .opencode/skills/digital-twin-sync in your project.

What does Digital Twin Sync need to run?

SKILL.md names no scripts, command-line tools or credentials: Digital Twin Sync is instructions for the agent only. Our summary lists: Python 3.

Does Digital Twin Sync access the network?

SKILL.md names 3 domains. As links in the text: digitaltwinconsortium.org, buildingsmart.org and datadrivenconstruction.io. This is read from the text; nothing was executed.

Is Digital Twin Sync safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.

What licence does Digital Twin Sync use?

Digital Twin Sync is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Digital Twin Sync use?

About 6.3k tokens (SKILL.md is roughly 25k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to Digital Twin Sync?

Skills that share tags, products or a category with Digital Twin Sync: Connect (ComposioHQ/awesome-claude-skills, 77k stars), Claude-Mem Cloud Sync (thedotmack/claude-mem, 98k stars), Node Connect (openclaw/openclaw, 392k stars) and Digital Forensics (sickn33/agentic-awesome-skills, 47k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Digital Twin Sync?

datadrivenconstruction (a GitHub user) maintains it in datadrivenconstruction/DDC_Skills_for_AI_Agents_in_Construction, which has 344 GitHub stars. The repository holds 43 skills in this directory. The repository was last updated on August 22, 2026.

Source: datadrivenconstruction/DDC_Skills_for_AI_Agents_in_Construction on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.