← Back to Skills Marketplace
datadrivenconstruction

Lifecycle Carbon Calculator

cross-platform ⚠ suspicious
722
Downloads
0
Stars
1
Active Installs
1
Versions
Install in OpenClaw
/install lifecycle-carbon-calculator
Description
Calculate embodied carbon and lifecycle emissions for construction materials and projects. Support sustainable design decisions with carbon data.
README (SKILL.md)

\r \r

Lifecycle Carbon Calculator for Construction\r

\r

Overview\r

\r Calculate embodied carbon (EC) and lifecycle carbon emissions for construction materials, assemblies, and projects. Support sustainable design decisions and carbon reduction targets.\r \r

Business Case\r

\r Carbon calculation supports:\r

  • Regulatory Compliance: Meet carbon reporting requirements\r
  • Green Certifications: LEED, BREEAM, Living Building Challenge\r
  • Design Optimization: Choose lower-carbon alternatives\r
  • Sustainability Goals: Track progress toward net-zero\r \r

Technical Implementation\r

\r

from dataclasses import dataclass, field\r
from typing import List, Dict, Any, Optional\r
from enum import Enum\r
import pandas as pd\r
\r
class LifecycleStage(Enum):\r
    A1_A3 = "Product Stage (A1-A3)"  # Raw materials, transport, manufacturing\r
    A4 = "Transport to Site (A4)"\r
    A5 = "Construction (A5)"\r
    B1_B7 = "Use Stage (B1-B7)"  # Maintenance, repair, replacement\r
    C1_C4 = "End of Life (C1-C4)"  # Demolition, transport, disposal\r
    D = "Beyond Lifecycle (D)"  # Reuse, recycling potential\r
\r
@dataclass\r
class MaterialCarbon:\r
    material_id: str\r
    name: str\r
    category: str\r
    unit: str\r
    carbon_a1_a3: float  # kgCO2e per unit\r
    carbon_a4: float\r
    carbon_a5: float\r
    carbon_b: float\r
    carbon_c: float\r
    carbon_d: float  # Usually negative (credit)\r
    density: float  # kg/m³ if applicable\r
    source: str\r
    epd_url: str = ""\r
\r
@dataclass\r
class AssemblyCarbon:\r
    assembly_id: str\r
    name: str\r
    materials: List[Dict[str, Any]]\r
    total_carbon: float\r
    carbon_by_stage: Dict[str, float]\r
\r
@dataclass\r
class ProjectCarbon:\r
    project_id: str\r
    name: str\r
    gross_area: float\r
    assemblies: List[AssemblyCarbon]\r
    total_embodied_carbon: float\r
    carbon_per_area: float\r
    carbon_by_stage: Dict[str, float]\r
    carbon_by_category: Dict[str, float]\r
    benchmark_comparison: Dict[str, Any]\r
\r
class LifecycleCarbonCalculator:\r
    """Calculate lifecycle carbon for construction."""\r
