Delivered output and usage
Requires Bee 1.0.0-beta.16 or later with bee delivery. Use bee delivery --help to check support in your binary.
| Quantity | What it establishes |
|---|---|
| Measured UTF-8 bytes | The size of Bee’s final output after its writer and flush succeed, including the wire envelope and newline. This is a local output observation. |
| Labelled token estimates | utf16-ceil-div4, version 1: round the final output’s UTF-16 code-unit count divided by four upward. This is not a provider tokenizer. |
| Externally supplied provider usage | The separate bee budget --measured command reads counters from an explicitly selected local Codex log. Delivery reports do not collect or reconcile those counters. |
| Savings, cost and adherence | Unmeasured. Neither output bytes nor estimates establish provider consumption, billing, savings, model adherence or quality. |
Read an existing observation
Section titled “Read an existing observation”An operator or agent can inspect what Bee successfully wrote before deciding which context to review. Let the existing Claude UserPromptSubmit hook run normally, then read its local metadata. There is no need to invoke a second hook to obtain a report: another output emission can create another event.
The default store is ~/.bee/usage/delivery-v1. With BEE_HOME, it is $BEE_HOME/.bee/usage/delivery-v1; BEE_HOME is the parent of .bee. Report and read require an explicit --store and run before configuration or update checks. They need no initialization, database, model or network connection.
delivery_store="${BEE_HOME:-$HOME}/.bee/usage/delivery-v1"bee delivery --helpbee delivery report --store "$delivery_store" --limit 100Start with totalsStatus, issues, deliveredEvents and deliveredUtf8Bytes. Only Delivered records contribute to byte and estimate totals. eventKinds also describes recorded write failures; a failed or partial write’s attempted size is not a count of delivered bytes. The estimate array keeps estimator IDs and versions separate.
totalsStatus: lower_bound means observations exist, not that the interval is complete. observationWindowComplete is always false; droppedObservationCount and measuredProviderTokens are null. Missing evidence is unknown, even when numeric counters are zero.
Find the relevant session and surface
Section titled “Find the relevant session and surface”| Question | Supported inspection and limit |
|---|---|
| Which output surface? | Inspect groups with dimension: surface: hook.prompt.plain or hook.prompt.context-json. There is no surface filter. Both are formats of the same prompt-hook surface. |
| Which session? | Use both --session-kind and --session. Native records use claude-native-session and the native UUID. In session groups, identity is the session ID and version is its identity kind. Matching is exact and case-sensitive. |
| Which source or recipe? | Native records have sourceRefHash: null and recipeHash: null. They are unknown and incomparable. The aggregate item steering-block, version 1, does not identify an individual rule or source revision. There is no source filter. |
| Which status? | Inspect eventKinds; inspect observation.observation.kind with read if an event UUID is already known. Native Withheld totals are explicitly unavailable: nativeWithheldEvents: null, nativeWithheldStatus: unavailable_no_native_producer. |
| Which time interval? | A known record has observation.observation.observedAtUtc, the UTC write-attempt observation time. Reports have no time-range filter, interval totals or event listing; they cannot establish a complete start/end window. |
The following UUID is synthetic. Replace it with the exact native session ID for your own observation:
bee delivery report --store "$delivery_store" \ --session-kind claude-native-session \ --session 11111111-1111-4111-8111-111111111111 --limit 100groups offers three views of the same delivered output: item, surface and session. Do not add their totals together. --limit limits groups across all three views, not events or input bytes; totals are calculated before that limit. The default and maximum are 100; 0 returns totals without groups. Check omittedGroups. If groups are omitted, increase a smaller limit or narrow to one known session and rerun. There is no continuation cursor or pagination; more than 100 groups cannot all be requested in one report. Do not sum overlapping reports.
read requires an already known nonzero event UUID in hyphenated form. Reports do not list event UUIDs, and the native hook does not print its append receipt. Use this only when an event ID has been supplied separately by a trusted producer or test receipt; it is not an event-discovery command. This synthetic UUID demonstrates the syntax and returns unavailable if absent:
bee delivery read --store "$delivery_store" \ --event 22222222-2222-4222-8222-222222222222A found response has status: recorded_observation; its observation contains the schema version, per-session sequence and nested observation metadata. This status does not itself mean the write was Delivered.
Try a valid offline empty report
Section titled “Try a valid offline empty report”This POSIX-shell example uses a new, empty temporary home and no services. It does not create a ledger or write internal store files. The CLI has no public append, import or synthetic-record command.
delivery_demo=$(mktemp -d)BEE_HOME="$delivery_demo" bee delivery report \ --store "$delivery_demo/.bee/usage/delivery-v1" --limit 0rmdir "$delivery_demo"The report command exits 5, as expected for unavailable evidence; the final rmdir cleans up the empty demo directory. These are selected fields from its actual JSON output:
{ "totalsStatus": "unknown", "observedEvents": 0, "deliveredEvents": 0, "deliveredUtf8Bytes": 0, "groups": [], "omittedGroups": 0, "issues": ["missing", "observation_window_open"], "observationWindowComplete": false, "measuredProviderTokens": null, "nativeWithheldEvents": null}This demonstrates an unknown observation window, not a measured zero-consumption session. A read of the synthetic event in an absent store likewise exits 5 with status: unavailable and observation: null.
Options, exits and bounds
Section titled “Options, exits and bounds”Output is JSON with a final newline; do not add --json to delivery commands. Supported forms are delivery --help, delivery report and delivery read only. There are no baseline/check, repair, reset or ledger-writing routes.
| Interface | Contract |
|---|---|
report |
Required --store PATH; optional paired --session-kind KIND --session ID; optional --limit 0..100. |
read |
Required --store PATH --event UUID; no report filters or limit. |
| Identity strings | 1–128 ASCII letters/digits or - _ . : /. Native session IDs are nonzero UUIDs; other identity kinds are not silently treated as Claude. |
| Invalid usage | Unknown, duplicate, missing or empty options are rejected. At most 16 arguments and 16384 UTF-16 code units across arguments. |
| Output bound | At most 262144 UTF-8 bytes of JSON, excluding the final newline. Overflow returns status: report_cap and exit 5, not partial JSON. There is no --budget option. |
| Exit 0 | Help, a report with at least one observed event, or a found event. Inspect issues and kinds: a verified prefix or failure-only report can still exit 0. |
| Exit 4 | Invalid usage. Correct the options before interpreting the result. |
| Exit 5 | No matching observations, unavailable event or output cap. Inspect JSON; this is not proof of zero delivery. |
Recording, privacy and failure limits
Section titled “Recording, privacy and failure limits”The native producer covers only the existing Claude UserPromptSubmit path, in plain text and context JSON. It requires a valid CLAUDE_CODE_SESSION_ID and an eligible JSON prompt envelope; a valid envelope session ID takes precedence. Raw or argument-only input, ambiguous/nested harness identity, malformed envelopes or envelopes over 65536 UTF-16 code units and non-UTF-8 output remain unobserved. Session-start, pre-tool, Codex and Hermes paths are not native delivery producers. Do not nest or manually repeat hook invocations to measure usage.
The ledger retains event/session IDs, surface and item identity, status, UTC timestamp, per-session sequence, byte count and named estimate. It does not store prompt/output bodies, body hashes, exception text or credentials. Metadata still reveals session identity, timing and volume: keep it local and review it before sharing. Checksums check metadata consistency, not authenticity.
Bee observes delivery only after writing and flushing the final output. This is not a transport ACK or proof that a model consumed it. Accounting failures preserve the primary hook output, diagnostic and exit behavior. The observer waits up to 100 ms for append, with at most one pending append per observer; a slow append may finish later. This does not impose a hard filesystem deadline. Busy stores, crashes, capacity and write failures can lose observations; loss markers do not count every loss.
The default store retains at most 2048 events (16 segments of 128). It retains IDs and stops appending at capacity rather than evicting old records. Exact replay of the same event ID and metadata is idempotent; conflicting replay preserves the first record. Separate invocations get new IDs. Neither this nor per-session ordering guarantees complete or exactly-once observation.
Reads use bounded regular files, refuse unsupported links/file shapes, and retain a verified prefix when corruption is found. Frame metadata is limited to 4096 bytes, plus its line ending; the header is bounded to 4096 bytes. Inspect issues for missing, busy, corrupt, capacity or I/O evidence. A prefix may be useful but is incomplete. There is no public resize, recovery or rotation command; do not edit internal files to manufacture observations or treat deletion as a continuation mechanism.
Keep three questions separate
Section titled “Keep three questions separate”bee context doctor inspects explicitly selected local context declarations before use; ordinary bee budget forecasts context size. Delivery accounting observes a small set of actual Bee output commits. The separate command below documents the offline reader for externally supplied Codex usage counters:
bee context doctor --helpbee budget --measured --help --jsonThat reader requires --harness codex, an exact native --session UUID and an explicit --log file. It keeps response and history streams separate; it does not attribute provider usage to a delivered rule or establish a bill. Do not add its counters to delivery estimates or infer savings from either.
See the command reference, hook setup, context tools and release notes.