Building Demoji: A Small Tool That Helped Me Test A Much Larger Idea
I've been working on a project called Cogit — a context system for coding agents. Memory, guidance, policy, delivery. I've been making good progress but I wanted to put it to the test.
So I built something small first.
Demoji is a TypeScript CLI that scans codebases for emoji, classifies what it finds, and either reports on it or cleans it up. That's it. But the reason I built it the way I did has more to do with Cogit than with emoji.
The emoji problem is real, just small
If you've spent time building with LLMs, you've seen the artifacts they leave behind. Emoji is one of them. It shows up in comments, log statements, variable names — places where it has no business being in code that's heading toward production.
How it works
Demoji has three modes: scan, clean, and report. Scan walks a repo and tells you what it found. Clean applies replacements. Report generates a standalone HTML file you can share.
The interesting part is the classification layer. Every emoji match gets tagged by where it appears:
- Comment — replaced with a text equivalent.
✅becomes[OK],🐛becomes[BUG], that kind of thing. - Log statement — emoji just gets dropped. Nobody needs emoji in their logs.
- String literal — left alone by default because it might be user-facing. There's a
--strictflag if you want to nuke those too. - Identifier — flagged for manual review. I'm not going to auto-rename your variables for you.
The rest of the design is cautious on purpose. Dry runs by default. Confirmation prompts before writes. A backup git branch gets created before anything changes. No runtime dependencies. Respects .gitignore. Skips binaries. I wanted it to be the kind of tool you could run against a production repo without thinking twice.
What this had to do with Cogit
Here's the actual point.
Cogit is about giving coding agents better context so they make better decisions. That's a broad idea, and broad ideas are easy to over-theorize.
The core instinct behind Cogit is: if you give automated systems clear policy, context-aware behavior, and inspectable outputs, they become trustworthy enough to actually use. Not "trust blindly" trustworthy — "I can see what it did and why" trustworthy.
Demoji was where I tested whether that instinct holds up when you put it in a real tool. Can I define behavior clearly enough that someone reading the output understands why each replacement happened? Can I make the cautious path the default without making the tool annoying? Can a user look at a dry-run report and actually audit it?
The answer to all of those turned out to be yes, which was useful. Not because a CLI that cleans emoji proves anything about agent systems at scale. But because it proved to me that Cogit is worth putting more time into.
What I'd tell someone considering the same approach
If you're working on a big system idea, find a small problem that puts the project's assumptions to the test. Not a toy problem. A real one, just a contained one.
The thing I got wrong initially was thinking I needed to validate Cogit inside Cogit. That's too many moving pieces. Demoji narrowed it to one question: does context-aware, policy-driven behavior actually produce better results than the naive version? It does. Now I can take that confidence into the bigger project.
I also came away more convinced that inspectability isn't a nice-to-have. Dry runs, explicit classifications, readable reports — these aren't polish. They're the reason you trust the tool. A system that changes your code and can't show you why is a system you stop using after the first bad surprise.
Wrapping up
Demoji is a small tool. It solves a specific problem, it's useful on its own, and I like that it doesn't need a five-minute preamble to justify its existence.
But for me, its real value was giving me a concrete, low-stakes place to pressure-test the ideas behind Cogit before trying to build them at full scale. Some of the broader governance and enforcement work in Cogit still needs more time. That's fine. The proof of concept did what proof of concepts are supposed to do — it made the next step clearer.