# Bidflow Electrical Estimator

> From a plain-English project scope and a price list CSV, produce a structured line-item electrical estimate with material costs, labor hours, markup, and a grand total in valid JSON.

- Skill: `riteshkew/bidflow-electrical-estimator` (Agent Skill, multi-file: 6 files)
- Install (CLI): `npx skillmds@latest add riteshkew/bidflow-electrical-estimator`
- Raw SKILL.md: https://api.skillmd.com/api/skills/riteshkew/bidflow-electrical-estimator/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Data & Analytics
- Author: riteshkew (https://skillmd.com/u/riteshkew)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/riteshkew/bidflow-electrical-estimator

---


# Workflow

When this skill triggers, follow these steps in order.

## Step 1 — Parse the scope into quantities

Read the project description carefully and extract a quantity takeoff table:

| Item | Quantity | Unit |
|------|----------|------|
| Receptacles | N | each |
| Switches | N | each |
| Fixtures | N | each |
| Conduit | N | linear ft |
| Panel(s) | N | each |
| Breakers | N | each |
| Boxes | N | each |
| Cable / wire | N | ft or rolls |
| Consumables | N | packs |

Rules for this step:
- Convert linear footage to conduit sticks (divide by 10 for 10ft sticks, round up).
- Derive outlet box count from device + fixture count (one box per device/fixture).
- Note the stated labor rate and markup percentage from the scope; use defaults ($85/hr, 15% markup) if not provided.
- Flag any scope items that have no matching SKU in the price list — list them as `"sku": "UNLISTED"` with `unit_cost: 0` and a note.

## Step 2 — Match each quantity to a SKU in the price list

Load `resources/prices.csv`. For each takeoff item:

1. Search for the best-matching row by description keywords (wire gauge, device type, conduit size, amperage).
2. Record the matched `sku`, `unit`, `unit_cost`, and `labor_hours` (per-unit labor from the price list).
3. If multiple SKUs could match, prefer the one whose unit matches the takeoff unit exactly.
4. If no SKU matches, record `sku: UNLISTED` and set both `unit_cost` and `labor_hours` to 0 so arithmetic is not corrupted.

## Step 3 — Compute material, labor, and line totals

For each line item, compute:

```
material_total  = qty * unit_cost                        (round to 2 decimal places)
labor_hours     = qty * labor_hours_per_unit_from_csv    (round to 2 decimal places)
labor_total     = labor_hours * labor_rate_per_hour      (round to 2 decimal places)
line_total      = material_total + labor_total           (round to 2 decimal places)
```

Then roll up totals:

```
totals.material  = sum of all material_total values
totals.labor     = sum of all labor_total values
totals.subtotal  = totals.material + totals.labor
totals.markup    = totals.subtotal * (markup_pct / 100)
totals.grand_total = totals.subtotal + totals.markup
```

Round every totals field to 2 decimal places. Double-check: sum the line_total column independently and confirm it equals subtotal before emitting output.

## Step 4 — Emit the JSON estimate

Output a single valid JSON document with this schema:

```json
{
  "project": "<short project description>",
  "assumptions": {
    "labor_rate_per_hour": <number>,
    "markup_pct": <number>,
    "notes": ["<any scope flags or UNLISTED items>"]
  },
  "line_items": [
    {
      "sku": "<sku>",
      "description": "<description>",
      "qty": <number>,
      "unit": "<unit>",
      "unit_cost": <number>,
      "material_total": <number>,
      "labor_hours": <number>,
      "labor_total": <number>,
      "line_total": <number>
    }
  ],
  "totals": {
    "material": <number>,
    "labor": <number>,
    "subtotal": <number>,
    "markup": <number>,
    "grand_total": <number>
  }
}
```

The output must be pure JSON — no markdown fences, no commentary outside the JSON object. Every number must be a JSON number (not a quoted string). The document must pass `JSON.parse` without error.

## Productionization gap

This skill uses the sample price list in `resources/prices.csv`. Real production use requires:

- **Live supplier pricing**: integration with distributor APIs (e.g., Graybar, Anixter, Rexel) or a regularly refreshed price feed.
- **True takeoff from plans**: PDF/DXF plan parsing to auto-extract quantities instead of relying on a plain-English scope description.
- **Regional labor rates**: NECA or Davis-Bacon wage tables by zip code rather than a single flat rate.
- **Tax and fee tables**: jurisdiction-specific sales tax on materials and permit fee schedules.

## Example

Input: `examples/input.md` — 1,200 sq ft office TI scope with 18 receptacles, 12 LED troffers, 1 new 100A subpanel, ~400 ft of 1/2 in EMT, 6 switches.

Output: `examples/output.md` — valid JSON estimate with 18 line items, internally consistent arithmetic, $85/hr labor rate, 15% markup, grand total $7,895.10.