\r
    # Sample material carbon data (kgCO2e per unit)\r
    DEFAULT_MATERIALS = {\r
        'concrete_30mpa': MaterialCarbon(\r
            material_id='C30', name='Concrete 30MPa', category='Concrete',\r
            unit='m³', carbon_a1_a3=300, carbon_a4=5, carbon_a5=2,\r
            carbon_b=0, carbon_c=10, carbon_d=-20, density=2400,\r
            source='EPD Database'\r
        ),\r
        'concrete_40mpa': MaterialCarbon(\r
            material_id='C40', name='Concrete 40MPa', category='Concrete',\r
            unit='m³', carbon_a1_a3=350, carbon_a4=5, carbon_a5=2,\r
            carbon_b=0, carbon_c=10, carbon_d=-20, density=2400,\r
            source='EPD Database'\r
        ),\r
        'steel_rebar': MaterialCarbon(\r
            material_id='REBAR', name='Steel Reinforcing Bar', category='Steel',\r
            unit='kg', carbon_a1_a3=1.99, carbon_a4=0.05, carbon_a5=0.02,\r
            carbon_b=0, carbon_c=0.05, carbon_d=-0.5, density=7850,\r
            source='WorldSteel EPD'\r
        ),\r
        'steel_structural': MaterialCarbon(\r
            material_id='STEEL', name='Structural Steel', category='Steel',\r
            unit='kg', carbon_a1_a3=1.55, carbon_a4=0.05, carbon_a5=0.03,\r
            carbon_b=0, carbon_c=0.05, carbon_d=-0.8, density=7850,\r
            source='AISC EPD'\r
        ),\r
        'timber_clt': MaterialCarbon(\r
            material_id='CLT', name='Cross-Laminated Timber', category='Timber',\r
            unit='m³', carbon_a1_a3=-500, carbon_a4=10, carbon_a5=5,\r
            carbon_b=0, carbon_c=50, carbon_d=-100, density=500,\r
            source='AWC EPD'\r
        ),\r
        'gypsum_board': MaterialCarbon(\r
            material_id='GYP', name='Gypsum Board 12.5mm', category='Finishes',\r
            unit='m²', carbon_a1_a3=3.2, carbon_a4=0.2, carbon_a5=0.1,\r
            carbon_b=0, carbon_c=0.3, carbon_d=-0.1, density=10,\r
            source='EUROGYPSUM EPD'\r
        ),\r
        'insulation_mineral': MaterialCarbon(\r
            material_id='INS_MW', name='Mineral Wool Insulation', category='Insulation',\r
            unit='m³', carbon_a1_a3=45, carbon_a4=2, carbon_a5=1,\r
            carbon_b=0, carbon_c=5, carbon_d=-2, density=40,\r
            source='EURIMA EPD'\r
        ),\r
        'glass_double': MaterialCarbon(\r
            material_id='GLASS', name='Double Glazed Unit', category='Glazing',\r
            unit='m²', carbon_a1_a3=35, carbon_a4=1, carbon_a5=0.5,\r
            carbon_b=0, carbon_c=2, carbon_d=-5, density=25,\r
            source='Glass for Europe EPD'\r
        ),\r
        'aluminum': MaterialCarbon(\r
            material_id='ALU', name='Aluminum Profile', category='Metals',\r
            unit='kg', carbon_a1_a3=8.0, carbon_a4=0.1, carbon_a5=0.05,\r
            carbon_b=0, carbon_c=0.1, carbon_d=-4.0, density=2700,\r
            source='EAA EPD'\r
        ),\r
    }\r
\r
    # Building type benchmarks (kgCO2e/m²)\r
    BENCHMARKS = {\r
        'Office': {'typical': 500, 'good': 350, 'best': 200},\r
        'Residential': {'typical': 400, 'good': 280, 'best': 150},\r
        'Retail': {'typical': 450, 'good': 320, 'best': 180},\r
        'Industrial': {'typical': 350, 'good': 250, 'best': 150},\r
        'Healthcare': {'typical': 700, 'good': 500, 'best': 350},\r
    }\r
\r
    def __init__(self):\r
        self.materials: Dict[str, MaterialCarbon] = dict(self.DEFAULT_MATERIALS)\r
        self.assemblies: Dict[str, AssemblyCarbon] = {}\r
\r
    def add_material(self, material: MaterialCarbon):\r
        """Add or update a material."""\r
        self.materials[material.material_id] = material\r
\r
    def calculate_material_carbon(self, material_id: str, quantity: float,\r
                                   stages: List[LifecycleStage] = None) -> Dict:\r
        """Calculate carbon for a material quantity."""\r
        if material_id not in self.materials:\r
            raise ValueError(f"Unknown material: {material_id}")\r
\r
        material = self.materials[material_id]\r
\r
        if stages is None:\r
            stages = list(LifecycleStage)\r
\r
        carbon_by_stage = {}\r
        total = 0\r
\r
        for stage in stages:\r
            if stage == LifecycleStage.A1_A3:\r
                carbon = material.carbon_a1_a3 * quantity\r
            elif stage == LifecycleStage.A4:\r
                carbon = material.carbon_a4 * quantity\r
            elif stage == LifecycleStage.A5:\r
                carbon = material.carbon_a5 * quantity\r
            elif stage == LifecycleStage.B1_B7:\r
                carbon = material.carbon_b * quantity\r
            elif stage == LifecycleStage.C1_C4:\r
                carbon = material.carbon_c * quantity\r
            elif stage == LifecycleStage.D:\r
                carbon = material.carbon_d * quantity\r
            else:\r
                carbon = 0\r
