Measure your own project
Every figure here is reproducible. This is the script that does it.
The calculator estimates from published figures. This measures your actual project: your CLAUDE.md, your skills, your MCP servers, as they are configured right now.
What it does
It starts throwaway sessions that say nothing but "Reply with only: OK", one in an empty temporary directory and one in your project, then subtracts the reported token counts. The difference is what your configuration costs at startup.
It does not modify anything and does not read the contents of your project files. It measures the byte size of your user-level CLAUDE.md (see below), creates one temporary directory, and deletes it on exit. You need claude andjq on your PATH.
It separates project config from global config
A user-level CLAUDE.md loads into every session, including the empty baseline, so it cancels out of the subtraction and is invisible in the project figure. That matters because it is often the larger number: on the machine these measurements were taken, the global file was worth 26,763 tokens against a couple of thousand for the project.
The script therefore reports it separately, estimated from file size at 0.368 tokens per byte. The project figure stays a true measurement; the global figure is an estimate and is labelled as one.
It measures its own noise floor first
The reported baseline drifts by a couple of hundred tokens over a session, which is larger than the entire cost of a small configuration. So the script measures the empty baselinetwice and treats the gap as that run's noise floor. If your configuration costs less than the floor, it says so instead of printing a precise-looking number.
This matters more than it sounds. An earlier version reported−139 tokens for an empty project, which is obviously wrong and would make you distrust every other number it printed. A measurement smaller than its own noise is not a measurement.
The script
Read it before you run it. Copy it into a file and run bash measure-context.sh, optionally with a path. It is also served at/measure-context.sh, but piping a URL straight into a shell is a bad habit and this page will not encourage it.
#!/usr/bin/env bash
# Measure what YOUR Claude Code project costs in startup context.
#
# What it does: starts two throwaway sessions that only say "Reply with only: OK",
# one in an empty temporary directory and one in your project, and subtracts the
# reported token counts. The difference is what your configuration costs.
#
# It does not modify anything and does not read the contents of your project
# files. It does check the byte size of your user-level CLAUDE.md, since that
# loads into every session and is otherwise invisible to the diff. It creates
# one temporary directory and deletes it on exit.
#
# Requires: claude, jq. Usage: bash measure-context.sh [path-to-project]
set -uo pipefail
PROJECT="${1:-$PWD}"
command -v claude >/dev/null || { echo "error: 'claude' not found on PATH" >&2; exit 1; }
command -v jq >/dev/null || { echo "error: 'jq' not found on PATH" >&2; exit 1; }
[ -d "$PROJECT" ] || { echo "error: not a directory: $PROJECT" >&2; exit 1; }
TMP="$(mktemp -d)"
trap 'rm -rf "$TMP"' EXIT
# Total prompt tokens for one trivial turn = fresh input + cache written + cache read.
# Reading .usage this way counts the whole prompt regardless of cache state, which
# is what makes the two measurements comparable.
measure() {
( cd "$1" && claude -p 'Reply with only: OK' --output-format json </dev/null 2>/dev/null ) \
| jq -r '(.usage.input_tokens // 0)
+ (.usage.cache_creation_input_tokens // 0)
+ (.usage.cache_read_input_tokens // 0)'
}
# The reported baseline drifts by a couple of hundred tokens over a session, so
# measure it twice. The gap between the two is this run's noise floor, and any
# result smaller than it is not a measurement.
echo "measuring an empty baseline (twice, to find the noise floor)..."
BASE1="$(measure "$TMP")"
BASE2="$(measure "$TMP")"
echo "measuring $PROJECT ..."
MINE="$(measure "$PROJECT")"
case "$BASE1$BASE2$MINE" in
*[!0-9]*|'') echo "error: could not read token usage; run 'claude -p hi --output-format json' to debug" >&2; exit 1 ;;
esac
BASE=$(( BASE1 < BASE2 ? BASE1 : BASE2 ))
NOISE=$(( BASE1 > BASE2 ? BASE1 - BASE2 : BASE2 - BASE1 ))
[ "$NOISE" -lt 50 ] && NOISE=50
OVERHEAD=$(( MINE - BASE ))
# A user-level CLAUDE.md loads into every session, including the "empty"
# baseline, so it is invisible to the diff above. Surface it, because it is
# often larger than the project config being measured.
USER_MD="${CLAUDE_CONFIG_DIR:-$HOME/.claude}/CLAUDE.md"
USER_BYTES=0
[ -f "$USER_MD" ] && USER_BYTES=$(wc -c < "$USER_MD" | tr -d ' ')
printf '\n %-34s %s\n' "empty project baseline" "$BASE"
printf ' %-34s %s\n' "your project at startup" "$MINE"
printf ' %-34s +/-%s\n' "measurement noise this run" "$NOISE"
if [ "$OVERHEAD" -le "$NOISE" ]; then
printf ' %-34s %s\n\n' "your configuration costs" "below the noise floor"
echo " Your project adds less context than this run can reliably measure."
echo " That means your configuration is close to free, which is a good result."
printf '\n'
else
printf ' %-34s %s\n\n' "your configuration costs" "$OVERHEAD"
fi
if [ "$USER_BYTES" -gt 0 ]; then
# 0.368 tokens/byte, measured on a real 72,783-byte instruction file. Dense
# structured markdown tokenises worse than prose, which sits nearer 0.26.
awk -v b="$USER_BYTES" 'BEGIN{
printf " %-34s ~%d tokens (%d bytes)\n", "your user-level CLAUDE.md", 106 + b*0.368, b
}'
echo " Counted inside the baseline, not in the project figure above,"
echo " because it loads in every project. Estimated from file size."
printf '\n'
fi
# Each tool round trip re-sends the whole context, and the context grows as
# results accumulate, so a session costs far more than its startup figure.
# Model validated against measured runs to within 0.45%. See the article below.
for TRIPS in 1 20 100; do
awk -v s="$MINE" -v n="$TRIPS" 'BEGIN{
r = 3000 * 0.35; t = 0
for (k = 0; k <= n; k++) t += s + r * k
printf " %-34s %d tokens (%.1fx startup)\n", n " round trips, 3KB results", t, t / s
}'
done
cat <<EOF
Assumes an average 3KB tool result. Your numbers will differ; the shape will not.
Method and published figures: https://aieveryminute.com/method/
EOF
Checking it against the published figures
Run against a project with an 8,025-byte CLAUDE.md and nothing else, the script reports 2,154 tokens of configuration cost. Thepublished figure for an 8KBCLAUDE.md is 2,185 tokens, measured separately. The two agree to within 1.4%, which is about what the noise floor allows.
If your run disagrees with something published here by more than that, it is worth knowing about. There is a correction form at the bottom of every article.