claude-obsidian: meter and cap usage; cut per-session cost ~5.6x
The user asked for usage to be monitored closely, and measuring it turned up that most of the spend was avoidable. Metering: every model call is appended to usage.jsonl with BILLED tokens (modelUsage -- the visible `usage` turn undercounted by half) and the CLI's list-price cost. `usage` reports 5h/24h/7d. Each call's cost is estimated first and refused if it would cross the per-run or rolling 24h budget, so budgets cannot be overshot. Removed --max-budget-usd: it aborts after spending and discards the result ($0.26 lost in one call). Cost, measured on one session ($0.057 -> $0.010, same summary content): - alwaysThinkingEnabled=false: extended thinking was ~85% of output. - DISABLE_PROMPT_CACHING=1: one-shot prompts were being written to the 1h cache at 2x input price. - CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1: a hidden side request re-read the whole prompt, doubling billed input (9,638 vs 4,663). Summaries are cached until their note is written, so a vault failure never re-pays; --prefetch summarizes while the vault is unreachable. Offline tests (fake claude binary): budget refusal pre-flight, cache reuse with zero calls, map-reduce, env/argv levers, billed-token ledger. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KF322NzozeaFjpgWvh4F4g
This commit is contained in:
@@ -36,6 +36,8 @@ claude.ai export .zip ────────┼─ condense → redact → sum
|
||||
claude-obsidian-sync sync # what the timer runs
|
||||
claude-obsidian-sync sync --session <session-id> # one session, now, ignoring the settle window
|
||||
claude-obsidian-sync import-claude-ai ~/Downloads/data-2026-09-13.zip
|
||||
claude-obsidian-sync sync --prefetch --limit 3 # summarize into the local cache, vault untouched
|
||||
claude-obsidian-sync usage # calls, billed tokens, spend: last 5h / 24h / 7d
|
||||
```
|
||||
|
||||
Claude reads the vault through the plugin's MCP server:
|
||||
@@ -53,6 +55,22 @@ claude mcp add --scope user --transport http obsidian http://<host>:27123/mcp/ \
|
||||
subscription has no key of its own, so a background job cannot use its `claude-*` models.
|
||||
- **`--no-session-persistence` is load-bearing.** Without it every summary writes a new
|
||||
transcript into `~/.claude/projects`, and the next run summarizes its own summarizing.
|
||||
- **Usage is metered and capped.** Every model call is appended to
|
||||
`~/.local/state/claude-obsidian/usage.jsonl` with *billed* tokens (the CLI's `modelUsage`, not
|
||||
the visible turn) and `total_cost_usd` — API list-price equivalent, a faithful proxy for how much
|
||||
was consumed; the plan's own meter is only visible in Claude Code's `/usage`. Before each call
|
||||
its cost is **estimated** (+20% margin) and the call is refused if it would cross
|
||||
`BUDGET_USD_PER_RUN` or the rolling `BUDGET_USD_PER_DAY` — so budgets are never overshot. Not
|
||||
`claude -p --max-budget-usd`: that aborts *after* the tokens are spent and discards the result
|
||||
(measured: $0.26 for nothing). Every run ends with a one-line usage report.
|
||||
- **Three cost levers, measured on one session — $0.057 → $0.010, same summary content:**
|
||||
`alwaysThinkingEnabled=false` (extended thinking was ~85% of output tokens),
|
||||
`DISABLE_PROMPT_CACHING=1` (the CLI writes each prompt to the 1-hour cache at 2× input price, and
|
||||
a one-shot call never reads it back), and `CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1` (otherwise a
|
||||
hidden side request re-reads the entire prompt, doubling billed input). A whole ~110-session
|
||||
backlog is about $2 at list price with all three.
|
||||
- **Summaries are cached until their note is written**, so a vault outage never pays for the same
|
||||
summary twice, and `--prefetch` can do the summarizing while the vault is unreachable.
|
||||
- **It shares your plan's usage limits.** A first backfill of ~100 sessions in parallel hit a
|
||||
session limit within minutes — which also limits *interactive* use. So: one job at a time,
|
||||
`MAX_PER_RUN` sessions per run (newest first), and the run **stops at the first usage-limit
|
||||
|
||||
Reference in New Issue
Block a user