Skip to main content

cleanshift

Delay batch ML/AI jobs to the cleanest grid window.

cleanshift wraps your long-running job — fine-tuning, batch inference, embedding generation — and schedules it during the lowest-carbon hour within a time window you specify. After execution it prints a savings receipt showing estimated CO₂ avoided vs. running immediately.

Install

pip install cleanshift

Quick start — no API key needed

import time
from cleanshift import carbon_window, MockProvider

provider = MockProvider()

with carbon_window(provider=provider, max_delay_hours=6) as window:
    time.sleep(1)  # your job here

print(window.receipt.model_dump_json(indent=2))

MockProvider generates a synthetic sinusoidal intensity curve (peak at 3 PM UTC, trough at 3 AM UTC) so you can develop and test without signing up for anything.

Real API example

import os, time
from cleanshift import carbon_window, ElectricityMapProvider

provider = ElectricityMapProvider(
    api_key=os.environ["ELECTRICITY_MAP_API_KEY"],
    zone="US-CAL-CISO",
)

with carbon_window(provider=provider, max_delay_hours=6) as window:
    run_fine_tuning()

print(window.receipt.model_dump_json(indent=2))

Decorator form

from cleanshift import carbon_window, ElectricityMapProvider, Policy

@carbon_window(
    provider=provider,
    max_delay_hours=12,
    policy=Policy.THRESHOLD,
    max_intensity_gco2_per_kwh=150,
)
def nightly_finetune():
    ...

nightly_finetune()
print(nightly_finetune.last_receipt.model_dump_json(indent=2))

Pure scheduling query

from cleanshift import find_cleanest_window, MockProvider

best = find_cleanest_window(
    MockProvider(),
    duration_hours=2,
    max_delay_hours=24,
)
print(f"Recommended start: {best.isoformat()}")

Policies

Policy Behaviour
min_carbon (default) Sleep until the lowest-intensity hour in the allowable window
threshold Run as soon as intensity drops below max_intensity_gco2_per_kwh; falls back to the cleanest available slot if the threshold is never met
now_or_never Run immediately if intensity is clean; raise JobSkipped otherwise
halt_if_dirty Start immediately; pause execution if intensity spikes above max_intensity_gco2_per_kwh mid-run; resume automatically when it drops back (Unix only)

halt_if_dirty notes

halt_if_dirty requires max_intensity_gco2_per_kwh and uses SIGSTOP/SIGCONT to pause the process, so it is not supported on Windows. The intensity is re-checked every poll_interval_seconds (default 5 minutes).

Receipt schema

class CarbonReceipt(BaseModel):
    scheduled_at: AwareDatetime        # when carbon_window was entered
    ran_at: AwareDatetime              # when execution actually started
    delay_seconds: int
    duration_seconds: int
    avg_intensity_gco2_per_kwh: float  # mean of readings at start + end of run
    counterfactual_avg_intensity: float  # intensity at scheduling time
    estimated_savings_pct: float       # computed field (positive = savings)
    region: str
    provider: str

avg_intensity_gco2_per_kwh is the arithmetic mean of readings taken at the start and end of the run — a point estimate, not a true integral. If your job is long enough that accuracy matters, prefer a provider with dense historical data.

Providers

Class Source Sign-up
MockProvider Synthetic curve None
ElectricityMapProvider electricitymaps.com Free tier available
WattTimeProvider watttime.org Free tier available

Adding a provider

Implement GridIntensityProvider:

from cleanshift.providers.base import GridIntensityProvider, IntensityPoint

class MyProvider(GridIntensityProvider):
    @property
    def provider_name(self) -> str: return "myprovider"

    @property
    def region(self) -> str: return "MY-REGION"

    async def current(self) -> IntensityPoint: ...

    async def forecast(self, from_dt, to_dt) -> list[IntensityPoint]: ...

CLI

# Dry-run with mock data (no API key)
cleanshift schedule --duration 2h --max-delay 24h --region US-CAL-CISO --dry-run

# With ElectricityMap
cleanshift schedule --duration 2h --max-delay 24h \
    --provider electricitymap --api-key $KEY --zone US-CAL-CISO --dry-run

Development

pip install -e ".[dev]"
pytest
python examples/synthetic_demo.py

License

MIT

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

cleanshift-0.1.0.tar.gz (14.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

cleanshift-0.1.0-py3-none-any.whl (15.8 kB view details)

Uploaded Python 3

File details

Details for the file cleanshift-0.1.0.tar.gz.

File metadata

  • Download URL: cleanshift-0.1.0.tar.gz
  • Upload date:
  • Size: 14.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for cleanshift-0.1.0.tar.gz
Algorithm Hash digest
SHA256 c35d02ff81ff5e03150f83a176cf9517db2452d8f2eeda070a3359927745ed40
MD5 9b7bb1d1d24f496e7a829a8881f72b84
BLAKE2b-256 806d9f64140a02312c3ce6a011914fec89aecd4ce419ba1e4a97e8a997d29771

See more details on using hashes here.

Provenance

The following attestation bundles were made for cleanshift-0.1.0.tar.gz:

Publisher: publish.yml on ChanelYJ19/cleanshift

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file cleanshift-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: cleanshift-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 15.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for cleanshift-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 cad3f528cb297bd01d714c6cfae5624bdaf31cf522ce038da8e84a7276d161c5
MD5 849c26b62249900d31c4032390690037
BLAKE2b-256 5c9dcc2ce47e8ea6a042475432ca675fa1308b51897c443c500227461b14c7ec

See more details on using hashes here.

Provenance

The following attestation bundles were made for cleanshift-0.1.0-py3-none-any.whl:

Publisher: publish.yml on ChanelYJ19/cleanshift

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page