---
title: '@runic-labs/ledger'
description: >-
  Contabilidade somente de acréscimo dos tokens gastos versus os tokens
  economizados.
sidebar:
  order: 5
---
`@runic-labs/ledger` é pura contabilidade — ele nunca impõe um orçamento, nunca recusa uma chamada, nunca estima um custo que você não informou. Ele responde a uma pergunta: *quanto a resolução dessas decisões realmente custou, e quanto disso foi evitado pela reutilização?*

```package-install
npm i @runic-labs/ledger
```

## `createLedger(store?)`

```ts
import { createLedger, FileLedgerStore, defaultLedgerFilePath } from "@runic-labs/ledger";

const ledger = createLedger(new FileLedgerStore({ filePath: defaultLedgerFilePath() }));
```

Por padrão, usa um `FileLedgerStore` em `.runic/ledger.json` (ou `$RUNIC_HOME/ledger.json`) caso nenhum armazenamento seja fornecido.

| Prop | Type | Default | Description |
| - | - | - | - |
| `recordMiss(signature, tokensSpent)?` | `void` | - | Logs a cache miss — the agent generated its own way and spent tokensSpent. |
| `recordHit(signature)?` | `void` | - | Logs a cache hit, recording the same tokensSpent as the original miss for this signature. |
| `summary()?` | `LedgerSummary` | - | Aggregated totals — see below. |
| `all()?` | `LedgerEvent[]` | - | The full raw event log. |
| `clear()?` | `void` | - | Removes all events. |

## `LedgerSummary`

```ts
interface LedgerSummary {
  totalSpent: number;
  totalSaved: number;
  hitsBySignature: Record<string, number>;
}
```

```ts
const summary = ledger.summary();
const totalHits = Object.values(summary.hitsBySignature).reduce((a, b) => a + b, 0);
const tokensWithoutRunic = summary.totalSpent + summary.totalSaved;
const savingsPercent = Math.round((summary.totalSaved / tokensWithoutRunic) * 100);
```

Este é exatamente o cálculo que tanto `benchmarks/openrouter-savings` quanto `benchmarks/reuse-sweep` usam para imprimir seus números finais — consulte [Benchmarks](/benchmarks).

## Por que `recordHit` não recebe um argumento `tokensSpent`

O valor de um acerto é definido como *o que quer que o erro original dessa assinatura tenha custado* — o registro consulta isso por conta própria, em vez de confiar que o chamador o repita corretamente a cada acerto. Se não houver um erro anterior para uma assinatura que, de alguma forma, esteja sendo acertada (isso não deveria acontecer no uso normal, mas o registro não presume que não possa), ele registra `0` em vez de adivinhar.

## Backends de armazenamento

O mesmo padrão de `@runic-labs/cache`: `MemoryLedgerStore` para testes e execuções efêmeras, `FileLedgerStore` para persistência entre invocações separadas de processos. Implemente você mesmo a interface `LedgerStore` para um backend diferente:

```ts
interface LedgerStore {
  append(event: LedgerEvent): void;
  all(): LedgerEvent[];
  clear(): void;
}
```

## Próximo

- [Cache](/cache) — o armazenamento correspondente indexado por assinatura
- [CLI](/cli) — `runic ledger status` lê este resumo pela linha de comando
