The moment of recognition came on a Tuesday, reading a daily note I had written six days earlier.
The note referenced Falcon twice, Spider once, and Owl in a context that made no obvious sense without knowing what Owl did. I had written the note. I still had to pause and mentally load a seven-item glossary before the sentences resolved into meaning. That is a bad sign. That is the sign that the vocabulary is doing negative work.
I run a seven-agent AI system I call the Single Brain. At the time, the agents had names: Brick (signal scanner), Owl (Bayesian grader), Bull (swing trade executor), Falcon (0-DTE put spread specialist), Spider (0-DTE iron condor specialist), Arrow (sales outreach pipeline), and Sage (knowledge vault). The names were memorable. They were also debt.
Animal names are debt.
The names came from a good instinct — give the system a personality, make the agents feel like a crew rather than a codebase. That instinct is reasonable for customer-facing products. It is actively harmful for internal vocabulary.
A new reader had to memorize a seven-word legend before parsing a daily note. Not seven functions. Seven proper nouns mapped to functions via metaphor. Falcon and Spider — both drawn from nature, both referring to adjacent 0-DTE strategies on the same underlying — required tribal knowledge to differentiate. If you didn't already know that Falcon ran put spreads and Spider ran iron condors, the distinction between them was invisible. They were just two fast, predatory things.
Sage and Owl both coded as "wise." Brick was the only one that even gestured at structure (heavy, solid, foundation-like). Bull was the most misleading: the name implied bullish directional bias, but the agent traded both directions on a 21–60 day timeframe. The names told you nothing reliable about what each agent did.
And the system was growing. More agents would be added. Each new animal name would compound the legend. The glossary was going to keep getting longer. That's when I decided to kill all seven names and start again.
What functional names actually buy you.
The new names: Scanner / Grader / SwingTrader / DayPut / DayCondor / Outreach / Vault. Each one says exactly what its agent does. Self-documenting. No legend required.
A new reader — or the future you, six months out — reads "Scanner says NEUTRAL_BEAR" and the meaning is intact. Compare to "Brick says NEUTRAL_BEAR." Without the glossary, meaningless. The functional name carries its own payload. The metaphorical name requires a lookup every single time.
The disambiguation problem that plagued Falcon and Spider is gone. DayPut and DayCondor differ on the obvious axis — the strategy each runs. You don't have to know which bird is which. You read the word and you know the thing.
Kunal Shah's framing applies here directly: soulfulness ≠ efficiency. Soul belongs in the products you ship to customers — the front door. Internal vocabulary is plumbing. Plumbing should be efficient, not soulful.
Three properties of a good functional name:
- The function is obvious from the word alone. No supplementary knowledge required. "Scanner" tells you it scans. "Vault" tells you it stores. "SwingTrader" tells you it executes multi-week trades.
- No metaphor required. A six-month-removed reader doesn't need to load the legend. The name is the legend.
- Disambiguation is automatic. DayPut and DayCondor differ on the obvious axis. Falcon and Spider did not differ on any observable axis without context.
What it actually touched.
The mechanical reality. Renaming "vocabulary" sounds small. It touched 26 files.
Daily notes that referenced the old names. Concept articles in the wiki that cited the doctrine. Memory entries in Claude's project memory pointing future sessions to the old vocabulary. Project tracker rows in Obsidian. The cross-domain query skill specification. Two CLAUDE.md files — the root file and the vault file. One Codex sync file. An AGENTS.md. Around twenty concept articles in the compiled wiki.
Why touch all 26? Because the old names were doing work — they weren't inert labels, they were vocabulary the whole system spoke. The daily brief referenced them. The ask-anything skill referenced them. The memory system used them as anchors for cross-session continuity. Names doing work are not free to change. A simple global find-and-replace would have broken doctrine notes that explicitly named the old system as legacy — some references had to stay as historical record, some had to flip to the new vocabulary.
The fix took roughly 30 minutes via a Python script with sentinels — protect folder paths first (so bull-trading/ doesn't become swingtrader-trading/), then word-boundary replace on prose, then unprotect. The decision to do it took longer than the doing. Most naming decisions do.
Layer 1 vs Layer 2.
The doctrine that fell out of the rename. Two layers. Two rules.
Layer 1 is anything that runs. Folder paths, Python file names, signal IDs, launchd job names, log filenames, database tables, cron job identifiers. Do not rename Layer 1. It breaks scripts. It breaks scheduled jobs. It corrupts audit history. The old folder paths — bull-trading/, falcon-trading/, spider-trading/ — stayed exactly as they were. The Python file names stayed exactly as they were. Layer 1 is stable by default.
Layer 2 is anything that's prose. Documentation, daily notes, concept articles, briefings, commit messages, memory files, CLAUDE.md files, skill specifications. Always rename Layer 2 when the vocabulary improves. This is the layer where readers live. Cost of confusion compounds; cost of a rename is bounded and one-time.
| Layer 1 — stays (it runs) | Layer 2 — rename (it's prose) |
|---|---|
| bull-trading/ (folder path) | Daily notes referencing "Bull" |
| falcon-trading/ (folder path) | Concept articles citing "Falcon" |
| agent4_grader.py (filename) | Memory entries using "Owl" |
| agent2_signals.py (filename) | CLAUDE.md persona descriptions |
| launchd job: com.sachin.bull | Cross-domain query skill spec |
| Log file: bull_eod_YYYYMMDD.log | Commit messages (going forward) |
| Signal ID: scanner_bull_high | Project briefings + briefings in docs |
The mistake most teams make: they treat code names as load-bearing. They are not — they are pet names that happen to live inside the codebase. The vocabulary your team speaks in standups, briefings, and documentation is what needs the discipline. Layer 2 is where real cost of confusion accumulates.
The Kunal Shah lesson.
A long aside on naming as a discipline, not a preference.
Kunal Shah has a framing about Indian status culture — and more broadly, about any organization that optimizes for visible symbols of status over actual outcomes. The pattern: put the peacock vehicles in the lobby, give everyone an impressive title, run a lengthy credentialing process. The result is an organization that looks excellent and performs poorly. The signal-to-noise ratio on visible status is zero.
The same dynamic plays out in naming. Cute internal names flatter the team's sense of itself ("we're a clever shop, we have a crew with memorable names") at the cost of clarity for anyone not in the room. The future hire who reads your briefings. The contractor who runs your scripts for a week. The future you, returning from three weeks offline and needing to parse a system you built six months ago.
The discipline: internal vocabulary is for the work, not for the team's self-image. Soul belongs in customer-facing brand. Plumbing should be efficient.
A second framing: names that compress meaning don't need a glossary. "Scanner says BEARISH" requires no preamble. "Brick says BEARISH" requires you to hold a seven-entry lookup table in working memory before you can parse the sentence. Every time. For as long as the system exists. Across every reader who ever interacts with it.
That lookup cost is tiny per instance. It compounds. Six months of daily notes, briefings, and cross-agent synthesis, all taxed by a glossary that should never have been necessary. Naming debt accrues silently, in the reader's working memory, not in the codebase.
Why bother — the salvage value.
Five concrete returns from the rename:
- Onboarding cost dropped to zero. A new collaborator — or the future you returning from sabbatical — reads "Scanner says NEUTRAL_BEAR, Grader flags low confidence, SwingTrader is long-loaded" and the sentence is complete. No glossary lookup. No mental translation. The names do the work the names are supposed to do. This matters most at 6am before coffee when you're parsing a daily brief before market open.
- Cross-system synthesis became cleaner. "Scanner is bearish but SwingTrader is long-loaded — risk concentration" is parseable in two seconds and actionable in three. With animal names, the reader had to mentally translate three proper nouns before the sentence even registered as a coherent thought. The cognitive overhead was not large. It was constant. That's worse.
- Productization became thinkable. A starter kit for solo operators with the old animal names would have shipped with a glossary appendix before page one. Functional names ship without one. Scanner / Grader / SwingTrader need no explanation to someone who has never seen the system. That's the product pitch — immediate legibility.
- Refactoring exposed hidden ambiguity. Two cases where the old vocabulary was concealing weak doctrine: Owl and Sage both coded as "wise knowledge agents," obscuring the real functional difference between a probabilistic grader and a static knowledge store. Falcon and Spider both coded as "fast, precise predators," obscuring the real difference between a defined-risk put spread and a defined-risk iron condor. The rename forced precision. The ambiguity was in the names, and the names were hiding it.
- It set the rule for next time. Roster cap is seven functional names. Any new agent must justify a name that says what it does in one word, or fold under an existing function. DayPut and DayCondor are at capacity for 0-DTE. If a third strategy gets added, it either replaces one of them or it doesn't get its own agent. The naming rule enforces the architecture.
The honest takeaway.
Naming is debt or it is leverage. Animal names felt clever and were debt. Functional names feel boring and are leverage. The rename took 30 minutes — considerably less time than the cumulative minutes I had spent over the prior two weeks justifying the metaphors to myself when re-reading old notes.
Most teams won't make this rename because the problem is invisible. The cost doesn't show up in a dashboard. It shows up in a half-second pause, a brief wrinkle of mental effort, each time someone reads a sentence that contains "Brick" instead of "Scanner." That pause happens hundreds of times. The cost is real. It's just small enough to ignore — which is exactly how naming debt compounds.
Soul belongs at the front door. In the products you ship to customers. In the brand voice that greets a new user. Internal vocabulary is plumbing. Plumbing should be efficient.
The old names — Brick, Owl, Bull, Falcon, Spider, Arrow, Sage — are now in the historical record. They served their purpose when the system was small enough that the builder was also the only reader. The system isn't that small anymore. The names had to grow up.
"Names that need a glossary are names that haven't earned the work they're doing."