haggle: Instructions file for Codex

AGENTS.md

haggle AGENTS.md is an instructions file for Codex, OpenCode from NaanyaBiz/haggle. It costs 31,946 tokens per session, scanned A, original, Apache-2.0.

A project instruction file for Haggle, a Home Assistant integration that imports AGL Australia smart-meter data into Home Assistant’s Energy dashboard. It documents the development loop, checks, and testing commands.

In plain words
What is it for?
Use it to install dependencies, run Python tests and code checks, validate the integration manifest, run type checks, and execute the project’s pre-commit checks.
Why use it?
It gives contributors and coding agents one place to find the project’s setup and validation steps. It also identifies checks that require Home Assistant’s tooling or a CI run.

Instructions file for CodexOpenCode

Written for Codex and OpenCode: the file is AGENTS.md. Also seen: reads .claude/ paths; mentions CLAUDE.md; mentions subagents.

This is NaanyaBiz/haggle's own configuration. It tells Codex and OpenCode how to work on haggle itself, so it is not a mod to install elsewhere. Copy it as a starting point and replace the rules that are about this project. Everything haggle configures →

Needs its repository: it reads a path above its own folder, which exists only inside the repository. The line is # → open Claude Code at ../haggle.wt/feat-agl-login/.

Reuse

Borrowing it

Nothing to install: this file belongs to NaanyaBiz/haggle. Take a copy, put it at the same path in your own repository, and replace the rules that are about this project with yours.

Copy the file
curl -O https://raw.githubusercontent.com/NaanyaBiz/haggle/main/AGENTS.md
Clone the repo
git clone --depth 1 https://github.com/NaanyaBiz/haggle

Made for: Codex, OpenCode.

Wrote this? Show the measurements

A badge with what this costs and how it scanned, read live from this page, so it follows the numbers instead of freezing them. Markdown for a README, HTML for a documentation site or a project page.

agentmods badge for haggle AGENTS.md

