import sys
import os
import argparse
def count_openai(text: str) -> int | None:
try:
import tiktoken
enc = tiktoken.get_encoding("o200k_base") return len(enc.encode(text))
except ImportError:
return None
def count_claude(text: str) -> int | None:
api_key = os.environ.get("ANTHROPIC_API_KEY")
if not api_key:
return None
try:
import anthropic
client = anthropic.Anthropic(api_key=api_key)
resp = client.messages.count_tokens(
model="claude-sonnet-4-20250514",
messages=[{"role": "user", "content": text}],
)
return resp.input_tokens
except Exception:
return None
def main():
parser = argparse.ArgumentParser(description="Count tokens with real tokenizers")
parser.add_argument("--file", "-f", help="Read input from file instead of stdin")
parser.add_argument("--openai", action="store_true", help="OpenAI count only")
parser.add_argument("--claude", action="store_true", help="Claude count only")
args = parser.parse_args()
if not args.openai and not args.claude:
args.openai = True
args.claude = True
if args.file:
with open(args.file, "r", errors="replace") as f:
text = f.read()
else:
text = sys.stdin.read()
openai_count = count_openai(text) if args.openai else None
claude_count = count_claude(text) if args.claude else None
if args.openai and not args.claude:
print(openai_count if openai_count is not None else "N/A")
elif args.claude and not args.openai:
print(claude_count if claude_count is not None else "N/A")
else:
o = str(openai_count) if openai_count is not None else "N/A"
c = str(claude_count) if claude_count is not None else "N/A"
print(f"{o}\t{c}")
if __name__ == "__main__":
main()