DEV Community

CARLOS ENRIQUE CASTRO LAZARO
CARLOS ENRIQUE CASTRO LAZARO

Posted on

green-linter: Your Project's Carbon Footprint in One Command

DEV Weekend Challenge: Earth Day

This is a submission for Weekend Challenge: Earth Day Edition

What I Built

green-linter is a zero-dependency CLI tool that scans your project and tells you exactly how much computational waste you're carrying — translated into grams of CO2.

No runtime analysis. No network requests. No opinions. Just measurable facts.

cargo install green-linter
green-linter ./my-project --country USA
Enter fullscreen mode Exit fullscreen mode

GitHub: OnCeUponTry/GREEN-LINTER | crates.io: green-linter


The Problem

Every node_modules/ committed to a repo, every phantom dependency listed but never imported, every Docker image built on ubuntu instead of alpine — it all gets stored, transferred, backed up, and rebuilt across CI pipelines worldwide.

But how much does it actually cost in carbon? I couldn't find a single tool that answered this question for project structure. Tools like CodeCarbon measure runtime energy. GreenFrame measures web page loads. Eco-CI tracks pipeline energy. But nothing audits the static waste sitting in your repo right now.

That's the gap green-linter fills.


How It Works

green-linter walks your project tree and checks for 12 categories of waste across 4 domains:

Domain Checks What It Catches
Docker 13 patterns Heavy base images with size deltas, missing cache optimization, layer bloat, orphaned Dockerfiles
Node.js Usage analysis Heavy deps with SAFE/PARTIAL/unused verdict, phantom deps via peer graph, duplicates, deprecated
Artifacts 10 dirs node_modules/, dist/, .next/, target/ committed to repo — real disk size
Lockfiles 2 checks Missing lockfile, conflicting lockfiles

Every finding is a measurable fact with real numbers. No "consider using alpine" — instead: "ubuntu:22.04 = 77MB. alpine:3.19 = 7MB. Delta: 70MB."

CO2 estimation uses peer-reviewed methodology:


Demo: Real Output

Here's green-linter scanning a real React + NestJS project:

green-linter v0.2.0

Scanning: /home/user/my-project
Detected: Node.js project (package.json)
Country:  PER (291.77 gCO2/kWh)

Found 18 finding(s):
14 Phantom Dependency | 2 Build Artifact | 1 Heavy Dependency | 1 Lockfile Conflict

 1. [N] Heavy Dependency (package.json)
    Heavy dependency: axios (~450KB) — PARTIAL usage
    Consider native fetch (0KB). Potential savings: ~450KB
    ~ 0.0073 gCO2

 2. [N] Phantom Dependency (package.json)
    Phantom dependency: @radix-ui/react-alert-dialog
    Listed in dependencies but not imported in any source file

17. [N] Build Artifact
    node_modules/ in repository (667.4 MB)
    ~ 10.8 gCO2

--- CO2 Impact Summary ---
  Total waste measured: 669.2 MB
  Estimated CO2:       11.4413 gCO2
  Method: 0.06 kWh/GB (Aslan 2018) x grid intensity (Ember 2023)
  Like keeping a 9W LED on for ~4.4 hours
  RAGEST (669.2 MB) — Your project weighs more than my first laptop.

  This scan's footprint: ~0.002g CO2
Enter fullscreen mode Exit fullscreen mode

What Makes It Different

Peer Graph Analysis — Zero False Positives

The hardest problem in dependency auditing: false positives. If your project lists @radix-ui/react-popover, which internally requires @radix-ui/react-portal as a peer dependency — is react-portal a phantom dependency?

No. green-linter reads every dependency's package.json inside node_modules/ and builds a peer dependency graph. If a listed dependency is required as a peer by any other installed package, it's not phantom. This eliminated 4 false positives in my test suite across 6 real-world projects.

The same logic extends to Docker: multi-stage awareness. If your Dockerfile has a production stage that runs npm install --production, green-linter won't flag devDependencies in that stage — because they're correctly excluded.

Result: 0 false positives across 37 findings in 6 projects tested.

The LED Bulb Equivalent

CO2 grams are abstract. So green-linter converts waste into something tangible: hours of a 9W LED bulb. The clever part? This metric is country-independent — the grid carbon intensity cancels out in the ratio (waste_CO2 / LED_CO2), because both use the same grid. It works the same in Norway (low carbon) and Poland (high carbon).

The RAGE Waste Scale

Every scan ends with a waste profile — with brutally honest feedback:

Level Range Sample Message
😌 CHILL < 100 MB "Nice! You actually read the docs."
😠 ANGRY 100–500 MB "node_modules just sent a distress signal."
💀 RAGEST > 500 MB "Delete node_modules. Breathe. Start over."

