# BUILD PROMPT — Prompt Thermometer

## TASK
Build a tool that measures the **real per-message token cost** that Claude Code
injects into the prompt for a given session/project — not file bytes, not char÷4
estimates. Output a per-source breakdown and a total "context floor" (the tokens
spent before the user types anything).

## TONE
Accuracy over convenience. Every number must be measured or flagged. Never report a
char÷4 estimate as a token count without labeling it "est." A confident wrong number
here is worse than a flagged unknown — this tool exists because two sessions disagreed.

## STATIC BACKGROUND (what's already known — do not re-derive)
The injected context per message is NOT just a file's bytes. It is the file content
PLUS harness wrapping. Confirmed sources that contribute to the floor:

1. User-global  `~/.claude/CLAUDE.md`            (measured: 6,299 chars on disk)
2. Project-local `<project>/.claude/CLAUDE.md`    (measured: 2,177 chars on disk for j:\AI\Claude Code)
3. `MEMORY.md` index (auto-memory)                (~5,600 chars)
4. Injected skill `description` blocks            (one per available skill, every message)
5. Injected MCP tool/server descriptions          (per connected server)
6. Harness envelope                                (the `# claudeMd` framing, path headers,
                                                    `<system-reminder>` tags, deferred-tool lists)

KEY DISTINCTION the tool must make explicit:
  - FILE BYTES        = what `wc -c` reports for a file
  - INJECTED PAYLOAD  = file content + wrapper, as it actually appears in the prompt
  - TOKENS            = the injected payload run through a real tokenizer
A 2,177-char file does NOT cost 2,177 chars in context — the wrapper inflates it.
This gap is the whole reason the tool exists.

TOKENIZER RULE:
  Use Anthropic's real count — `/v1/messages/count_tokens` or the SDK's token counting —
  NOT len(text)/4. The char÷4 heuristic may be shown as a SECONDARY column labeled "est."
  for sanity, never as the primary number.
  API key lives in `_shared/env/.env` (ANTHROPIC_API_KEY). Never commit it.

STACK: Python 3.10+, `uv` for deps, `pathlib` over os.path. (House convention.)

## STRUCTURE TO BUILD

Projects/prompt_thermometer/
README.md                  # what it measures + the bytes/payload/tokens distinction
pyproject.toml             # uv-managed
src/
sources.py               # locate & read each injected source (the 6 above)
wrap.py                  # reconstruct the harness envelope per source (best-effort, documented)
tokenize.py              # real Anthropic count_tokens; char÷4 as labeled fallback
measure.py               # orchestrate: per-source bytes, payload, tokens
report.py                # render the table + floor total
tests/
test_tokenize.py         # known-string → known token count (lock the tokenizer)
test_sources.py          # fixture files → expected byte counts
output/                    # generated reports, git-ignored



## STEP-BY-STEP
1. **Locate sources.** Resolve the 6 source paths for a target project (default: this
   project; accept a `--project <path>` arg to scan others — that's the "scan other
   projects" capability from the project brief).
2. **Measure file bytes.** `wc -c` equivalent per file. This is the floor's lower bound.
3. **Reconstruct injected payload.** For each source, wrap it as the harness does
   (framing + headers + reminder tags). Where the exact wrapper can't be observed,
   document the assumption in `wrap.py` and mark that portion "approximate."
4. **Tokenize for real.** Run each payload through Anthropic count_tokens. Cache results
   by content hash so repeat runs are cheap.
5. **Self-audit first.** Run against THIS project before any other — print its own floor.
   (The brief says "self-audits then scans other projects.")
6. **Report.** Emit the table + total. Flag every estimate vs measured value.

## EXAMPLES (tricky cases to handle correctly)
- A skill with a 1,200-char `description` injected every message can cost MORE per
  session than the project CLAUDE.md. The report must surface skill/MCP descriptions
  as first-class sources, not lump them into "other."
- `wc -c` on a UTF-8 file with accented chars (é, ñ, ·) counts BYTES not characters —
  "Pablo Chea — Operating Identity" has multibyte chars. Report both byte count and
  codepoint count where they diverge, so the numbers are unambiguous.
- If `ANTHROPIC_API_KEY` is missing/offline, the tool must NOT silently fall back to
  char÷4 and present it as truth — it must FAIL LOUD or clearly label the entire run
  "ESTIMATED (no tokenizer)."

## REMINDERS
- Report measured numbers only. Label every estimate "est." Flag anything unverified.
- Never commit `.env`. Read the key from `_shared/env/.env`.
- The deliverable is the number that hits the token budget per message — the FLOOR —
  broken down by source so the user can see what to cut.

## OUTPUT FORMAT
A single report (stdout + `output/floor-report.md`):

  PROMPT THERMOMETER — <project name>
  tokenizer: anthropic count_tokens | est(char/4)   ← which was used

  SOURCE                        BYTES    PAYLOAD    TOKENS
  user-global CLAUDE.md         ...      ...        ...
  project CLAUDE.md             ...      ...        ...
  MEMORY.md                     ...      ...        ...
  skill descriptions (N)        ...      ...        ...
  MCP descriptions (N)          ...      ...        ...
  harness envelope              ...      ...        ...
  ─────────────────────────────────────────────────────
  CONTEXT FLOOR (per message)            ...        ... tok

  FLAGS: <every estimated/approximate value listed here>