README.md
[![agentmods](https://agentmods.dev/badge/instructions/naanyabiz/haggle/agents-md/github.svg)](https://agentmods.dev/instructions/naanyabiz/haggle/agents-md)
Your own site
<a href="https://agentmods.dev/instructions/naanyabiz/haggle/agents-md"><img src="https://agentmods.dev/badge/instructions/naanyabiz/haggle/agents-md/github.svg" alt="Measured on agentmods" height="20"></a>

Or the 80×15 button, for a site that already has a row of RSS and ATOM ones. Only the verdict fits; the numbers stay here.

agentmods 80×15 button for haggle AGENTS.md

Your own site · 80×15
<a href="https://agentmods.dev/instructions/naanyabiz/haggle/agents-md"><img src="https://agentmods.dev/badge/instructions/naanyabiz/haggle/agents-md.svg" alt="Reviewed on agentmods" width="80" height="20"></a>
Per session 31,946 This file is loaded in full into every session.
When invoked 31,946 The same file — it is already loaded in full.
Security scan A 0 findings. A grade says what 26 rules found in the file — not that it is safe.
Origin original No closer match found in the catalogue.
Token cost

What it costs to keep this loaded

Counted locally with the o200k_base tokenizer, which is exact for GPT models; Claude uses its own tokenizer and its counts differ. Treat this as one consistent yardstick across the catalogue rather than a bill. Prices are per million input tokens.

ModelPer sessionOnce invoked
Fable 5.1 $0.31946 $0.31946
Opus 5.5 $0.12778 $0.12778
Sonnet 5.5 $0.06389 $0.06389
Haiku 4.5 $0.03195 $0.03195

Measured 5d ago against content hash fb02c4ae3726, method: parsed. Prices are Anthropic first-party input rates as of 2026-10-07, from the pricing page.

Security

Grade A, and why

haggle AGENTS.md scanned grade A with 0 findings against 26 rules in 11 categories — prompt injection, anti-refusal, data exfiltration, privilege escalation, supply chain, agent snooping, system-prompt leakage, SSRF and excessive agency — measured 5d ago.

A static scan of the body, not an audit. Every finding is printed with the line that produced it so you can judge whether it matters here. A mod is markdown that instructs an agent; that is exactly why what it instructs is worth reading.

Nothing flagged

None of the 26 patterns this scan looks for appear in this file: no shell pipes, no recursive deletes, no credential paths, no hidden text, no instruction-override or anti-refusal phrasing, no agent-config snooping. That is not a guarantee, it is the absence of the things that are checkable.

AGENTS.md · 1,859 lines

How it starts

The opening of the file, as written. The whole thing — 1,859 lines — stays where its author put it; the contents beside it link to each section on GitHub.

AGENTS.md — Haggle Integration Guide

One-liner: haggle is a Home Assistant custom integration that pulls AGL Australia smart-meter interval data from AGL's undocumented REST API and feeds it into HA's Energy dashboard via import_statistics().

This file is the canonical documentation for both human contributors and AI agents. CLAUDE.md is a symlink to this file.


Dev Loop

# Install deps (once, or after pyproject.toml changes)
uv sync

# Wire the git hooks (once) — pre-commit + commit-msg stages
# (provenance trailer, Conventional Commits); pre-push stays opt-in
uv run pre-commit install

# Run tests
uv run pytest

# Lint + format
uv run ruff check --fix custom_components/ tests/
uv run ruff format custom_components/ tests/

# Type-check
uv run mypy custom_components/haggle

# Validate manifest
python scripts/validate_manifest.py custom_components/haggle/manifest.json

# Run all pre-commit hooks
uv run pre-commit run --all-files

# Hassfest — easiest via CI (push a branch + open PR)
# Or use the dedicated image locally:
docker run --rm \
  -v "$(pwd)/custom_components:/github/workspace/custom_components:ro" \
  ghcr.io/home-assistant/hassfest \
  --integration-path /github/workspace/custom_components/haggle

Test strategy (what layer of testing a change needs, coverage floor, when live-HA manual testing is required): docs/testing.md.

Control expectations: this repository operates under the committed secure-SDLC standard; every CO-x.y reference in this tree resolves there. The statement-level conformance map records how each control is met (or the recorded exception) — a PR that changes a control surface (workflow, ruleset baseline, agent grant, release gate, security doc) updates the affected conformance rows in the same PR.


Repo Map

custom_components/haggle/
├── __init__.py          # async_setup_entry / async_unload_entry / async_remove_entry + HaggleRuntimeData; _check_pin reads pins live from entry.data; async_migrate_entry (minor 1→2: CONF_LOCAL_TZ derived from the entry title, #268); setup resolves the contract tz CONF_LOCAL_TZ → HA tz (fallback flagged tz_is_contract=False)
├── manifest.json        # HACS/HA metadata; hassfest validates this
├── const.py             # all constants — DOMAIN, API hosts, config-entry keys (incl. CONF_LOCAL_TZ, the contract-tz authority), AGL_API_TZ_KEY (the zone AGL converts dateTime through, #292), CONF_TZ_REALIGN + TZ_REALIGN_* / MAX_TZ_REALIGN_* (the one-off timezone history re-alignment record contract, #292), data keys
├── config_flow.py       # PKCE authorize URL → user pastes callback → exchange → select_contract (electricity-only via _serviceable_contracts, #260); reauth via its own `reauth_confirm` step (#284; token only, fills missing pins) + reconfigure (token + re-pin, dismisses pin-mismatch notices): entry contract matched by number, no picker, async_update_reload_and_abort(data_updates=…) (#275); options flow (solar statistics-writes toggle, poll-interval throttle); MINOR_VERSION 2 — stores CONF_LOCAL_TZ from the selected contract's address at creation (fast path + picker) and refreshes it on reauth/reconfigure (#292/#268)
├── diagnostics.py       # anonymized config-entry diagnostics (schema v4 — v3 added coordinator.contract_timezone + entry.data.local_tz, v4 the top-level tz_realign record) — public-safe; parsed by the triage routine (docs/diagnostics.md)
├── coordinator.py       # HaggleCoordinator: 30-day backfill (throttled, 429-aware, per-series ranges) + incremental statistics import (aggregate + per-tariff ToU series + solar generation/credit on hasSolar contracts) + bill-period solar totals + half-hour-zone straddle guard (overlap day + content-derived trim, #292) + contract-local midnight helper _local_midnight_utc (#268) + stale-key fill on every import (_stale_key_fill: provenance-gated zero / carry-forward re-chain of stored rows the batch has no value for, #300) + one-off 30-day timezone history re-alignment (_plan_tz_realign / _settle_tz_realign, CONF_TZ_REALIGN: zone-gated (shift scanned over a year, NT/WA excluded in every season), two stages, bar-exact floor junction _realign_junction (rewrites the hour below the window), pure re-key recognition _rekey_matches on realign imports (#303), incomplete sweep degrades to a normal cycle, #292)
├── sensor.py            # 14 SensorEntityDescription entries (3 conditional ToU rate sensors, 5 conditional solar sensors); HaggleEnergySensor
├── agl/
│   ├── __init__.py
│   ├── client.py        # AglAuth (JWT expiry + token rotation) + AglClient (HTTP methods; local_tz + tz_is_contract, set_contract_tz)
│   ├── models.py        # TokenSet, Contract, IntervalReading, DailyReading, BillPeriod, PlanRates
│   ├── parser.py        # JSON → typed dataclasses; TOTAL over arbitrary JSON (fuzz-enforced) — filters type=none intervals; label-keyed bill projection (_projection_label, #253); Sydney-conversion inverse relocalise_agl_timestamp keyed on the response's timeZone (#292); agl_api_tz (the ONE API-zone resolution the parser and the re-alignment gate share) + agl_reported_timestamp (exact inverse: the old-convention instant, for the realign junction)
│   └── pinning.py       # SPKI extraction helper for Trust-On-First-Use TLS pinning
├── strings.json         # translatable config-flow strings
└── translations/en.json # English strings (must mirror strings.json)

tests/
├── conftest.py                      # _auto_enable_custom_integrations fixture
├── fixtures/
│   ├── PROVENANCE.md                 # fixture provenance + the solar capture consent note
│   ├── hourly_response.json         # 30-min interval data (Current/Hourly)
│   ├── overview_response.json       # /v3/overview with accounts + contracts
│   ├── plan_response.json           # /v2/plan/energy with gstInclusiveRates (flat rate)
│   ├── tou_plan_response.json       # Time-of-Use plan — per-band gstInclusiveRates
│   ├── tou_hourly_response.json     # mixed peak/offpeak/shoulder/normal intervals
│   ├── solar_hourly_response.json   # REAL full-day ElectricitySolar capture (2026-07-01, app-reconciled) — provenance + consent: fixtures/PROVENANCE.md
│   ├── solar_plan_response.json     # solar plan — feed-in rate in gstExclusiveRates
│   ├── overview_solar_response.json # /v3/overview variant with hasSolar: true
│   └── bill_period_response.json    # usage summary
├── test_init.py                     # setup/unload smoke tests + minor-version migration (CONF_LOCAL_TZ from title) + stored-tz resolution at setup
├── test_config_flow.py              # PKCE step navigation (user → exchange → select_contract) + reauth/reconfigure update-in-place + CONF_LOCAL_TZ stored on creation/reauth/reconfigure
├── test_agl_client.py               # AglAuth token rotation + AglClient HTTP methods + pin-check wiring
├── test_const.py                    # base64 sanity-check on AGL_AUTH0_CLIENT
├── test_parser.py                   # parse_interval_readings, parse_overview, parse_plan, ToU rate mapping, safe_float, relocalise_agl_timestamp zone/DST vectors + window interaction (#292)
├── test_pinning.py                  # SPKI extraction + host-name guards
├── fuzz/
│   ├── fuzz_parser.py               # atheris harness — parser totality + numeric guards (run by fuzz.yml)
│   └── requirements.txt             # hash-pinned atheris (Scorecard Pinned-Dependencies)
├── test_coordinator_statistics.py   # backfill, incremental resume, idempotency, ToU per-tariff series, numeric guards, half-hour-zone overlap/trim + contract-local midnight sites (#292)
├── test_tz_realign.py               # #292 timezone history re-alignment state machine (gates incl. NT/WA unsupported_shift checked first, with no Repairs issue, floor freeze, stages, halts vs attempts, C2 inclusive horizon, give-up, zone change, notice floor = swept start, Repairs issues, period gate, diagnostics v4, request ceiling, junction old-convention classifier TestRealignJunctionMatch)
├── test_tz_realign_recorder.py      # re-alignment end to end vs the REAL recorder — bar-exact floor junction (consumption + generation, sum and floor-day bar), stage order/budget, C1 degrade == plain normal poll, give-up and NT/WA (RA-19) junction residuals, C10, junction cost/bands/credit, interior check past a flat night, #303/R2 re-key through the cycle (consumption family incl. ToU bands, and generation)
├── test_recorder_statistics.py      # sum-chain scenarios vs the REAL recorder (recorder_mock) — spike/#114/ToU-partition/half-hour-straddle classes + #300 stale-key fill (SA/QLD-DST/generation convention re-key with stale keys asserted 0, per-day gate incl. generation error day, wholly-absent ToU band, provenance gate, straddle both-days, conservation guard, read budget on the real recorder read)
├── test_sensor.py                   # sensor descriptions + conditional ToU rate-sensor registration
├── test_claude_hooks.py             # hook sanitization (#244), guard robustness, TOFU verify-wiring fail-closed (#245) — executes the literal shipped scripts/commands
├── test_provenance_hook.py          # executes scripts/check_provenance_trailer.sh against sample messages (any-vendor Co-Authored-By / AI-Assisted: none / merge skip)
└── test_diagnostics.py              # leak tests (token/contract/account/SPKI never serialize) + schema v4 shape (tz_realign)

docs/
├── compliance/
│   ├── secure-sdlc-standard.md  # the standard this repo operates under — 19 COs / 94 statements, industry-agnostic (v1.0)
│   └── conformance.md           # statement-level conformance map: mechanism per statement + RA-xx exceptions — update rows in the SAME PR as any control-surface change
├── energy-dashboard.md  # user guide — which haggle:* statistics to add per plan type, sensor glossary, troubleshooting (#137 footgun)
├── delivery-metrics.md  # quarterly delivery-metrics process + recorded time-to-restore exception (CO-18.3)
├── releasing.md         # release acceptance policy — beta-soak rule, hotfix evidence rule, downgrade test, acceptance record
├── testing.md           # test strategy — four layers, coverage floor, when live-HA manual testing is required
├── diagnostics.md       # diagnostics schema v3 reference — users + triage routine (bump with DIAGNOSTICS_SCHEMA_VERSION)
├── threat-model.md      # living threat model — trust boundaries, STRIDE register + dispositions, AI agents, regulatory scope, resilience targets
└── agents/
    ├── triage-routine.md    # authoritative spec of the haggle-triage routine (repo-first change control, CO-12.8) — edit HERE, then sync the platform copy
    └── injection-corpus.md  # canned hostile payloads + manual replay procedure — run before ANY triage-prompt change

scripts/
├── delivery_metrics.py  # quarterly CO-18.3 delivery metrics + CHANGELOG/tag/release reconciliation (docs/delivery-metrics.md)
├── wt                   # bash worktree helper (new / list / rm)
├── pin-hooks.sh         # re-pin .claude hook scripts + install wiring into settings.local.json AFTER reviewing diffs (#245 TOFU control)
├── access-review.sh     # quarterly access review (SECURITY.md "Access Review") — asserts the expected access surface + prints the manual checklist; read-only, maintainer-run with local gh auth, deliberately not CI
├── check_provenance_trailer.sh  # commit-msg hook: every commit names its AI tool (Co-Authored-By) or declares AI-Assisted: none (#283); tested by tests/test_provenance_hook.py
├── export-settings.sh   # admin-run: re-export control-plane baselines into .github/settings/ (PR-first on any settings change)
├── normalize-ruleset.jq / normalize-repo-public.jq  # shared normalizers (export script + settings-drift workflow)
└── validate_manifest.py # used by the validate-manifest Claude hook

.claude/
├── settings.json        # committed permission policy (permissions ONLY — hook wiring deliberately lives in the untracked settings.local.json, see #245)
├── hooks-wiring.json    # policy record for the hook wiring; installed into settings.local.json by scripts/pin-hooks.sh after review
├── hooks/               # the four hook scripts — TOFU-pinned via .claude/hooks.sha256 (untracked)
├── agents/              # 8 subagent definitions (5 domain + 3 review)
└── commands/            # 5 slash commands (new-entity, wt, release, hassfest, pr)

.github/
├── settings/            # declared state of the GitHub control plane (rulesets, repo settings) — see settings/README.md; weekly drift check
├── workflows/
│   ├── ci.yml           # ruff + mypy + pytest (Python 3.14, coverage floor 89) + gitleaks full-history scan + dependency-review + shellcheck/actionlint/zizmor
│   ├── hacs.yml         # HACS validation
│   ├── hassfest.yml     # Home Assistant integration manifest validation
│   ├── release.yml      # tag-triggered Release (first-party gh CLI): tag-on-main + tag-signature gates, HACS-installed attested zip (zip_release), SBOM attestations, check-run snapshot
│   ├── codeql.yml       # weekly + per-PR CodeQL Python scan
│   ├── compat.yml       # weekly non-blocking suite vs latest phcc/HA (incl. beta) — early upstream-breakage warning
│   ├── scorecard.yml    # weekly + on-push OpenSSF Scorecard self-assessment (feeds README badge)
│   ├── fuzz.yml         # weekly deep run + unconditional 120s PR smoke; corpus cached across runs; crash artifacts uploaded
│   └── settings-drift.yml # weekly: re-export rulesets + public repo settings, diff vs .github/settings/, issue on drift
├── CODEOWNERS           # @naanyabiz owns everything
└── dependabot.yml       # weekly pip + github-actions updates, grouped into one PR per ecosystem

# Repo-root posture files
.gitleaks.toml           # repo-specific secret rules (Auth0 refresh tokens, real AGL account/contract numbers) layered on gitleaks defaults
osv-scanner.toml         # per-advisory, expiring lockfile-advisory exceptions read by OSV-Scanner + Scorecard Vulnerabilities (admission rule: SECURITY.md § Supply chain, RA-20)
SECURITY.md              # disclosure path + threat-model summary
CONTRIBUTING.md          # dev loop + commit conventions + PR checklist
CODE_OF_CONDUCT.md       # Contributor Covenant 2.1
ROADMAP.md               # ~12-month direction + explicit non-goals (single-retailer AGL, read-only, no telemetry)

Read the full file on GitHub · 1,859 lines

Changes

What this file has done since we first saw it

Hashed on every crawl. A supply-chain change to an agent config is a question of when, not whether, so the history is kept rather than the latest state alone.

  1. 5d ago Changed · +11 lines · +250 tokens per session fb02c4ae3726
  2. 17d ago Changed · +382 lines · +6,592 tokens per session 6384ae85120b
  3. 19d ago Changed · +65 lines · +1,192 tokens per session 0a59bfcce29b
  4. 20d ago Changed · +237 lines · +4,604 tokens per session 0352b0f8f6b1
  5. 22d ago Changed · +78 lines · +1,409 tokens per session ee309ab1cf34
  6. 1mo ago Changed · +54 lines · +1,011 tokens per session fc4a57f80f16
  7. 1mo ago Changed · +78 lines · +1,160 tokens per session 0cf074423797
  8. 1mo ago First seen · 954 lines · 15,728 tokens per session scan A f446d762ee0c

Subscribe to this mod's changes

haggle AGENTS.md is an instructions file published in the GitHub repository NaanyaBiz/haggle (14 stars, last pushed yesterday), licensed Apache-2.0. It adds 31,946 tokens to every session, about $0.1278 per session on Opus 5.5. A static security scan graded it A with 0 findings. No closer match exists in the catalogue, so it is treated as the original; first seen 2026-09-04.

Related

Other instructions, from other repositories

vscode buildNext.instructions.md

Working notes and architecture documentation for the new esbuild-based build system in build/next. Use when making changes to the new build pipeline (transpile/bundle commands, NLS plugin, source-map handling, resource copying, or self-hosting watch tasks).

microsoft/vscode · 9,715 tokens

next.js AGENTS.md

AGENTS.md instructions for vercel/next.js, covering next.js development guide, codebase structure, monorepo overview, core package: packages/next and other important packages.

vercel/next.js · 7,461 tokens

vscode oss-third-party-notices.instructions.md

Instructions for microsoft/vscode, covering vs code oss third-party-notices pipeline, architecture, pipeline flow in ci, cache eligibility and rollout and applying the notice (cutover).

microsoft/vscode · 5,262 tokens

langchain AGENTS.md

AGENTS.md instructions for langchain-ai/langchain, covering global development guidelines for the langchain monorepo, corridor security analysis, project architecture and context, monorepo structure and development tools & commands.

langchain-ai/langchain · 4,680 tokens

vscode copilot-instructions.md

Copilot instructions for microsoft/vscode, covering vs code copilot instructions, project overview, root folders, core architecture (src/ folder) and built-in extensions (extensions/ folder).

microsoft/vscode · 2,750 tokens

deno copilot-instructions.md

Copilot instructions for denoland/deno, covering deno development guide for github copilot, network access, high level overview, key directories and key files to understand first.

denoland/deno · 3,077 tokens