A headless CLI for accessing Con Edison account, billing, and energy-usage data.
coned supports:
- Native login with SMS MFA and remembered devices
- Secure credential and session storage through the OS keyring
- Bill history and validated PDF downloads
- Historical usage, costs, forecasts, weather, and neighbor comparisons
- Green Button CSV, JSON, XML, and ZIP exports
- Human-readable tables and structured JSON output
- A deterministic offline demo that requires no account or network access
The project is pre-1.0. Commands and JSON schemas may change between minor releases. Authentication credentials and utility data are sensitive; review the security model before use.
Download a release archive, verify its checksum, and, when the gh CLI is available, verify its GitHub build provenance:
sha256sum -c checksums.txt --ignore-missing
gh attestation verify coned-cli_<version>_<os>_<arch>.tar.gz --repo zzwong/coned-cliAlternatively, install with Go:
go install github.com/zzwong/coned-cli/cmd/coned@latestTo build from a checkout:
make installGo 1.25.12 or newer is required. Release binaries are available for Linux and macOS on amd64 and arm64.
Demo mode is deterministic, offline, and isolated from your keyring:
coned --demo --json entities list
coned --demo usage forecast
coned --demo usage reads --aggregate hour \
--from 2026-01-01 \
--to 2026-01-02coned auth init
coned auth login
coned auth status
coned auth logout
coned auth logout --forgetInteractive password input is hidden. With persistence enabled, credentials and session cookies are stored only in macOS Keychain or Linux Secret Service. Credentials are saved only after confirmation, and there is no plaintext fallback.
For a one-off session:
coned auth login --no-storeFor operator-controlled input, pass one newline-terminated password through standard input:
printf '%s\n' "$CONED_PASSWORD" | \
coned auth login --password-stdin --no-storeThere is intentionally no --password argument.
If native login is unavailable, auth import-browser can import an authenticated local Chrome or Brave session over a loopback CDP endpoint:
coned auth import-browserconed bills list
coned --json bills list
coned bills download 2026-06-30-<id>
coned bills download 2026-06-30-<id> --output bill.pdfBill PDFs are first written to an owner-only temporary file with mode 0600. Before atomically moving the file to its destination, coned verifies the PDF file signature and enforces the download size limit. Existing files are left unchanged unless you pass --force.
coned accounts list
coned usage summary
coned usage forecast
coned usage bills
coned usage weather
coned usage neighbors
coned usage meters
coned usage realtimeUse --json for structured output:
coned --json usage summaryconed usage reads --aggregate bill
coned usage reads --aggregate day \
--from 2026-01-01 \
--to 2026-01-31
coned usage costs --aggregate hour \
--from 2026-01-01 \
--to 2026-01-02Supported aggregation levels are bill, day, and hour. Day and hour queries require both --from and --to. Large ranges are split automatically to stay within provider limits. When granular cost data is unavailable, non-bill cost queries fall back to usage-only reads.
coned usage export --format csv > usage.csv
coned usage export --format json --output usage.jsonExports support csv and json. When --output is used, coned writes to an owner-only temporary file and atomically moves it to the requested destination. Existing files are left unchanged unless you pass --force.
All usage commands are read-only. Missing real-time readings are reported as unavailable rather than returned as a provider error payload.
Provider identifiers can be represented by stable, profile-specific HMAC handles. The HMAC key is stored in the OS keyring. Raw account, premise, meter, and register identifiers are not written to configuration or diagnostic files.
coned entities list
coned --json entities list --type meter
coned entities alias account-xxxxxxxxxxxx home
coned entities alias meter-xxxxxxxxxxxx electric
coned entities select homeUse an alias or handle to select an account or meter:
coned --account home usage summary
coned --account home --meter electric usage realtimeIf more than one eligible entity exists, coned requires an explicit selection instead of silently choosing the first one.
Forecast and REST-history commands currently span all authorized utility accounts. They reject explicit selectors rather than guessing how Con Edison and Opower account identifiers correspond.
coned green-button inspect
coned green-button inspect --json
coned green-button export --format csv \
--from 2026-01-01 \
--to 2026-01-31 > usage.csv
coned green-button export --format json > usage.ndjson
coned green-button export --format xml > usage.xml
coned green-button download --format csv --output usage.zipThe provider generates these exports asynchronously. export writes the selected CSV or XML file to standard output; JSON output consists of newline-delimited objects converted from CSV. download saves the original provider ZIP through the same owner-only, atomic file-writing process.
When a provider response changes, generate a value-free structural report:
coned diagnostics schema --output schema.json
coned diagnostics inspect schema.jsonDiagnostics contain JSON paths, types, nullability, array cardinality, a schema version, provenance, and a small allowlist of non-sensitive enum values. They do not retain identifiers, names, addresses, dates, usage, costs, tokens, URLs, or response bodies. Diagnostic files are written with mode 0600.
Use profiles to isolate credentials and sessions:
coned --profile home auth loginOn Linux, non-secret configuration is stored at ~/.config/coned/config.json. Other operating systems use their standard user configuration directory:
{
"base_url": "https://www.coned.com",
"profile": "default",
"request_timeout": 30000000000
}CLI flags override the configured profile and timeout. The production client accepts only https://www.coned.com as its base URL.
make check
make build
./bin/coned versionSee CONTRIBUTING.md for development and pull-request guidance. Provider fixtures must be synthetic and include version, provenance, and last-verified metadata.
Use GitHub issues for reproducible, sanitized bugs and feature requests. This community project cannot help with Con Edison account, billing, outage, or service requests.
Report vulnerabilities privately according to SECURITY.md. See docs/security.md for storage behavior, headless Linux limitations, and the threat model.
This project interoperates with non-public web interfaces used by Con Edison’s My Account site. These interfaces are not offered as a documented or supported developer API and may change without notice. It is intended only for account holders and authorized agents accessing data they are permitted to view. Users are responsible for complying with their utility agreements and applicable terms. The software does not bypass access controls.
This project is not affiliated with or endorsed by Consolidated Edison, Inc., Opower, or Oracle. “Con Edison” and related marks belong to their respective owners.
Licensed under the Apache License 2.0. Copyright 2026 zzwong. Third-party license texts distributed with release archives are in third_party_licenses/.