open-standards/joulehook/SPEC.md
Transaction Science 1d000aba5a joulehook: new open standard v0.1.0-draft.1 — metered/gated/attested agent work in any host
The host-binding layer for JCP + Mesh + jcp-efficiency: carry energy-metering,
capability-gating, and attested receipts into third-party AI coding agents
(Claude Code, Cursor, Windsurf, Antigravity, Zed, JetBrains, OpenCode) through
their own extension seams, without forking them. Grounded in research: no host
exposes its agent loop to extensions, but all expose three seams — a per-action
gate (PreToolUse-hook family / ACP request_permission), a model-call meter
(base_url proxy / OTel gen_ai.*), and a receipt surface. SPEC.md normalizes those
seams + defines conformance profiles (claude-code reference, hooks-family, acp,
opencode, cline, vscode, meter-only). §7 states the honest limit: a host adapter
alone cannot meter the host agent's tokens — a complete figure needs the meter seam.

Name is provisional (steward's call). Reference impl (joulehook-rs + the
claude-code plugin) lands next.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-07-04 05:42:45 -04:00

12 KiB
Raw Permalink Blame History

JouleHook — Metered, Gated, Attested Agent Work in Any Host

Version: 0.1.0-draft.1 · Status: Draft · Profile: joulehook/1 Specification text: CC-BY-4.0 · Reference code (joulehook-rs/): Apache-2.0

Provisional name. The steward may rename the standard; the profile string, receipt kind, and seam names are the stable surface.

JouleHook is the open standard for carrying energy-metering, capability-gating, and attested receipts into a third-party AI coding agent or editor — through the host's own extension seams, without forking it. It does not replace the host's agent or its model. It binds the three seams that every host already exposes — a per-action gate, a model-call meter, and a receipt surface — to a decide-outside-the-model grant check, an honest energy meter, and a sealed receipt. One agent's work becomes a metered, gated transaction — in Claude Code, Cursor, Windsurf, Antigravity, Zed, JetBrains, or OpenCode — from one core.

JouleHook is one of the Transaction Science open standards. Transaction Science is the steward, not the proprietor: the seam interfaces and the right to fork are public. JouleHook builds on three sibling standards rather than re-inventing them: JCP (../jcp) supplies the grant + decision model, Mesh (../mesh) supplies the metering front door, and jcp-efficiency supplies the efficiency/1 receipt.


§1 Why JouleHook exists

An energy-accounted, methodology-gated coding loop is worth little if it only runs in one editor. Developers already live in Claude Code, Cursor, Antigravity, Zed, and OpenCode, and no host exposes its built-in agent loop to a third-party extension: you cannot, from an extension, observe the host agent's token consumption or intercept its native file/shell tools. A naïve "one native plugin per editor that wraps the agent" is therefore impossible by construction.

But every host does expose the same three seams, and JouleHook is the normative contract over them:

  1. A gate — the host lets an external process (or an in-process hook) approve, deny, or rewrite a tool action before it executes. This is the PreToolUse-hook family (Claude Code, Cursor, Windsurf, Antigravity, Cline, OpenCode) and ACP session/request_permission (Zed, JetBrains, Neovim).
  2. A meter — the one place every agent's tokens are authoritative and every request can be refused is the model-call boundary: an OpenAI/Anthropic-shaped proxy addressed by a base_url override, or the host's own OpenTelemetry gen_ai.* export.
  3. A receipt surface — a place to carry verifiable artifacts back to the user: MCP resources, a status line, or a panel.

JouleHook standardizes the shape of what rides those seams, so a single core is written once and bound to each host by a thin adapter.


§2 The three seams (the whole standard)

Seam Binds to (host mechanisms) JouleHook contract Backed by
Gate (§3) PreToolUse-hook family; ACP request_permission Normalized ActionDecision (allow / deny / ask / rewrite) + sealed decision receipt JCP grant (../jcp)
Meter (§4) base_url proxy; OTel gen_ai.* ingest efficiency/1 per completed unit; joule-ceiling enforced at the model boundary Mesh (../mesh), jcp-efficiency
Receipt (§5) MCP resources; status line; panel Hash-chained, verifiable efficiency/1 + decision receipts jcp-efficiency, jcp-receipt

