daily-report-generator
Automatically generate daily construction reports from field data, worker inputs, weather, and progress photos. Creates professional PDF reports.
Install / Use
npx skills add datadrivenconstruction/DDC_Skills_for_AI_Agents_in_Construction --skill daily-report-generatorInstalls into whichever agent you are using.
SKILL.md
Installable skill definition
Quality Score
Category
AutomationSupported Platforms
Our assessment of daily-report-generator
daily-report-generator scores 91/100 on our quality scale, 1190th of 2,904 Automation skills we index (top 41%).
Its SKILL.md is 20 KB long, well organised into 13 sections with 6 code examples: a thorough specification that gives an agent plenty to work with.
It has 333 GitHub stars, a meaningful sign that others use it.
Maintenance, license and trust
- The repository was last updated about 2 months ago, so daily-report-generator is actively maintained.
- It is released under the MIT license, a permissive license that allows use, modification and commercial use with attribution.
- Its trust signals score 100/100, with no cautions. These come from repository metadata, not a code audit — read the skill file before letting an agent act on it.
daily-report-generator compared with similar skills
All 4 of these similar skills score higher than daily-report-generator; compare them before choosing.
| Skill | Score | Stars | Updated | Format |
|---|---|---|---|---|
| daily-report-generator (this skill)by datadrivenconstruction | 91 | 333 | 56d ago | SKILL.md |
| Agent-Reachby Panniantong | 100 | 98.3k | 2d ago | CLAUDE.md |
| headroomby headroomlabs-ai | 100 | 75.5k | today | CLAUDE.md |
| Scraplingby D4Vinci | 100 | 88.2k | today | MCP Server |
| crawl4aiby unclecode | 100 | 85.7k | 2d ago | MCP Server |
Frequently asked questions
- How do I install daily-report-generator?
- Run
npx skills add datadrivenconstruction/DDC_Skills_for_AI_Agents_in_Construction --skill daily-report-generator. The install tabs above show the steps for each supported agent. - Which AI agents does daily-report-generator work with?
- It is written for Universal, as a SKILL.md file. Other agents that read the same format can often use it too.
- Is daily-report-generator safe to use?
- It is MIT-licensed and scores 100/100 on trust signals. Skills are instructions an agent will follow, so read the file before installing it and do not approve commands you do not understand.
- Is daily-report-generator still maintained?
- The repository was last updated about 2 months ago, so daily-report-generator is actively maintained.
Skill content
View source on GitHubname: "daily-report-generator" description: "Automatically generate daily construction reports from field data, worker inputs, weather, and progress photos. Creates professional PDF reports." homepage: "https://datadrivenconstruction.io" metadata: {"openclaw": {"emoji": "🏗️", "os": ["darwin", "linux", "win32"], "homepage": "https://datadrivenconstruction.io", "requires": {"bins": ["python3"]}}}
Daily Report Generator for Construction Sites
Automate the creation of comprehensive daily construction reports by aggregating data from multiple sources into professional documentation.
Business Case
Problem: Site managers spend 45-60 minutes daily on:
- Collecting information from foremen
- Checking weather conditions
- Compiling worker counts and hours
- Writing narrative summaries
- Formatting and distributing reports
Solution: Automated system that:
- Pulls data from Google Sheets/project database
- Integrates weather API data
- Aggregates worker timesheets
- Generates professional PDF reports
- Distributes to stakeholders automatically
ROI: 80% reduction in daily reporting time (45 min → 9 min for review)
Report Structure
┌──────────────────────────────────────────────────────────────────────┐
│ DAILY CONSTRUCTION REPORT │
│ │
│ Project: ЖК Солнечный, Корпус 2 Date: 24.01.2026 │
│ Report #: DCR-2026-024 Weather: ☁️ -5°C │
├──────────────────────────────────────────────────────────────────────┤
│ │
│ 1. WEATHER CONDITIONS │
│ ┌────────────┬────────────┬────────────┬────────────┐ │
│ │ Morning │ Afternoon │ Evening │ Impact │ │
│ │ -8°C ☀️ │ -5°C ☁️ │ -7°C 🌙 │ Normal │ │
│ └────────────┴────────────┴────────────┴────────────┘ │
│ │
│ 2. WORKFORCE │
│ ┌────────────────────────────────────────────────────┐ │
│ │ Category │ Planned │ Actual │ Hours │ │
│ ├────────────────────────────────────────────────────┤ │
│ │ GC Supervision │ 3 │ 3 │ 27 │ │
│ │ Electrical │ 12 │ 11 │ 88 │ │
│ │ Plumbing │ 8 │ 8 │ 64 │ │
│ │ HVAC │ 6 │ 6 │ 48 │ │
│ │ TOTAL │ 29 │ 28 │ 227 │ │
│ └────────────────────────────────────────────────────┘ │
│ │
│ 3. WORK COMPLETED TODAY │
│ • Electrical: Completed rough-in floors 5-6 │
│ • Plumbing: Installed risers section A │
│ • HVAC: Ductwork installation 60% complete │
│ │
│ 4. WORK PLANNED FOR TOMORROW │
│ • Electrical: Begin rough-in floor 7 │
│ • Plumbing: Continue risers section B │
│ • HVAC: Complete ductwork, begin testing │
│ │
│ 5. ISSUES / DELAYS │
│ • Material delay: Electrical panels (ETA: 26.01) │
│ • Weather: Expected snow may delay exterior work │
│ │
│ 6. SAFETY │
│ ✅ No incidents │
│ ✅ Toolbox talk completed: Fall protection │
│ │
│ 7. PHOTOS │
│ [Photo 1: Floor 5 electrical] [Photo 2: Riser installation] │
│ │
│ ───────────────────────────────────────────────────────────────── │
│ Prepared by: Иван Петров, Site Manager │
│ Approved by: ___________________ │
│ Distribution: Owner, Architect, PM │
└──────────────────────────────────────────────────────────────────────┘
Python Implementation
import pandas as pd
from datetime import datetime, date
from typing import Optional, List, Dict
import requests
from reportlab.lib import colors
from reportlab.lib.pagesizes import A4
from reportlab.platypus import SimpleDocTemplate, Table, TableStyle, Paragraph, Spacer, Image
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.units import cm
import os
class DailyReportGenerator:
"""Generate professional daily construction reports"""
def __init__(self, config: dict):
self.config = config
self.weather_api_key = config.get('weather_api_key')
self.project_name = config.get('project_name')
self.report_date = config.get('report_date', date.today())
def get_weather_data(self, location: str) -> dict:
"""Fetch weather data from API"""
if not self.weather_api_key:
return self._mock_weather()
url = f"https://api.openweathermap.org/data/2.5/weather"
params = {
'q': location,
'appid': self.weather_api_key,
'units': 'metric',
'lang': 'ru'
}
response = requests.get(url, params=params)
if response.status_code == 200:
data = response.json()
return {
'temp': round(data['main']['temp']),
'description': data['weather'][0]['description'],
'humidity': data['main']['humidity'],
'wind_speed': round(data['wind']['speed']),
'icon': self._get_weather_icon(data['weather'][0]['main'])
}
return self._mock_weather()
def _get_weather_icon(self, condition: str) -> str:
icons = {
'Clear': '☀️',
'Clouds': '☁️',
'Rain': '🌧️',
'Snow': '❄️',
'Thunderstorm': '⛈️',
'Mist': '🌫️'
}
return icons.get(condition, '🌤️')
def _mock_weather(self) -> dict:
return {
'temp': -5,
'description': 'облачно',
'humidity': 65,
'wind_speed': 3,
'icon': '☁️'
}
def get_workforce_data(self, source: pd.DataFrame) -> dict:
"""Aggregate workforce data from timesheet"""
# Expected columns: trade, worker_name, hours_worked, planned_hours
summary = source.groupby('trade').agg({
'worker_name': 'count',
'hours_worked': 'sum',
'planned_hours': 'sum'
}).reset_index()
summary.columns = ['trade', 'actual_count', 'actual_hours', 'planned_hours']
# Calculate planned count (assuming 8-hour shifts)
summary['planned_count'] = (summary['planned_hours'] / 8).astype(int)
return {
'trades': summary.to_dict('records'),
'total_workers': summary['actual_count'].sum(),
'total_hours': summary['actual_hours'].sum(),
'total_planned': summary['planned_count'].sum()
}
def get_work_completed(self, tasks: pd.DataFrame) -> List[dict]:
"""Extract completed work from task system"""
# Filter completed tasks for today
completed = tasks[
(tasks['date'] == self.report_date.strftime('%d.%m.%Y')) &
(tasks['status'].isin(['Completed', 'Partial']))
]
work_items = []
for _, row in completed.iterrows():
work_items.append({
'trade': row['trade'],
'description': row['description'],
'status': row['status'],
'notes': row.get('notes', '')
})
return work_items
def get_work_planned(self, tasks: pd.DataFrame) -> List[dict]:
"""Get planned work for tomorrow"""
tomorrow = self.report_date + pd.Timedelta(days=1)
planned = tasks[
tasks['date'] == tomorrow.strftime('%d.%m.%Y')
]
work_items = []
for _, row in planned.iterrows():
work_items.append({
'trade': row['trade'],
'description': row['description'],
'priority': row.get('priority', 'Medium')
})
return work_items
def get_issues(self, issues_log: pd.DataFrame) -> List[dict]:
"""Get active issues and delays"""
active = issues_log[
(issues_log['status'] == 'Open') |
(issues_log['date_reported'] == self.report_date.strftime('%d.%m.%Y'))
]
return active[['category', 'description', 'impact', 'resolution_date']].to_dict('records')
def get_safety_data(self, safety_log: pd.DataFrame) -> dict:
"""Get safety information for the day"""
today_incidents = safety_log[
safety_log['date'] == self.report_date.strftime('%d.%m.%Y')
]
return {
'incidents': len(today_incidents[today_incidents['type'] == 'Incident']),
'near_misses': len(today_incidents[today_incidents['type'] == 'Near Miss']),
'toolbox_talk': today_incidents[
today_incidents['type'] == 'Toolbox Talk'
]['topic'].tolist(),
'observations': today_incidents[
today_incidents['type'] == 'Observation'
]['description'].tolist()
}
def generate_report(self, data: dict, output_path: str) -> str:
"""Generate PDF report"""
doc = SimpleDocTemplate(
output_path,
pagesize=A4,
rightMargin=2*cm,
leftMargin=2*cm,
topMargin=2*cm,
bottomMargin=2*cm
)
styles = getSampleStyleSheet()
title_style = ParagraphStyle(
'Title',
parent=styles['Heading1'],
fontSize=16,
alignment=1,
spaceAfter=12
)
heading_style = ParagraphStyle(
'Heading',
parent=styles['Heading2'],
fontSize=12,
spaceBefore=12,
spaceAfter=6
)
elements = []
# Title
elements.append(Paragraph(
f"DAILY CONSTRUCTION REPORT",
title_style
))
# Header info
header_data = [
['Project:', self.project_name, 'Date:', self.report_date.strftime('%d.%m.%Y')],
['Report #:', data.get('report_number', 'DCR-001'), 'Weather:', f"{data['weather']['icon']} {data['weather']['temp']}°C"]
]
header_table = Table(header_data, colWidths=[3*cm, 6*cm, 3*cm, 4*cm])
header_table.setStyle(TableStyle([
('FONTNAME', (0, 0), (-1, -1), 'Helvetica'),
('FONTSIZE', (0, 0), (-1, -1), 10),
('FONTNAME', (0, 0), (0, -1), 'Helvetica-Bold'),
('FONTNAME', (2, 0), (2, -1), 'Helvetica-Bold'),
]))
elements.append(header_table)
elements.append(Spacer(1, 12))
# Weather section
elements.append(Paragraph("1. WEATHER CONDITIONS", heading_style))
weather = data['weather']
weather_text = f"""
Temperature: {weather['temp']}°C | Humidity: {weat
Truncated for display — read the full file on GitHub.
Related Skills
Agent-Reach
98.3kGive your AI agent eyes to see the entire internet. Read & search Twitter, Reddit, YouTube, GitHub, Bilibili, XiaoHongShu — one CLI, zero API fees.
headroom
75.5kCompress tool outputs, logs, files, and RAG chunks before they reach the LLM. 20% fewer tokens for coding agents, 60-95% fewer tokens for JSON, same answers. Library, proxy, MCP server.
Scrapling
88.2k🕷️ An adaptive Web Scraping framework that handles everything from a single request to a full-scale crawl! Don't be shy, join here: https://discord.gg/EMgGbDceNQ and follow here for daily tips and tricks: https://x.com/Scrapling_dev
crawl4ai
85.7kOpen-source web crawler and scraper for LLMs and AI agents: any website into clean, LLM-ready Markdown. Run it yourself, or use Crawl4AI Cloud with one key.
Languages
Trust signals
From repository metadata: license, adoption, age and documentation. Not a code audit — see the Safety scan above for what the skill file itself contains.