\r
            carbon_by_stage[stage.value] = carbon\r
            total += carbon\r
\r
        return {\r
            'material_id': material_id,\r
            'material_name': material.name,\r
            'quantity': quantity,\r
            'unit': material.unit,\r
            'total_carbon': total,\r
            'carbon_by_stage': carbon_by_stage\r
        }\r
\r
    def create_assembly(self, assembly_id: str, name: str,\r
                        components: List[Dict]) -> AssemblyCarbon:\r
        """Create an assembly from multiple materials."""\r
        total_carbon = 0\r
        carbon_by_stage = {stage.value: 0 for stage in LifecycleStage}\r
        material_details = []\r
\r
        for comp in components:\r
            material_id = comp['material_id']\r
            quantity = comp['quantity']\r
\r
            result = self.calculate_material_carbon(material_id, quantity)\r
            total_carbon += result['total_carbon']\r
\r
            for stage, carbon in result['carbon_by_stage'].items():\r
                carbon_by_stage[stage] += carbon\r
\r
            material_details.append({\r
                'material': result['material_name'],\r
                'quantity': quantity,\r
                'unit': result['unit'],\r
                'carbon': result['total_carbon']\r
            })\r
\r
        assembly = AssemblyCarbon(\r
            assembly_id=assembly_id,\r
            name=name,\r
            materials=material_details,\r
            total_carbon=total_carbon,\r
            carbon_by_stage=carbon_by_stage\r
        )\r
\r
        self.assemblies[assembly_id] = assembly\r
        return assembly\r
\r
    def calculate_project_carbon(self, project_id: str, project_name: str,\r
                                  gross_area: float, building_type: str,\r
                                  quantities: List[Dict]) -> ProjectCarbon:\r
        """Calculate total project carbon."""\r
        assemblies = []\r
        total_carbon = 0\r
        carbon_by_stage = {stage.value: 0 for stage in LifecycleStage}\r
        carbon_by_category = {}\r
\r
        for qty in quantities:\r
            if 'assembly_id' in qty:\r
                # Use predefined assembly\r
                if qty['assembly_id'] in self.assemblies:\r
                    assembly = self.assemblies[qty['assembly_id']]\r
                    multiplier = qty.get('multiplier', 1)\r
                    scaled_carbon = assembly.total_carbon * multiplier\r
\r
                    assemblies.append(AssemblyCarbon(\r
                        assembly_id=assembly.assembly_id,\r
                        name=assembly.name,\r
                        materials=assembly.materials,\r
                        total_carbon=scaled_carbon,\r
                        carbon_by_stage={k: v * multiplier for k, v in assembly.carbon_by_stage.items()}\r
                    ))\r
                    total_carbon += scaled_carbon\r
\r
            elif 'material_id' in qty:\r
                # Direct material\r
                result = self.calculate_material_carbon(\r
                    qty['material_id'], qty['quantity']\r
                )\r
                total_carbon += result['total_carbon']\r
\r
                for stage, carbon in result['carbon_by_stage'].items():\r
                    carbon_by_stage[stage] += carbon\r
\r
                # Track by category\r
                material = self.materials[qty['material_id']]\r
                cat = material.category\r
                carbon_by_category[cat] = carbon_by_category.get(cat, 0) + result['total_carbon']\r
\r
        # Calculate metrics\r
        carbon_per_area = total_carbon / gross_area if gross_area > 0 else 0\r
\r
        # Compare to benchmarks\r
        benchmark = self.BENCHMARKS.get(building_type, self.BENCHMARKS['Office'])\r
        benchmark_comparison = {\r
            'carbon_per_area': carbon_per_area,\r
            'typical_benchmark': benchmark['typical'],\r
            'good_benchmark': benchmark['good'],\r
            'best_benchmark': benchmark['best'],\r
            'vs_typical': (carbon_per_area / benchmark['typical'] - 1) * 100,\r
            'rating': self._get_rating(carbon_per_area, benchmark)\r
        }\r
