Release v0.1.1 - #4
Merged
Merged
Conversation
anilmurty
force-pushed
the
release-v0.1.1
branch
from
April 6, 2026 22:35
681d3ff to
7ccec6b
Compare
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
anilmurty
force-pushed
the
release-v0.1.1
branch
from
April 6, 2026 22:38
7ccec6b to
f12cbfc
Compare
anilmurty
added a commit
that referenced
this pull request
Jun 19, 2026
#4: plain `tj onboard` honors --plan / prompts for plan tier
This was referenced Jun 19, 2026
HoomanDgtl
pushed a commit
to HoomanDigital/tokenjam
that referenced
this pull request
Jun 20, 2026
…an tier Plain `tj onboard` only prompted for daily budget and silently ignored `--plan`, so `[budget.<provider>] plan` was never written — breaking plan-aware dollar rendering and contradicting the docs. - The plain path now honors `--plan <tier>` non-interactively and prompts for it interactively (Claude-first: offers the Anthropic tiers). An OpenAI-only tier (plus/team/enterprise) is routed to `[budget.openai]`; everything else to `[budget.anthropic]`. Non-interactive with no `--plan` writes no plan section (no hang, no presumptuous default). - Confirmation line + CLAUDE.md wording updated to match. The `--claude-code` / `--codex` global integration flows are unchanged. Tests: --plan writes the right [budget.<provider>] section (api/max_5x → anthropic, plus → openai), no-plan non-interactive writes none, output is valid TOML. Full suite green (711); ruff/mypy clean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
HoomanDgtl
pushed a commit
to HoomanDigital/tokenjam
that referenced
this pull request
Jun 20, 2026
…Labs#157) The plan-written confirmation rendered "(written to )" because Rich interpreted the `[budget.<provider>]` TOML header as a markup tag and stripped it. Wrap the section name in rich.markup.escape() so it renders literally. Regression introduced by the Metabuilder-Labs#4 fix (plain onboard --plan). Adds a regression test asserting the message keeps the section header. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This was referenced Jun 20, 2026
anilmurty
pushed a commit
that referenced
this pull request
Jul 2, 2026
#4) Claude Code's built-ins leave a real, documented gap: /compact is reactive, lossy and single-session; /context shows current-session totals only. Neither attributes WHAT is burning quota across sessions nor suggests a structural fix. A whole DIY ecosystem (ccusage, codeburn, context-analyzer, session-recall, ...) has sprung up to fill it — the strongest revealed-demand signal. Proof point: anthropics/claude-code#24147, where a dev hand-parsed 30 days of JSONL to find CLAUDE.md re-reads consumed 99.93% of their quota. `tj context` runs a local diagnostic over Claude Code sessions and reports: 1. Per-turn context composition — what share of each turn went to RE-READING prior context (cache-read tokens: conversation history, CLAUDE.md, accrued tool output) vs. NET-NEW WORK (uncached input + output), with the re-read overhead named. 2. Recurring inclusions — the same file re-read across many sessions, frequency-counted, each with a concrete `@file` / CLAUDE.md structural fix (capture-gated on `[capture] tool_inputs`). 3. Compact candidates — sessions whose accumulated re-reading makes a mid-session /compact reclaim the most quota. Framing is quota-native (the subscription majority): headline numbers render as token-share / "% of cycle tokens" via core/framing.py — the single source of truth for plan-tier-aware rendering — for Pro/Max users. Dollars are a SECONDARY calibration signal for API users, never the headline. Output is a screenshottable terminal card; `--json` for machine-readable output. Honesty discipline (CLAUDE.md Rule 14): every figure is a measured token share or a structural candidate flag, never a guaranteed saving; re-read tokens are cache reads (billed at a reduced rate, not free) — real quota, stated as such. Needs a direct DuckDB connection (reads the raw `attributes` column, which the API shim doesn't expose) — fails gracefully with a `tj stop` hint when the daemon holds the lock, mirroring `tj report --trim`. Scoped OUT of v1 (named, not faked): MCP schema-injection attribution and prompt-cache-miss attribution aren't derivable from current backfill data; recurring-inclusion detection covers file Reads only. Per the #3 handoff, content lands only on freshly-ingested spans after enabling `[capture]` — the command surfaces that nudge rather than silently showing empty recurring data. Covered by tests/unit/test_context_diagnostic.py over a synthetic multi-session fixture: per-turn re-read-vs-work composition, cross-session recurring-inclusion detection with structural fix, compact-candidate detection, the capture-off nudge, and end-to-end CLI rendering of quota-share for a Max plan. Co-Authored-By: Claude <noreply@anthropic.com>
anilmurty
pushed a commit
that referenced
this pull request
Jul 2, 2026
…e reads #4's recurring-inclusion detection only covered file Reads (group by `file_path`, frequency-count across sessions, suggest `@file`/CLAUDE.md). Repeated prompts, repeated searches, and large repeated tool outputs also re-paste across turns/sessions and burn the same quota, but went undetected. Generalize the detector into one `(inclusion_type, tool_name, signature)` aggregation carrying a distinct-session set + occurrence count, then flag four kinds, each with a type-appropriate structural fix: * file reads (Read/View/Cat `file_path`) -> `@file` / CLAUDE.md; * searches (Grep/Glob/Search query/pattern) -> pin / capture the result; * prompts (identical `gen_ai.prompt.content` re-sent) -> save as a slash-command / CLAUDE.md note; * large tool outputs (identical `gen_ai.tool.output` >= 2K chars re-pasted) -> reference the artifact instead of re-running. Each kind is independently capture-gated by its `[capture]` toggle (tool_inputs / prompts / tool_outputs), so default-off behavior is unchanged and a flag-off kind contributes nothing. File reads / searches gate on distinct sessions (a single session re-reading a file isn't structural); prompts / outputs re-paste across turns within a session too, so they gate on raw occurrence count. Framing stays quota-native (#4). Tool outputs are only captured on the live ingest path, not the on-disk transcript — the nudge note says so. `RecurringInclusion` now carries `inclusion_type`; the CLI renders a per-kind tag and the JSON payload round-trips it. Extends the synthetic fixture to exercise recurring Grep, prompts, and large outputs, asserting each is detected with frequency + the structural fix, plus a size-gate test and a per-flag gating test. Co-Authored-By: Claude <noreply@anthropic.com>
anilmurty
pushed a commit
that referenced
this pull request
Jul 2, 2026
`tj context` (#4) named re-read overhead (cache reads) but not the two specific large sources #11 asked for: MCP schema-injection and prompt- cache-miss tokens. This ships the derivable half and parks the other with a precise note, keeping the honesty discipline (Rule 14) — no invented attribution numbers. Cache-miss (DERIVABLE): cache-creation tokens (NormalizedSpan.cache_write_ tokens, from the on-disk usage block's cache_creation_input_tokens) are input that missed the cache and had to be written to it, billed by Anthropic at a premium. They were already summed into total_cache_write_ tokens and the composition denominator but never named as their own overhead category — so the re-read and net-new-work shares silently failed to sum to 100% whenever cache writes were present. Now surfaced as a distinct `cache_miss` category: total_cache_miss_tokens / cache_miss_share on the diagnostic, cache_miss_tokens / cache_miss_share per turn, a new "Cache-miss:" breakdown line in the card (shown only when non-zero so default output is unchanged), and corresponding JSON fields. MCP schema-injection (~25K tok/call) (PARKED): not derivable from current data. Neither the on-disk transcript nor live spans carry per-tool / per-schema token attribution — tool-definition tokens are folded into input/cache-creation, and `mcp__`-prefixed names appear only on tool- invocation spans (no schema-injection token count). Surfaced as MCP_INJECTION_PARK_NOTE (a diagnostic note + a JSON field) naming exactly what data would be needed (a per-request tool-schema token delta) rather than fabricating a figure. Tests: extend the synthetic fixture so session B pays a cache-creation premium; assert the named cache-miss category is computed (core + per-turn + JSON), rendered in the card, and that the MCP half is parked with a precise note. Default-off behavior unchanged. Full suite green (1207 passed), ruff + mypy clean. Co-Authored-By: Claude <noreply@anthropic.com>
anilmurty
pushed a commit
that referenced
this pull request
Jul 2, 2026
Add `tj quota-audit` — the accountability companion to opusplan / `/model`. Those are forward-looking and say nothing about session history; nothing answered the backward-looking question "which of my PAST Opus sessions were Sonnet-shaped?". This runs the structural downsize heuristic retroactively, scoped to Opus sessions, and reports: - the headline "% of your Opus quota reclaimable from Sonnet-shaped sessions" computed as candidate-Opus-tokens / total-Opus-tokens — quota language, not dollars (the subscription majority is on a flat fee, so dollar framing mis-targets them; implied dollars are a secondary API-only calibration line); - the specific example sessions to spot-check; - an optional tuned routing-config export (`--export-config claude-code`, reusing the existing snippet generator via a DowngradeFinding shim). Framed as an audit (quota terms) with the honesty caveat always visible — "candidates to spot-check, never safe-to-downgrade". Computes purely from already-backfilled token/model metadata; does not depend on captured content. `audit_opus_quota()` + `OpusQuotaAudit` / `OpusAuditExample` extend model_downgrade.py / types.py; framing reuses core/framing (#4 pattern, window-independent plan mix per #177). Covered by a synthetic-mix test (Sonnet-shaped Opus candidates vs Opus-shaped Opus vs excluded Sonnet sessions) asserting the % reclaimable, the spot-check listing, and the caveat render. Co-Authored-By: Claude <noreply@anthropic.com>
anilmurty
pushed a commit
that referenced
this pull request
Jul 2, 2026
The "tokenmaxxing → tokenminimizing" cultural shift (June 2026) means a spend-brag card now repels while an efficiency/quota card aligns, and the subscription majority has no dollar spend to brag about at all. The old card rendered an (ironic) spend-tier ladder — the wrong polarity. Reframe the card to a quota/efficiency artifact: - Lead with the context-COMPOSITION headline from #4's compute_context_diagnostic: what share of quota went to overhead (re-reading history / CLAUDE.md / tool output) vs real work (uncached input + output). - Classify into 5 efficiency tiers keyed on the overhead share (lower = leaner = a better tier), replacing the 6-tier spend ladder. - Render quota-native via core/framing, mirroring #5's polarity: headline is a token-share / "% of cycle tokens"; dollars are demoted to a secondary "Implied API value" line shown only for api plans, suppressed for subscription / local / unknown. No dollar spend-brag for subscription users. - Frame the action line as reclaimable quota (points at tj context). - Add a --weekly "Quota Wrapped" recap preset (7-day window + recap copy). The card now needs a direct DuckDB connection (it reads context composition), matching tj context / tj quota-audit. Tests rewritten to assert the efficiency framing (composition + reclaimed, not spend-brag) and quota-native suppression of dollars for a subscription plan, plus weekly mode and the api secondary line. Updated the two forward-looking release checklists and CLAUDE.md to match. Co-Authored-By: Claude <noreply@anthropic.com>
anilmurty
pushed a commit
that referenced
this pull request
Jul 2, 2026
Distribution research (adoption.md) is blunt: 15-second-TTFV `npx` tools dramatically out-adopt 2-minute-install tools, and every high-star CLI in this niche has sub-30s time-to-first-value. TokenJam's `pipx install` + launchd/systemd daemon + onboarding is great for power users but measurably higher friction than `npx ccusage` for the Claude Code crowd — who reach for `npx` first and whose JSONL tj reads is the very same file ccusage parses. This ships a no-setup first-run path so a user with zero prior setup runs ONE command and sees where their Claude Code quota actually goes in well under 30s. - `tj quickstart` (cmd_quickstart.py): opens a transient InMemoryBackend (nothing written to ~/.tj, no config read/written, no daemon started or contacted), backfills ~/.claude/projects/*.jsonl into it, then renders quota composition (reusing #4's context_diagnostic engine) + a session timeline (new core/session_timeline.py). Output leads with ccusage-parity framing. Registered in `no_db_commands` so the CLI never opens the on-disk DB / trips the daemon lock for it. - Bare `tj` (no subcommand) routes to quickstart — the group is now `invoke_without_command=True`, so `uvx --from tokenjam tj` is one command. `--help`/`--version` are eager and still short-circuit. - `npm-wrapper/`: a dependency-free npm package named `tj` so `npx tj` works — a thin launcher that shells out to the Python CLI via the first available runner (uvx -> pipx run -> installed tj) and passes args through. NOT published here (build + document only). - Docs: README + docs/installation.md lead with `npx tj` / `uvx --from tokenjam tj` as the primary starting point; `tj onboard` stays the opt-in "go deeper" (daemon/MCP/live) path. Honesty discipline (Rule 14) preserved: every figure is a measured token share re-derived from the JSONL, never a projected saving. Tests: tests/unit/test_quickstart.py covers the timeline core, the CLI render, the JSON output, the no-logs branch, and that quickstart + bare `tj` never open the on-disk DB (open_db patched to raise). Validated with `make all` — ruff + mypy clean, full suite 1171 passed. `uvx --from <repo> tj` and the npm wrapper passthrough were exercised locally end-to-end. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
anilmurty
pushed a commit
that referenced
this pull request
Jul 2, 2026
… flags (#3) The Claude Code JSONL backfill parser recomputed cost from token/model metadata but never extracted per-message content or tool-input from the transcript — even though that data is present and core/transcript.py already reads it. Because backfill bypasses IngestPipeline/strip_captured_content, the [capture] toggles were a no-op on the CC path: flipping capture.prompts changed nothing. This blocked the context-cost diagnostic (#4), which needs per-message content + inclusion args to attribute tokens. parse_claude_code_session now accepts a CaptureConfig and, gated per toggle, populates the assistant LLM span with gen_ai.prompt.content (the triggering human prompt) and gen_ai.completion.content (the agent narration), and each tool span with gen_ai.tool.input (the raw args). The keys match GenAIAttributes so downstream consumers and alert content-stripping treat backfilled content identically to live content. ingest_claude_code reads config.capture and forwards it; iter_claude_code_sessions threads it through. Extraction is strictly opt-in: the None default and the all-False CaptureConfig default leave every span's attributes byte-for-byte unchanged ({"source": ...}), so a default backfill is unchanged and stays 100% local. Reuses _block_text from core/transcript.py for the record-walking. Co-Authored-By: Claude <noreply@anthropic.com>
anilmurty
pushed a commit
that referenced
this pull request
Jul 2, 2026
Enabling [capture] after a Claude Code session is already ingested never landed message content / tool_input on the existing rows: the idempotent INSERT skips on span_id conflict, and the --reingest path updated only sub_agent_id, leaving the attributes column untouched. So #4's recurring-inclusion detection (which reads that content) only worked against a fresh DB. The --reingest UPDATE now also overlays the freshly-parsed span's attributes over the stored ones (parsed wins per key) via a small _merge_attributes helper. This ADDS the content keys (gen_ai.prompt.content / completion.content / tool.input) without discarding any keys the stored row already carried (e.g. from live ingest). Capture-off reingest stays a no-op — the parsed attributes are just {"source": ...}, which the stored row already has — so it never wipes content a prior capture-on backfill stored. Two tests added: (1) ingest with capture OFF, enable capture, re-run with --reingest -> existing spans now carry content/tool_input, no fresh DB, no new rows; (2) a capture-off --reingest does not delete previously stored content. Co-Authored-By: Claude <noreply@anthropic.com>
anilmurty
pushed a commit
to tarun73/tokenjam
that referenced
this pull request
Jul 3, 2026
…s running `tj context` is the launch-hero command (issue Metabuilder-Labs#4 wedge), but the composition diagnostic reads the raw `attributes` column for recurring-inclusion detection — data the API shim never exposed. So whenever `tj serve` held the DuckDB write lock, the CLI fell back to `ApiBackend` (no `.conn`) and refused to run, telling users to stop the daemon on the exact command the launch drives them to. DuckDB permits only one writer OR many readers across processes (a concurrent read-only conn alongside the serve write-lock raises an IOException), so a client-side read-only workaround isn't available. Route the compute through the daemon instead — which already owns the direct connection — mirroring `/api/v1/reuse/clusters` (Metabuilder-Labs#154) and `/api/v1/optimize` (Metabuilder-Labs#68): * new `GET /api/v1/context` endpoint computes the diagnostic server-side (incl. recurring inclusions from raw `attributes`) plus a plan-tier `framing` block, exactly as the CLI's direct-conn path does * new `diagnostic_from_dict` inverse of `diagnostic_to_dict` so the CLI reconstructs the dataclass and renders identically through serve * `cmd_context` shim path: on `ApiBackend` (no `.conn`), fetch + render via `_render_via_serve`; on a truly non-conn/non-Api backend, still surface a clean error (guards on `isinstance(db, ApiBackend)`) Covered by `tests/integration/test_context_serve.py`: * endpoint computes diagnostic server-side, including the recurring file-read only surfaceable from raw `attributes` * `tj context` (plain + `--json`) renders through an in-process ASGI-wired `ApiBackend` — the exact daemon-is-running state * a non-conn/non-Api backend still errors cleanly (no traceback) Co-Authored-By: Claude <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Bump version to 0.1.1 with changelog covering all changes since v0.1.0-alpha.
Fixed
ocw exportempty output (corrupted DuckDB span indexes)ocw statusshowing?for completed sessionsocw statusshowing$0.000000cost (date.today vs UTC mismatch)ocw costspurious zero-cost row from session spansAdded
ocw traceChanged
@openclawwatch/sdkTest plan
v0.1.1publish-pypi.ymltriggers and publishes to PyPI with updated metadata🤖 Generated with Claude Code