A conformant deployment binds at least the Gate seam or the Meter seam, MUST seal receipts (§5), and MUST state honest provenance (§7). Binding all three is the full profile (§6).


§3 The Gate seam (normative)

§3.1 The normalized action event

A host presents a pending tool action to the gate. JouleHook normalizes the host's native schema into a host-agnostic ActionEvent:

Field Type Meaning
session_id string The host session.
tool string The action's tool name (host-native or mcp__<server>__<tool>).
input object The tool's arguments (e.g. {"command":"npm test"}, {"path":..,"content":..}).
cwd string Working directory.
content_id string | null Content id of the target, when derivable (a file, a command).

An adapter MUST map its host's hook payload onto ActionEvent losslessly for the fields the host provides, and MUST NOT fabricate a content_id it cannot derive.

§3.2 The decision

The gate returns an ActionDecision:

  • allow — the action proceeds unchanged.
  • deny — the action is blocked; reason is surfaced to the agent.
  • ask — a human is asked to approve (bound to the host's approval UI where one exists; otherwise degrades to deny).
  • rewrite — the action proceeds with updated_input substituted (e.g. a redaction).

The decision MUST be reached outside the model — it is a deterministic function of the ActionEvent and the active JCP grant, never a request to the LLM (JCP § decide-in-the-runtime). An adapter that asks the host's model to self-approve is non-conformant.

§3.3 The JCP binding

The gate decision is a JCP capability + budget check:

  1. Resolve the active SignedGrant for the session. Verify its issuer signature.
  2. The action tool×content_id MUST be permitted by the grant's capability set; an action the grant does not hold is deny.
  3. If the action carries an estimable cost, the grant's joule budget MUST be ≥ the estimate; over budget is deny. On allow, the spent amount is debited.
  4. The decision — allow and deny alike — is sealed (§5).

§3.4 Host bindings (informative)

Host Gate mechanism deny signal
Claude Code PreToolUse hook (external process, JSON on stdin) permissionDecision:"deny" / exit 2 — blocks even under --dangerously-skip-permissions
Cursor .cursor/hooks.json (beforeShellExecution, beforeMCPExecution, …) permission:"deny" / exit 2
Windsurf Cascade hooks (pre_run_command, pre_write_code, …) exit 2
Antigravity hooks.json PreToolUse allow_tool:false + deny_reason
OpenCode tool.execute.before (in-process TS) throw to deny / mutate args to rewrite
Cline SDK beforeTool (fail_closed); file PreToolUse {cancel}
Zed / JetBrains / Neovim ACP session/request_permission reject

The four external-process hooks (Claude Code, Cursor, Windsurf, Antigravity) share a JSON-in / decision-out shape; a single gate binary MAY serve all four behind a per-host input adapter. OpenCode/Cline are served by a thin in-process shim that calls the same core; Zed/JetBrains by an ACP agent (§6).


§4 The Meter seam (normative)

§4.1 The model-call boundary

Authoritative token accounting and enforceable spend control exist at exactly one place common to every host: the model call. A JouleHook meter binds there by one of two methods:

  • Proxy (enforcing) — an OpenAI/Anthropic-shaped endpoint the host is pointed at via base_url / ANTHROPIC_BASE_URL. It reads the authoritative usage on every response, converts tokens→microjoules at honest provenance, and MAY refuse a request whose estimated cost exceeds the active grant's joule ceiling (a hard reject before the request reaches the provider). This is the Mesh front door (../mesh); its usage.energy carries the receipt.
  • Telemetry (observing) — ingest of the host's native OpenTelemetry GenAI export (gen_ai.usage.input_tokens / output_tokens), where the host emits it (Claude Code, VS Code/Copilot, Gemini CLI, Codex). Observe-only: it cannot refuse.

§4.2 The unit and the ceiling

The meter MUST produce an efficiency/1 receipt per completed, verified unit of work (jcp-efficiency), carrying microjoules per accepted token at honest provenance and the outcome anchor. A joule ceiling declared on the session grant MUST be enforced by a Proxy meter (reject over budget) and, where only a Telemetry meter is present, MAY be enforced only after the fact (the run is metered, not capped) — which the adapter MUST disclose (§7).


§5 The Receipt seam (normative)

Every gate decision and every completed unit seals as a receipt:

  • Decision receipts — each allow/deny from §3, sealed as a JCP decision receipt (non-repudiable, hash-chained).
  • efficiency/1 receipts — each completed unit from §4.

Receipts MUST be verifiable by a third party holding the steward's public key, MUST hash-chain within a session, and SHOULD be surfaced through the host's receipt surface (MCP resources, a status-line figure, or a panel). Where the meter is bound via the Mesh proxy and the energy figure is attested (sandbox-tee::energy), the receipt MAY carry the attestation commitment (efficiency/1.energy_attestation) and its honest trust level.


§6 Conformance profiles

A JouleHook adapter declares one or more profiles. Each names the seams it binds:

Profile Host(s) Gate Meter Receipt
claude-code Claude Code PreToolUse hook proxy or OTel MCP + statusline
hooks-family Cursor, Windsurf, Antigravity hooks.json proxy or OTel MCP + panel
acp Zed, JetBrains, Neovim request_permission own the loop session/update
opencode OpenCode tool.execute.before own the loop or proxy tui.toast
cline Cline beforeTool own the loop or proxy registered tool
vscode VS Code family (Open-VSX) own contributed tool only proxy or OTel status bar + webview
meter-only Continue, any OTel host — OTel data/gen_ai.* dashboard

Minimal conformance: bind ≥1 seam and seal receipts (§5) with honest provenance (§7). full conformance: bind all three seams for a host, with a Proxy meter (enforceable ceiling) and hash-chained receipts.

The reference profile is claude-code: a single installable plugin bundling the gate hook, an MCP receipt server, and a status-line joule meter — the deepest gate available anywhere and the clearest end-to-end demonstration.


§7 The honest limit (normative honesty)

A host-side adapter, alone, cannot meter the host agent's own tokens or its built-in (non-adapter) tool calls — those are invisible from every host's extension sandbox (confirmed across VS Code, Cursor, Windsurf, Antigravity, Zed, JetBrains). Therefore:

  • A complete energy figure REQUIRES the Meter seam (§4) bound via proxy or OTel. An adapter that presents a whole-session energy figure without a bound meter is non-conformant — it may only report the energy of work that passed through its own tools, and MUST label it as such.
  • An adapter whose only meter is Telemetry (§4.1) MUST disclose that its joule ceiling is observed, not enforced.

Overclaiming coverage is a conformance failure, not a rounding of the truth.


§8 Security and trust

JouleHook inherits JCP's stance: every action is decided in the runtime, never in the LLM, because a tool description and a tool result are untrusted input. The gate is a deterministic function; a deny binds regardless of the host's permission mode where the host allows a hook to override it (e.g. Claude Code PreToolUse fires before the permission check). Receipts are non-repudiable and hash-chained. The adapter runs inside the host's trust domain and MUST NOT weaken it: it adds gates and receipts, it does not remove the host's own approvals.


§9 Relationship to the sibling standards

JouleHook is the host-binding layer, not a re-implementation:

  • JCP decides and grants (capability ⊗ joule budget = one signed grant); JouleHook binds that decision to each host's gate seam.
  • Mesh meters and routes at the model front door; JouleHook points a host at it as the Meter seam and enforces the ceiling.
  • jcp-efficiency is the receipt; JouleHook carries it through each host's receipt surface, optionally with an attested energy figure (sandbox-tee::energy).

The contribution of JouleHook is the normative seam contract + the conformance profiles that make one metered, gated, attested loop portable across agents that would otherwise each need a bespoke integration.