\r
        return ProjectCarbon(\r
            project_id=project_id,\r
            name=project_name,\r
            gross_area=gross_area,\r
            assemblies=assemblies,\r
            total_embodied_carbon=total_carbon,\r
            carbon_per_area=carbon_per_area,\r
            carbon_by_stage=carbon_by_stage,\r
            carbon_by_category=carbon_by_category,\r
            benchmark_comparison=benchmark_comparison\r
        )\r
\r
    def _get_rating(self, carbon: float, benchmark: Dict) -> str:\r
        """Get rating based on benchmark comparison."""\r
        if carbon \x3C= benchmark['best']:\r
            return 'A (Best Practice)'\r
        elif carbon \x3C= benchmark['good']:\r
            return 'B (Good Practice)'\r
        elif carbon \x3C= benchmark['typical']:\r
            return 'C (Typical)'\r
        else:\r
            return 'D (Above Typical)'\r
\r
    def compare_alternatives(self, base_project: ProjectCarbon,\r
                              alternatives: List[Dict]) -> pd.DataFrame:\r
        """Compare carbon of design alternatives."""\r
        comparisons = [{\r
            'Option': 'Base Design',\r
            'Total Carbon (tCO2e)': base_project.total_embodied_carbon / 1000,\r
            'Carbon/m² (kgCO2e)': base_project.carbon_per_area,\r
            'vs Base': '0%',\r
            'Rating': base_project.benchmark_comparison['rating']\r
        }]\r
\r
        for alt in alternatives:\r
            project = self.calculate_project_carbon(\r
                alt['id'], alt['name'], alt['gross_area'],\r
                alt.get('building_type', 'Office'), alt['quantities']\r
            )\r
\r
            change = (project.total_embodied_carbon - base_project.total_embodied_carbon) / base_project.total_embodied_carbon * 100\r
\r
            comparisons.append({\r
                'Option': alt['name'],\r
                'Total Carbon (tCO2e)': project.total_embodied_carbon / 1000,\r
                'Carbon/m² (kgCO2e)': project.carbon_per_area,\r
                'vs Base': f'{change:+.1f}%',\r
                'Rating': project.benchmark_comparison['rating']\r
            })\r
\r
        return pd.DataFrame(comparisons)\r
\r
    def suggest_reductions(self, project: ProjectCarbon) -> List[Dict]:\r
        """Suggest carbon reduction opportunities."""\r
        suggestions = []\r
\r
        # Analyze by category\r
        if 'Concrete' in project.carbon_by_category:\r
            concrete_carbon = project.carbon_by_category['Concrete']\r
            if concrete_carbon > project.total_embodied_carbon * 0.3:\r
                suggestions.append({\r
                    'category': 'Concrete',\r
                    'current_carbon': concrete_carbon,\r
                    'suggestion': 'Consider low-carbon concrete (GGBS/PFA replacement)',\r
                    'potential_reduction': '20-40%',\r
                    'impact': concrete_carbon * 0.3\r
                })\r
\r
        if 'Steel' in project.carbon_by_category:\r
            steel_carbon = project.carbon_by_category['Steel']\r
            if steel_carbon > project.total_embodied_carbon * 0.2:\r
                suggestions.append({\r
                    'category': 'Steel',\r
                    'current_carbon': steel_carbon,\r
                    'suggestion': 'Specify high recycled content steel',\r
                    'potential_reduction': '10-25%',\r
                    'impact': steel_carbon * 0.2\r
                })\r
\r
        # Benchmark-based suggestions\r
        if project.benchmark_comparison['vs_typical'] > 0:\r
            suggestions.append({\r
                'category': 'Overall',\r
                'current_carbon': project.total_embodied_carbon,\r
                'suggestion': 'Project exceeds typical benchmark - review high-carbon elements',\r
                'potential_reduction': f"{abs(project.benchmark_comparison['vs_typical']):.0f}%",\r
                'impact': project.total_embodied_carbon * abs(project.benchmark_comparison['vs_typical']) / 100\r
            })\r
\r
        return sorted(suggestions, key=lambda x: -x['impact'])\r
\r
    def generate_report(self, project: ProjectCarbon) -> str:\r
        """Generate carbon assessment report."""\r
        lines = ["# Embodied Carbon Assessment Report", ""]\r
        lines.append(f"**Project:** {project.name}")\r
        lines.append(f"**Gross Area:** {project.gross_area:,.0f} m²")\r
        lines.append(f"**Assessment Date:** {pd.Timestamp.now().strftime('%Y-%m-%d')}")\r
        lines.append("")\r
