← back to blog

The cost of context: how a pricing change led me to add embeddings and structural graphs to my dev CLI

I've been working on a project since 2020: IUNCI, a Local-First POS and inventory system for SMBs in Latin America. Over time it grew past 40 tables, multiple services distributed between Windows and WSL, and an architectural migration that ended up being the catalyst for everything that followed.

The real story of void-stack — from simple project launcher to local GraphRAG in two months.


I’ve been working on a project since 2020: IUNCI, a Local-First POS and inventory system for SMBs in Latin America. Over time it grew past 40 tables, multiple services distributed between Windows and WSL, and an architectural migration that ended up being the catalyst for everything that followed.

But this story isn’t about IUNCI. It’s about the moment context limits stopped being a technical problem and became an economic one.


Where it started: I just wanted a project launcher

In March 2026 I had a concrete problem: several active projects, each with a different stack. For IUNCI alone I had to remember which service ran in WSL and which on Windows, which port each used, and in what order to start them. Multiply that by six parallel projects.

The first version of void-stack was exactly that — a launcher. One command to start everything. void start, void stop, void status. The binary was 5MB and I was perfectly happy with that.


The breaking point: when context became expensive

At first I worked with AI directly: I’d copy and paste into the chat when needed. It worked because Claude sessions were generous.

When Anthropic adjusted costs and session limits, that changed. Suddenly, orienting the AI in a large project cost 35% of the available context before even getting to the actual problem. It wasn’t a capability problem — it was an economic one. Every session started at a deficit.

That’s when I said: I need to do something.

Semantic search exists in Python — there are tools that do this. But I wanted something completely local, without sending source code to external services and without per-query costs. And I already had void-stack in Rust. I didn’t want another separate tool to maintain.


v0.23.0 shipped on April 7, 2026 — one month after the original launcher. It added the full semantic index: BAAI/bge-small-en-v1.5 running locally with fastembed, HNSW for search, and .claudeignore support to skip what isn’t valuable.

Measured result after 135 real searches on my own codebase: 97.5% fewer tokens than reading files directly.

How is this measured? void-stack tracks the bytes of returned chunks versus the bytes of all unique relevant source files, divided by 4 to estimate tokens. The void stats command shows accumulated savings per project and operation.

# The problem: orienting the AI cost 35% of context in every session
# With void-stack:

void search iunci "sync fails on offline conflict"

# Result: the 5 most relevant chunks from the sync system
# and the repositories involved — without scanning the rest

Crossing data: from concept to structural graph (GraphRAG)

Shortly after, a LinkedIn post surfaced code-review-graph. I downloaded it, analyzed it with Claude using void-stack to understand the architecture, and saw it did something I needed: build a call graph with Tree-sitter. I understood what problem it solved, extracted the ideas that worked for me, and implemented a native Rust version inside void-stack.

That was missing. Semantic search tells you what is conceptually similar. The structural graph tells you what breaks if you change this. They’re complementary.

How GraphRAG combines semantic and structural search in void-stack Your project feeds a semantic search (what is similar?) and a structural graph (what breaks?). GraphRAG fuses both into a combined ranking and hands only the relevant chunks to Claude Code and Claude Desktop. Your project Semantic search BAAI embeddings · HNSW what is similar? Structural graph Tree-sitter · BFS SQLite what breaks? GraphRAG combined ranking Claude Code / Claude Desktop receives only the relevant chunks
GraphRAG in void-stack — 97.5% fewer tokens, measured over 135 real searches.

v0.23.5 (April 13) added the structural graph: Tree-sitter for 10 languages, bidirectional BFS in SQLite for blast radius. v0.26.0 (May 7) fused them into GraphRAG. After several tests on my own codebase, a 60/40 weighting between semantic and structural signal produced the most useful results — but the exact ranking strategy deserves its own article.

The README cites code-review-graph explicitly: “Structural analysis inspired by code-review-graph (MIT) — AST node mappings and BFS query logic reimplemented natively in Rust.”

Here’s what a real GraphRAG query on IUNCI looks like:

$ void graphrag iunci "modify offline sync"

Semantic seeds (3 found):
  sync_repository_registry.dart    [score: 0.94]
  hybrid_inventory_repository.dart [score: 0.89]
  sync_status_notifier.dart        [score: 0.82]

Structural context (BFS depth 2):
 HybridInventoryRepository calls SyncRepositoryRegistry
 SyncRepositoryRegistry calls HybridSalesRepository
 SyncRepositoryRegistry calls HybridSupplierRepository

Total: 5 chunks · ~2,800 tokens
vs scanning 48 related files · ~96,000 estimated tokens

The workflow: directing, not writing

I didn’t write all of this line by line. I directed it.

My actual cycle:

  1. Identify the problem and design the solution
  2. Claude Desktop analyzes it and generates the implementation prompt
  3. Claude Code implements, writes tests, commits
  4. I test on real hardware and report what doesn’t work
  5. Back to step 1

Learning Rust while building a CLI with a SQLite backend and local FastEmbed sounds like a recipe for disaster. But delegating the heavy implementation and strict typing to AI — while focusing on architecture and system behavior — accelerates the learning curve in an absurd way.

It wasn’t my first encounter with Rust. I’d used it in 2021 working with smart contracts on Solana for a virtual reality project. A basic Microsoft course in 2024 refreshed what I already knew. But void-stack was where I actually used it in earnest: learning what I needed while building what I needed.

That process produced 7 crates, 1,010 tests, 80.5% coverage, and 4 interfaces (CLI, TUI, desktop app, MCP server) — all in roughly two months. All to solve a problem that originally seemed much smaller: the cost of explaining a large project to an AI.


The real impact on IUNCI

With void-stack, the migration that had been blocked for months started moving steadily. Things that used to take days took hours. The AI has the exact context of each module’s state — what’s migrated, what has pending technical debt — and gives accurate diagnoses from the first response, without reconstructing the project from scratch every session.


The bottom line

I started building a launcher so I wouldn’t have to remember commands. I ended up building a way to reduce the cost of context in projects that no longer fit in a chat window.

Available at void-stack.dev and GitHub.


About the author

Systems engineer from Venezuela. I build developer tools and products for the LATAM market.

void-stack.dev · github.com/mague