Deep Dive macOS April 29, 2026 · 16 min read

I Built an App to Steal $50M Back from Claude Code

How I cut my Claude Code bill from $180 to $31/month — and what the Agent Monitor revealed about how AI coding tools actually waste your money.

The 35% Problem

I pulled three months of Claude Code session logs and analyzed them. The result was uncomfortable.

"Could you please help me with…"
"If it's not too much trouble…"
"I was wondering if you might be able to…"
"What I'd like you to do here is just…"

Roughly 35% of my input tokens went to content that provided zero signal to the model. I was talking to Claude like a nervous intern I didn't want to offend. Claude doesn't have feelings. It doesn't try harder because you said "please." The politeness tax is 100% yours.

Token Waste Visualizer analyzing...

Your prompt, tokenized:

Wasted (noise) Signal (kept)

Claude Sonnet 4.5 is priced at $3 per million input tokens. But that's not the number that matters. Every message in a long session re-sends the entire conversation history. Message 50 costs 200 tokens plus 49 previous messages. Context compounds. That 35% noise compounds with it.

35%avg. token waste
$180→$31monthly bill reduction
11×same file re-read in one session

What Terse Is — and What It's Built With

Terse is a macOS application that sits between your keyboard and your AI tools. It reads what you're typing, compresses it locally, and replaces it before you send. No servers. No third parties. Your prompts never leave your machine.

One thing worth getting right immediately: Terse is not an Electron app. It's built on Tauri — a framework that uses Rust for the backend and the system's native WKWebView for the frontend.

Using Rust wasn't aesthetic. The performance requirements for real-time text processing, file system watching, and process introspection made a compiled systems language the right call. The NLP optimizer runs in a Node.js sidecar, but all system-level operations — agent monitoring, capture pipeline, IPC — are native Rust.


How Text Capture Works: The terse-ax Swift Helper

The core challenge: reading from and writing to arbitrary third-party apps requires access to their text fields — owned by other processes. On macOS, the answer is the Accessibility API.

Terse ships a compiled Swift binary called terse-ax. When Terse starts, Rust resolves the path from the Tauri bundle structure:

// Contents/MacOS/ — main binary
// Contents/Resources/terse-ax — Swift helper
let r1 = contents_dir.join("Resources/terse-ax");
if r1.exists() { return r1.to_string_lossy().to_string(); }

On first run, two things happen automatically:

// Remove macOS quarantine (set on all DMG-installed binaries)
Command::new("xattr").args(["-dr", "com.apple.quarantine", &path]);

// Ensure executable bit is set
Command::new("chmod").args(["+x", &path]);

Without quarantine removal, Gatekeeper would block the Swift helper even after the user grants accessibility permissions — a common DMG distribution pitfall.

terse-ax · Accessibility Capture Pipeline live
1Get frontmost app (JXA + NSWorkspace)
2Traverse AX element hierarchy
3Find AXTextArea / AXTextField
4Read via AXValue
5Run 7-stage optimizer
6Write back via AXValue (fallback: Cmd+A Cmd+V)
VS Code / Canvas edge case: Electron-based editors render on Canvas — AX can't read it. Terse falls back to selection capture (Cmd+C → compress → Cmd+V). The UI shows which method is active.

The 7-Stage Compression Pipeline

Before any compression logic runs, a three-stage spellcheck fires first.

Spellcheck Pipeline (runs before everything)

Spellcheck — 3 Stages live
TYPOS Dict
Norvig Edit-Distance
QWERTY Proximity
nspell / Hunspell
what shoudl I do to deplpy my databse to producton

Stage 1 — Hardcoded TYPOS dictionary (~600 entries). O(1) lookups for the most common developer typos: fucntion → function, algortihm → algorithm, databse → database. A TECH_WORDS allowlist (~100 entries: async, jwt, kubernetes…) prevents downstream stages from mangling valid tech vocabulary.

Stage 2 — Norvig edit-distance with QWERTY proximity weighting. Generates candidate corrections at edit distance 1–2, filters to known words, ranks by frequency. The QWERTY weight means teh scores higher confidence than zeh as a correction of the — adjacent-key errors are structurally more likely.

Stage 3 — nspell (Hunspell-backed). Same dictionaries as Firefox and LibreOffice. Catches anything the first two stages miss.

The 7 Compression Stages

After spellcheck, code blocks are extracted and vaulted (restored verbatim at the end). Then compression runs:

7-Stage Optimizer — Normal Mode ready
1Spell Correction
2Whitespace Normalization
3Pattern Optimization (130+ rules)
4Redundancy Elimination
5NLP Analysis — filler + hedging
6Aggressive Compression
7Final Cleanup
Could you please help me refactor this function? I was wondering if you might be able to improve it. It's basically a utility that just handles user authentication.
ModeReductionWhat it removesBest for
🟢 Soft 5–15% Contractions, verbose phrases, filler adverbs, greetings Precise technical conversations
🟡 Normal 20–35% Politeness wrappers, meta-language, hedging, redundancy Daily coding — default mode
🔴 Aggressive 40–70% Articles, prepositions, markdown, all social scaffolding Batch Agent tasks, pipelines

The Agent Monitor: Where the Real Money Is