9 messages total, deterministically selected — same project always gets the same message.

Disk Accuracy: 99.6%

Most tools use metadata.len() (logical file size). green-linter uses blocks() * 512 (actual disk allocation) on Unix systems. For directories with thousands of small files (like node_modules/), this closes a ~28% gap between reported and real disk usage. Verified against du -sh.


Built With GitHub Copilot — Pure Terminal, Zero IDE

This entire project was built using GitHub Copilot CLI in a Linux terminal. No VS Code. No GUI. No IDE. Just a shell, Copilot, and a conversation.

Here's what that looked like in practice — real pair programming, not "AI wrote my code":

Structured Definition Before Code

Before writing a single line of Rust, we went through a 6-phase MVP definition:

  1. E2E scope: 7 mandatory features, anything else goes to MEJORAS.md
  2. Uniqueness search: analyzed 7 existing tools — found the niche (static structure audit)
  3. Scope questionnaire: decided offline-only, 2 ecosystems, CLI-only
  4. Improvements log: 12 ideas captured but excluded from MVP
  5. Gap analysis: 6 gaps identified with explicit strategies (RESOLVE / SCOPE-REDUCE / DEFER)
  6. Pre-implementation review: verified architecture covers all features, no contradictions

Only then did we start coding. This structure prevented scope creep and kept the weekend timeline achievable.

The Pair Programming Dynamic

This wasn't "prompt and paste." I set quality standards; Copilot proposed implementations; I challenged the proposals:

  • I detected that phantom dependency detection had false positives on framework packages → Copilot implemented peer graph analysis by walking node_modules/*/package.json
  • I noticed that metadata.len() underreported node_modules/ size by ~28% → Copilot found std::os::unix::fs::MetadataExt::blocks() * 512 for disk-accurate measurement
  • Copilot proposed the LED bulb equivalent → I validated that grid intensity cancels out, making it country-independent
  • I required zero false positives → Copilot built multi-stage Docker awareness and the import index (O(1) lookup per dependency)

Every architectural decision was debated, not delegated.

Terminal Workflow

The entire lifecycle happened in Copilot CLI:

  • Architecture: discussed and documented in DEFINICION.md (6 phases)
  • Implementation: Rust code written, compiled, tested — all via terminal
  • Compilation: cargo build via SSH to a build server, results analyzed in the same session
  • Testing: ran against 6 real projects, verified 0 false positives, benchmarked at 56ms median
  • Publishing: git commit, git push, cargo publish to crates.io — from the same terminal session
  • This post: drafted, reviewed, and published via Copilot CLI + dev.to API — even this writing was pair-programmed

No file was ever opened in an IDE. The git log tells the story:

e4e10eb v0.2.0: disk size accuracy, LED bulb equivalent, RAGE waste profile
2511345 green-linter v0.1.0: static project auditor for computational waste
71a6442 Add GPL-3.0-or-later license
Enter fullscreen mode Exit fullscreen mode

Three focused commits. Two published versions. One weekend.


JSON for CI/CD

green-linter . --country USA --json | jq '.summary'
Enter fullscreen mode Exit fullscreen mode
{
  "total_findings": 18,
  "total_wasted_bytes": 701753344,
  "total_co2_grams": 11.441,
  "lightbulb_hours": 4.357,
  "waste_profile": {
    "emoji": "RAGEST",
    "label": "RAGEST",
    "message": "Your project weighs more than my first laptop."
  }
}
Enter fullscreen mode Exit fullscreen mode

Exit code 1 when waste is detected — plug it into any CI pipeline to catch bloat before it ships.


Prize Categories

Best Use of GitHub Copilot — green-linter was built entirely through pair programming with GitHub Copilot CLI in a pure terminal environment. Every line of Rust, every architectural decision, every test, and every publication step — including this very post — was pair-programmed in Copilot CLI. No IDE was used at any point.


Technical Stats

Metric Value
Build time ~8 hours (single day, from zero to published)
Language Rust (855KB static binary)
Dependencies 4 (clap, colored, serde, serde_json)
Scan speed 56ms median (real project, 61 source files)
Countries 209 (carbon data embedded, offline)
False positives 0 across 6 projects, 37 findings
Disk accuracy 99.6% vs du -sh
Scan footprint ~0.002g CO2 (5,720x less than typical project waste)
License GPL-3.0-or-later

Try It

# Install
cargo install green-linter

# Scan your project
green-linter . --country USA

# JSON output for CI
green-linter . --country USA --json
Enter fullscreen mode Exit fullscreen mode

Your project's waste is probably 5,720x more expensive than running this scan. Find out how much.


green-linter v0.2.0 — GitHub | crates.io

Top comments (0)