\r
        # Summary\r
        lines.append("## Carbon Summary")\r
        lines.append(f"- **Total Embodied Carbon:** {project.total_embodied_carbon/1000:,.0f} tCO2e")\r
        lines.append(f"- **Carbon Intensity:** {project.carbon_per_area:,.0f} kgCO2e/m²")\r
        lines.append(f"- **Rating:** {project.benchmark_comparison['rating']}")\r
        lines.append("")\r
\r
        # By lifecycle stage\r
        lines.append("## Carbon by Lifecycle Stage")\r
        for stage, carbon in project.carbon_by_stage.items():\r
            if carbon != 0:\r
                pct = carbon / project.total_embodied_carbon * 100\r
                lines.append(f"- {stage}: {carbon/1000:,.1f} tCO2e ({pct:.1f}%)")\r
        lines.append("")\r
\r
        # By category\r
        lines.append("## Carbon by Material Category")\r
        for cat, carbon in sorted(project.carbon_by_category.items(), key=lambda x: -x[1]):\r
            pct = carbon / project.total_embodied_carbon * 100\r
            lines.append(f"- {cat}: {carbon/1000:,.1f} tCO2e ({pct:.1f}%)")\r
        lines.append("")\r
\r
        # Benchmark\r
        lines.append("## Benchmark Comparison")\r
        bc = project.benchmark_comparison\r
        lines.append(f"- Project: {bc['carbon_per_area']:.0f} kgCO2e/m²")\r
        lines.append(f"- Typical: {bc['typical_benchmark']} kgCO2e/m²")\r
        lines.append(f"- Good Practice: {bc['good_benchmark']} kgCO2e/m²")\r
        lines.append(f"- Best Practice: {bc['best_benchmark']} kgCO2e/m²")\r
        lines.append("")\r
\r
        # Reduction opportunities\r
        suggestions = self.suggest_reductions(project)\r
        if suggestions:\r
            lines.append("## Reduction Opportunities")\r
            for sug in suggestions[:5]:\r
                lines.append(f"\
### {sug['category']}")\r
                lines.append(f"- **Suggestion:** {sug['suggestion']}")\r
                lines.append(f"- **Potential Reduction:** {sug['potential_reduction']}")\r
                lines.append(f"- **Impact:** {sug['impact']/1000:,.1f} tCO2e")\r
\r
        return "\
".join(lines)\r
```\r
\r
## Quick Start\r
\r
```python\r
# Initialize calculator\r
calc = LifecycleCarbonCalculator()\r
\r
# Calculate project carbon\r
project = calc.calculate_project_carbon(\r
    project_id="PROJ-001",\r
    project_name="Office Building",\r
    gross_area=5000,\r
    building_type="Office",\r
    quantities=[\r
        {'material_id': 'concrete_40mpa', 'quantity': 1500},  # m³\r
        {'material_id': 'steel_rebar', 'quantity': 150000},   # kg\r
        {'material_id': 'steel_structural', 'quantity': 200000},\r
        {'material_id': 'gypsum_board', 'quantity': 8000},    # m²\r
        {'material_id': 'glass_double', 'quantity': 1200},    # m²\r
    ]\r
)\r
\r
print(f"Total Carbon: {project.total_embodied_carbon/1000:,.0f} tCO2e")\r
print(f"Carbon Intensity: {project.carbon_per_area:,.0f} kgCO2e/m²")\r
print(f"Rating: {project.benchmark_comparison['rating']}")\r
\r
# Get reduction suggestions\r
suggestions = calc.suggest_reductions(project)\r
for sug in suggestions:\r
    print(f"- {sug['category']}: {sug['suggestion']}")\r