Prompt compression is linear savings. The Agent Monitor catches geometric waste — the kind that can run up hundreds of turns before you notice.

When a Claude Code session runs long, the context window fills. At high fill percentages, agents start thrashing: re-reading files already processed, re-calling tools used 20 steps ago, generating filler text to "stay busy." This is invisible in a terminal — tool calls scroll by, costs accumulate silently.

Session File Discovery (Rust)

Claude Code stores every session as a JSONL file under ~/.claude/projects/<encoded-cwd>/. The directory name is the working directory with / replaced by -. Terse finds the right session by:

// 1. lsof to get CWD of every running 'claude' process
Command::new("lsof").args(["-c", "claude", "-a", "-d", "cwd", "-Fn"])

// 2. Encode CWD to match Claude's project dir naming
let encoded = cwd.replace('/', "-");

// 3. Prefer the session matching the focused terminal
// (highest PID = most recently started claude process)
if is_focused && !was_focused { true }   // focused wins over recency
else if mtime > prev_mtime { true }       // recency as tiebreaker

What the JSONL Parser Tracks

Agent Monitor — Claude Code · claude-sonnet-4-6 ● live
0 total tokens
$0.000 est. cost
0 tokens / min
0 duplicate calls
Context fill 0%
Tool call log

Duplicate detection uses a hash of tool_name + first 100 chars of input. If a hash is already in the seen set, the call is flagged:

let cache_key = format!("{}:{}", name, input_prefix);
if !self.tool_call_hashes.insert(cache_key) {
    // Already seen this tool+input combo — flag it
    self.duplicate_tool_calls += 1;
}

Redundant file reads are tracked separately with a HashMap<String, u32> — any file with count ≥ 2 is flagged. Wasted tokens estimated at ~800 per redundant read (average file size in a typical project).

Tool Result Compressibility

Not all tool output is equally dense. Terse estimates how compressible each tool's results are:

Tool Result Compressibility Estimates RTK analysis
Bash
60–90%
Glob
50–70%
Read
40–60%
Grep
40–50%
WebFetch
30–40%
Agent
~25%

Bash output is most compressible: git logs, test runners, build output — lots of structure that tokenizes poorly but compresses well.

Multi-Agent Support

The monitor isn't Claude Code-specific. Terse detects any of these agents automatically:

AgentDetection MethodParser
Claude Code 🤖lsof CWD → ~/.claude/projects/ JSONLclaudeCode
Cursor Agent 📝Process scan (Cursor Helper) + ~/.cursorgeneric
Cline 🔍VS Code extension storage mtimegeneric
Windsurf 🏄Process scan (Windsurf Helper) + ~/.windsurfgeneric
Aider 🔧Process scan (aider)generic
OpenAI Codex 🧠~/.codex/sessions mtimecodex
Copilot CLIProcess scan (ghcs, copilot-cli)generic

For VS Code extensions (Cline, Copilot Chat) with no standalone process, Terse checks whether the extension's storage directory has been recently modified — a modification means the extension is active.


Actual Results

My Claude Code monthly spend: $180 → $31 over three months of daily use.

Savings driverTypeMechanism
Prompt compressionLinearNormal mode, 20–35% per message × thousands of messages
Interrupted degenerate sessionsNon-linearAgent Monitor flags thrashing → /compact or restart
Behavior changeCompoundingLive token counter changes how you write prompts
💡
The meter is motivating. When you watch a live token counter tick up with every turn, you write differently. You use /compact earlier. You start fresh sessions more readily. A monthly invoice tells you nothing actionable. A live counter changes behavior.

Honest Limitations

LimitationWhy
macOS onlyAX API is mature and consistent on macOS. Windows UIA is unreliable across Electron apps. Roadmap.
No browser-terminal Claude CodeDesktop client and VS Code terminal only. Browser-based terminal isn't AX-readable.
Aggressive mode loses precisionBy design. For batch Agent automation, not nuanced technical discussions.
Agent Monitor requires local Claude CodeReads ~/.claude/projects/ JSONL. Remote/SSH sessions not watched.

Why Tauri and Not Electron

A background tool that quietly consumes 300 MB of RAM and 15% CPU is one that gets force-quit. Terse runs alongside Claude Code, Cursor, and whatever else you have open — it can't be the memory hog.

Tauri eliminates bundled Chromium by using WKWebView. The Rust backend handles all system-level operations with memory-safe compiled code. The app binary is ~6 MB, starts in under half a second, and idles at 15–30 MB — numbers that matter when your AI tools are already hungry.


The Economics of Prompt Hygiene

Most advice about AI productivity focuses on outputs: better prompts, better responses. Almost none focuses on the input side — what you're actually sending, how much is noise, what that noise costs at scale.

Heavy AI users send millions of tokens per month. At those volumes, 35% waste is a real number. Fixing it doesn't require understanding transformer architecture. It requires acknowledging that habits built for human communication don't apply to language models — and running a tool that enforces that awareness automatically.

Free for 30 Days — Unlimited Access

Full access, no limits, no credit card. Every feature unlocked for 30 days. Install, watch your bill.

30 days free · Unlimited access · No credit card required · $4.99/mo after trial