\r
# Generate full report\r
report = calc.generate_report(project)\r
print(report)\r
```\r
\r
## Dependencies\r
\r
```bash\r
pip install pandas\r
```\r
Usage Guidance
This skill appears to be a legitimate lifecycle-carbon calculator, but the SKILL.md contains runnable Python code (uses pandas and references external EPD URLs) while the package declares no runtime dependencies or install steps. Before installing or enabling it, ask the publisher to: (1) state required runtime dependencies (Python version and libraries such as pandas) or provide an install spec; (2) confirm whether the skill will fetch external EPDs or upload project data to external endpoints (and which endpoints); (3) provide a clear statement about data handling and privacy for any URLs or reporting features. If you decide to try it, run it in a sandboxed environment with no sensitive credentials available, and review the full SKILL.md for any network calls or file reads that could exfiltrate data.
Capability Analysis
Type: OpenClaw Skill Name: lifecycle-carbon-calculator Version: 1.0.0 The OpenClaw AgentSkills bundle 'lifecycle-carbon-calculator' appears benign. The Python code in `SKILL.md` implements a carbon calculation tool using standard libraries like `pandas` for data processing. There are no imports of modules like `os`, `subprocess`, `requests`, or `socket`, nor any direct calls that would enable file system access, network communication, or arbitrary command execution. The markdown instructions are descriptive and do not contain any overt prompt injection attempts against the agent. While the `generate_report` function outputs markdown, which could theoretically be re-interpreted by an agent as new instructions, this is a general vulnerability of agent systems processing their own output, not evidence of malicious intent within this specific skill's code.
Capability Assessment
Purpose & Capability
The name, description, and SKILL.md content consistently describe a lifecycle/embodied-carbon calculator for construction, with sample material datasets, benchmarks, and calculation logic. The requested capability matches the stated purpose.
Instruction Scope
SKILL.md includes substantial Python implementation (classes, calculation methods, sample datasets) that imports pandas and references EPD URLs. The instructions are implementation-level rather than purely conceptual. The file does not explicitly tell the agent how/when to execute code, nor does it declare required runtime environment; running it would require Python and third‑party libraries and could lead to network requests (EPD URLs) if implemented to fetch external data.
Install Mechanism
There is no install spec (lowest-risk form). However, the bundled code expects Python and pandas; the absence of declared dependencies or an install step is an incoherence — the skill assumes runtime capabilities that may not exist on the agent host.
Credentials
The skill declares no required environment variables, credentials, or config paths. The code shown does not request secrets or unrelated system credentials. This is proportionate to the stated purpose.
Persistence & Privilege
always:false and no install hooks are present. The skill does not request persistent agent privileges or modify other skills. Autonomous invocation is allowed (platform default) but is not combined with other high-risk flags.
How to Use
  1. Make sure OpenClaw is installed (local or Docker)
  2. Run the install command in chat: /install lifecycle-carbon-calculator
  3. After installation, invoke the skill by name or use /lifecycle-carbon-calculator
  4. Provide required inputs per the skill's parameter spec and get structured output
Version History
v1.0.0
Initial release of the Lifecycle Carbon Calculator skill. - Calculate embodied and lifecycle carbon emissions for construction materials, assemblies, and projects. - Includes default carbon factors for common construction materials. - Supports calculation by lifecycle stage (A1–A3, A4, A5, B, C, D). - Provides industry benchmark comparisons for various building types. - Designed to aid sustainable design decisions and support compliance with green certifications.
Metadata
Slug lifecycle-carbon-calculator
Version 1.0.0
License
All-time Installs 1
Active Installs 1
Total Versions 1
Frequently Asked Questions

What is Lifecycle Carbon Calculator?

Calculate embodied carbon and lifecycle emissions for construction materials and projects. Support sustainable design decisions with carbon data. It is an AI Agent Skill for Claude Code / OpenClaw, with 722 downloads so far.

How do I install Lifecycle Carbon Calculator?

Run "/install lifecycle-carbon-calculator" in the OpenClaw or Claude Code chat to install it in one step — no extra setup required.

Is Lifecycle Carbon Calculator free?

Yes, Lifecycle Carbon Calculator is completely free (open-source). You can download, install and use it at no cost.

Which platforms does Lifecycle Carbon Calculator support?

Lifecycle Carbon Calculator is cross-platform and runs anywhere OpenClaw / Claude Code is available (cross-platform).

Who created Lifecycle Carbon Calculator?

It is built and maintained by datadrivenconstruction (@datadrivenconstruction); the current version is v1.0.0.

💬 Comments