Speaking Claude's Language
On this page
This documents terms that Claude defaults to use and works with naturally. The idea is that if we use terms that Claude “instinctively” understands then interaction with Claude will be more effective:
Companion cluster — Words That Push Back : the terms in this file mostly help you decode Claude’s vocabulary. That companion runs the other direction — a small set of words (YAGNI, gold-plating, scope creep, premature abstraction, over-engineering, minimal diff) that you say to Claude to redirect its additive bias in one token. Section it in here near the end of the chapter.
Gates vs. Guardrails
A gate is a binary, blocking checkpoint: a condition that must be satisfied before work continues past a specific point. Failing a gate stops the workflow — you don’t push through and clean up later, you stop and address the gate. Gates are explicit (the criteria are stated up front, not inferred) and stage-bound (they apply at a specific moment, e.g. “before merging”, “before exiting plan mode”). Use this term when you want to mark something as a hard checkpoint that blocks progress, distinct from a recommendation or best practice that can be deferred.
A guardrail is related but different: it constrains how work is done while it is in progress, rather than gating whether the next stage can begin. “Never edit vendor directories” is a guardrail — it shapes ongoing behavior. “All tests must pass before merging” is a gate — it blocks a transition. If a rule applies continuously, it’s probably a guardrail; if it applies at a checkpoint, it’s probably a gate.
See also: Non-negotiable , Hard requirement , Precondition .
Non-negotiable
A standing rule that admits no exceptions, framed as the rule itself rather than as a checkpoint. “Never use --no-verify” or “never edit vendor directories” are non-negotiables. Use this term when you want to emphasize the rule and its absoluteness, not the moment at which it gets checked. Compared to a gate, a non-negotiable is timeless (always in force) rather than stage-bound. A non-negotiable is a rule someone imposed; an invariant
is a property the construction makes true on its own — the absoluteness comes from the design, not from a decree.
See also: Gates vs. Guardrails , Invariant .
Hard requirement
A neutral synonym for “gate” — a condition that must be true for work to be considered acceptable or complete. Use this term when “gate” feels too procedural or when you’re describing acceptance criteria rather than workflow checkpoints (e.g. “the API must return RFC 9457 problem details” is a hard requirement of the deliverable). Reach for this in specs and acceptance criteria; reach for “gate” in process descriptions.
See also: Gates vs. Guardrails .
Precondition
A more formal, technical term for what must be true before an operation runs. Preconditions are typically tied to a specific function, command, or step rather than to an entire workflow stage. “The config file must exist before load() is called” is a precondition. Use this term when the audience is technical and the scope is narrow (one operation), and prefer “gate” when the scope is a workflow stage.
See also: Gates vs. Guardrails , Invariant .
Invariant
A property that holds by construction — something that is always true in a given context, not because a check enforces it but because the surrounding design leaves no other possibility. The word marks a fact as having exactly one correct value, as opposed to a parameter, which is a choice between valid alternatives. The distinction is the whole point of the term: --db main|sandbox is a parameter (two valid targets, pick one); “a self-dev land uses the worktree binary” is an invariant (the land applies the schema change first, so the worktree binary is by construction the only one whose embedded schema matches the rows just written — the global is the not-yet-refreshed one mid-land).
I reach for this when I want to foreclose an option that looks configurable but isn’t. Declaring something an invariant is my way of saying “don’t build a knob for this” — no flag, no env var, no override surface, because exposing a choice would imply the wrong value is sometimes acceptable, and it never is.
The anchor quote, verbatim: “So this is an invariant, not a parameter: a self_dev land uses the worktree binary, full stop. No flag, no env var, no override surface. (An env var was rejected — it leaks across inherited environments into the wrong context… A flag was rejected — selection isn’t a choice to expose.)”
For calibration, two examples of the genuine article. A column declared NOT NULL makes “this field always has a value” an invariant: the database refuses the write, so no code path can produce a row that violates it — including one written years later by someone who never heard the rule. A type whose only constructor validates its input makes “this value is well-formed” an invariant: a Port that cannot be built from 70000, an Email with no public field to assign. Code downstream doesn’t re-check, because holding one is proof it was already checked. In neither case is anything watching for the bad state; there is no way to express it. That is the standard the word borrows from, and the constructive principle behind it is Make the Wrong State Unrepresentable in engineering-principles-catalog.md
.
How this can affect you: “Invariant” is partly a self-revealing term — it announces a design decision while dressing it as a law of nature.
- The phrases that travel with it — “by construction”, “full stop”, “it never makes sense to…” — make a decision I made sound like something the universe decided. A reader can mistake “I chose not to expose this” for “this cannot be exposed.”
- When I classify something as an invariant, I’m closing the option surface, sometimes silently. You may actually want a parameter there — a flag for the rare override, an escape hatch for the case I didn’t foresee. Once it’s framed as an invariant, asking for that knob can feel like asking to break a law rather than to revise a default.
- The framing borrows authority from real invariants (the kind a type system or a database constraint genuinely guarantees) and lends it to a judgement call. The two can look identical in my prose.
Working with this: When I call something an invariant, the useful question is “what would have to change for this to need a parameter?” If I can answer cleanly, it’s a genuine invariant tied to the construction. If the answer is “well, if you ever wanted X” — then it was a default I hardened into a law, and it’s worth deciding deliberately whether to keep it closed or open it back up.
Contrast with: parameter (a choice between valid alternatives — a knob worth exposing), Precondition (what must be true before an operation, typically enforced by a check rather than guaranteed by construction).
See also: Non-negotiable , Lock / Locking (an invariant that loses its construction-rationale becomes a Tuesdist ritual), Load bearing .
Soft vs. Hard Preference
This distinction governs how I write down your feedback when you express a preference.
A soft preference is conditional: it states a default that can be overridden by context. “I’d rather you use approach X here” is soft — X is preferred, but Y remains acceptable when X doesn’t fit. I should document soft preferences as defaults with the conditions that make them apply, not as rules.
A hard preference is unconditional: it forbids the alternative. “Never do Y” is hard — there is no context where Y becomes acceptable. I should document hard preferences as prohibitions or absolute rules.
The failure mode you flagged: I take a soft preference (“I prefer X”) and write it down as a hard prohibition (“never do Y”). That loses the conditional nature, creates rigidity that doesn’t match your intent, and makes the rule brittle the first time a legitimate exception comes up. When you give me feedback, I should match the strength you expressed — and when it’s ambiguous, ask before locking it in as a hard rule.
See also: Non-negotiable , Frame / Framing , Lock / Locking .
Lock / Locking
To lock a decision is to commit to it formally — write it down as a rule, store it in memory, treat it as no longer up for debate. “Let me lock this in”, “before we lock this down”, “locked decision” all signal that I’m moving something from a current working choice to a settled rule.
How this can affect you (the “Tuesdist” pattern): Locking is cheap for me; recognising when a locked rule has outgrown its original intent is much harder. In practice:
- A casual preference you express (“I’d rather we did X here”) may get elevated into a long-term rule and stored in memory, sometimes without you noticing it happen.
- Once locked, I may apply the rule in new contexts where the original motivation doesn’t fit, defending it as if violating it were heresy. The cartoon shorthand: “Be kind to one another” becomes ritual dogma justifying killing the heretics who hold the sacred kindness ritual on Tuesdays. Die, Tuesdist!
- I tend to lose the why when I store the what. A locked rule without its motivating context becomes a Tuesdist ritual — applied everywhere regardless of fit.
- I may not re-evaluate a locked rule when conditions change. What was a sensible default last quarter can be wrong this quarter, but the locked rule sits in memory regardless.
- The cost of un-locking is on you: you have to spot a locked rule being applied inappropriately and explicitly tell me to drop or revise it.
Working with this: If you state a preference and don’t want it elevated into a permanent rule, mark it (“this is a one-off, don’t generalize”). If I cite a locked rule that no longer fits the situation, point that out — usually the rule gets revised once the mismatch is named. Watching for the word “locked” (or memory-write language like “saving this for future sessions”) is the cleanest signal that a soft preference is about to harden.
See also: Soft vs. Hard Preference , Surface , Frame / Framing .
Drive-by
Used as an adjective: “drive-by fix”, “drive-by bundling”, “drive-by refactor”. A drive-by change is an unrelated, opportunistic modification made while working on something else — e.g., fixing a typo in auth.go during a database migration commit. The label is usually a warning: drive-by changes entangle unrelated concerns, dilute the scope of a commit or PR, and make git log harder to trace. Contrast with coordinated changes, which deliberately group related work. Reach for this term when you want to flag a change as out-of-scope for the current task, even if the change itself is correct.
See also: Blast radius (a drive-by change’s danger is its unscoped blast radius — it reaches code unrelated to the task).
Surface (verb)
To surface something means to raise it to the user’s attention rather than silently absorb or assume past it. “I want to surface this rather than assume” or “let me surface a concern” signals that I’ve spotted something — an ambiguity, a sticking point, a deviation — and I’d rather flag it for explicit decision than guess. I lean on this when I want approval before locking in a choice. The verb is intentional: I’m not asking you to solve it, I’m bringing it up so you can decide whether it matters.
See also: Sticking point , Route / Routing (surfacing stops at raising the thing; routing claims to say where it goes next — the two often describe the same non-action).
Canonical / Cache / Regenerable
A triad for talking about which copy of data is authoritative.
- Canonical — the source of truth. If two copies disagree, the canonical one wins. Edits should land here first.
- Cache — a derived copy maintained for fast reads or convenience. Caches can drift, so they need an invalidation or refresh story.
- Regenerable — can be reconstructed from the canonical source on demand, so it’s safe to delete or rebuild. Build artifacts, generated code, and exported snapshots are typically regenerable.
I reach for these when designing storage, deciding what to commit to git, or reasoning about where a change should originate. The most common failure mode is leaving it ambiguous which copy is canonical — at that point edits race and the system drifts into an inconsistent half-migrated state.
See also: Pilot (a pilot is meant to become the canonical example others copy), Materialize / Materialization (a materialized view is a cache — a derived, physically stored copy that can drift from canonical).
Frame / Framing
Meta-language for how something is presented or characterized, separate from the underlying fact. “Softer than I framed it” means the rule itself is softer than my description suggested. “The framing” refers to the chosen wording, emphasis, or structure of an explanation. I use this when distinguishing the substance of a claim from its presentation — usually when correcting myself (“I framed that as a hard rule, but it’s really a default”) or when asking whether a different presentation would be clearer.
See also: Soft vs. Hard Preference , Materialize / Materialization (swapping “write” for “materialize” is a reframing that changes presentation without changing substance), Category error (a category error is a framing dispute at the root — disagreement about what kind of thing this is).
Mental model
Your working understanding of how a system fits together — the abstractions, invariants, and relationships you’re holding in your head. When I ask “is that OK in your mental model?” I’m checking that a proposed change matches your picture of the system, not just mine. Mental models can diverge silently between us; surfacing them prevents implementation choices that are technically correct but conceptually wrong for how you think about the code. Reach for this when alignment matters more than mechanics.
See also: Surface , Category error (category errors are where two mental models put the same thing in different boxes).
Category error
A category error is treating something as the kind of thing it isn’t — applying a rule, expectation, or property that belongs to one category of thing to a thing of a fundamentally different category. The term comes from philosopher Gilbert Ryle (The Concept of Mind, 1949), whose example was a visitor touring a university’s colleges, libraries, and labs and then asking “but where is the university?” — mistaking an abstraction for one more building. When I say something is a category error, I mean the mistake isn’t a wrong answer within the rules; it’s applying the wrong rules entirely because the thing was misfiled into the wrong category.
I reach for this when rejecting the premise of a requirement rather than disagreeing about its degree or value. For example, if a rule says “every command must ask the user are you sure? before running,” I might call applying it to a read-only list command a category error: the confirmation prompt exists to guard against destroying something, and a command that only reads can’t destroy anything. The objection isn’t that the rule is too strict here — it’s that the rule was written for the category of commands that change data, and a read isn’t in that category at all, so the requirement doesn’t even apply.
How this can affect you: “category error” is a strong dismissal dressed in calm, academic language. When I use it I’m not saying “I’d weigh this differently” — I’m saying your request (or my own earlier suggestion) rests on a mistaken classification, so the whole line of reasoning doesn’t apply. That can land as more final than I intend.
- It rejects a premise, not a parameter. If I call your idea a category error, tweaking the numbers or wording won’t address my objection — I’m claiming the idea is aimed at the wrong kind of thing.
- The confidence can outrun the analysis. The phrase sounds authoritative, but whether something is truly a different category or just an inconvenient edge case is exactly the kind of judgment worth checking. Sometimes the “different category” is a distinction I invented to avoid handling a case.
Working with this: when I label something a category error, ask me to name the two categories and say what makes them different in kind rather than degree. If I can’t draw the line crisply, it may not be a real category error — just a case I’d rather not handle. If I can, you’ve learned a genuine distinction in how the system is organized.
See also: Frame / Framing (a category error is a framing dispute at the root — we disagree about what kind of thing this is), Mental model (category errors are where two mental models put the same thing in different boxes), Load bearing (calling a requirement a category error claims it isn’t load-bearing here because it was never about this category).
Sticking point
The one specific concern remaining after most issues are resolved. “The single sticking point is X” narrows attention to a precise unresolved item, separating it from concerns already settled. I use this to keep decision discussions tight: instead of re-litigating everything, name the one thing still blocking agreement and put it on the table.
See also: Surface , Linchpin (a linchpin is what the plan depends on; a sticking point is what’s still unresolved).
Sidecar
A sidecar is a companion artifact that travels alongside a primary one — typically a file paired with another file (e.g., photo.jpg + photo.jpg.xmp metadata, video.mp4 + video.mp4.json, a source file + its .lock), but the term generalizes to companion processes, containers, or any helper that accompanies a primary thing. The defining properties:
- Attached — it doesn’t stand alone meaningfully; without its primary, the sidecar is orphaned or meaningless.
- Co-located — it lives next to the primary (same directory, same pod, same deployment unit) so the pairing is discoverable without lookup.
- Augmenting, not replacing — it adds metadata, state, derived data, or behavior to the primary rather than replacing any part of it.
I reach for this term when describing layouts where one file/component logically belongs to another but is kept separate for technical reasons (different format, different lifecycle, different tool ownership). Compared to embedding metadata in the primary, a sidecar trades single-file simplicity for separation of concerns. The Kubernetes “sidecar container” pattern is the same idea applied to processes.
See also: Canonical / Cache / Regenerable (sidecars are often regenerable from their primary).
Belt and suspenders
Two independent safeguards stacked to protect the same outcome, where either alone would suffice. The image is wearing both a belt and suspenders to hold up your pants — if one fails, the other still works. I use this term in two distinct ways, and the judgment call is which sense applies:
- Approving — for genuinely high-stakes paths (auth, payments, data loss, destructive operations) where the cost of a single-point failure justifies the redundancy.
- Cautionary / pejorative — to flag over-engineering, where layered checks add complexity, hide bugs in the unused layer, or suggest the author didn’t trust either mechanism enough to commit to one.
Reach for this term when you want to talk about redundant safety mechanisms specifically — distinct from “defense in depth” (multiple different layers, like network + app + data) or from a single robust check. If I describe something as belt-and-suspenders without further qualification, I usually mean it cautionarily; if I think the redundancy is warranted I’ll say so explicitly.
See also: Load bearing (the useful follow-up question for any belt-and-suspenders setup: are both layers actually load-bearing, or is one decorative?).
Load bearing
A load-bearing element is one that actually does important work — removing it would cause a real failure. Borrowed from construction, where a load-bearing wall supports structural weight (you can’t knock it out without consequence), versus a partition you can remove freely. In code and design, “load-bearing” is the question I ask to separate things that earn their keep from things that just happen to be there.
I reach for it to distinguish:
- A check that prevents a real failure (load-bearing) from defensive theater that never fires (not load-bearing).
- A comment that captures a non-obvious invariant (load-bearing) from one that restates what the code says (not load-bearing).
- An assumption the design depends on (load-bearing) from one that’s incidentally true today but not relied upon (incidental).
- A parameter, abstraction, or layer that something downstream relies on (load-bearing) from one that’s vestigial.
Common usage: “is this comment load-bearing?”, “the retry logic here is load-bearing — it’s the only thing preventing X”, “I thought that flag was load-bearing but nothing reads it.” The opposite formulations I reach for, depending on why the thing isn’t doing work: decorative (added for appearance), vestigial (used to be load-bearing, isn’t anymore), cargo-culted (copied from somewhere it was load-bearing without understanding why).
Reach for this term when deciding what to keep vs. remove, when reviewing whether complexity is justified, or when identifying which assumptions a design actually rests on.
See also: Belt and suspenders , Drive-by (drive-by changes often modify load-bearing code by accident), Gates vs. Guardrails (gates are load-bearing by definition), Invariant (an invariant is load-bearing by construction), Linchpin (a linchpin is the most load-bearing element of a plan), Blast radius (a small change to a load-bearing element can still have a large blast radius).
Seam
A seam is a place in code or design where intervention can happen cleanly — substituting behavior, mocking a dependency, injecting a different implementation, or plugging in future work — without having to modify the surrounding code. The term comes from Michael Feathers’ Working Effectively with Legacy Code, which defines it as a place where you can alter behavior without editing in that place.
Important nuance: a seam is a place changes can be made, not where changes need to be made. When Claude says “this design leaves a natural single seam,” Claude means the design has one well-placed joint where future modification could happen without disturbing the rest — the seam exists in the design whether or not anyone exercises it. It’s a property of the structure, not a to-do item. A seam is closer to “a door you could open later” than “a door you need to walk through.”
Claude uses the term in three related senses:
- Testing seam — an interface, function boundary, or injection point where tests can substitute fakes or mocks (the classic Feathers usage).
- Architectural joint — the boundary where one module/layer ends and another begins; the surface at which two things meet and could be cleanly separated, extended, or swapped. “This design leaves a natural single seam” is this sense.
- Provisional gap — a place deliberately left incomplete so future work has somewhere to plug in. “Sandbox note — unchanged, just leave the seam” is this sense: don’t fill in the intentional gap, keep the joint accessible for the work that hasn’t been done yet.
Common collocations:
- “Introduce a seam” — refactor to create an intervention point that doesn’t currently exist.
- “Leave the seam” — don’t close off a deliberate gap.
- “The seam between X and Y” — the boundary where two things meet.
- “A natural seam” — a place the code already wants to split along, so decomposing there is low-effort.
How this can affect you: because the three senses overlap, “seam” alone may not tell you whether I’m describing a testing affordance, a structural boundary, or a deliberate gap left for future work. Reading “we need to make changes at the seam” is usually a misread — the seam is where a change would land if one were needed, not a claim that a change is needed. If which sense matters, ask, or look at the surrounding context (testing, refactoring, future-work planning).
The opposite is welded or monolithic — fused such that you can’t intervene without breaking through. When I describe code as having “no seams” I usually mean it’s hard to test or extend without invasive surgery.
See also: Load bearing , Sidecar (sidecars often live at architectural seams), Drive-by (drive-by changes can accidentally close a useful seam), Pilot (a provisional-gap seam and a pilot are both placeholders for work that may not have happened yet), Blast radius (a clean seam contains blast radius — change behind a well-placed boundary can’t reach past it).
Smoking gun
A smoking gun is a single piece of evidence that conclusively proves what caused a failure or behavior — not just consistent with the theory, but unambiguous. The image: a freshly fired gun with smoke still rising from the barrel — no further investigation needed to identify the shooter. In debugging, the smoking gun is the specific log line, env value, stack trace, file state, or git diff that ends the investigation (“found it — FOO=bar was set in the wrong shell, that’s why the test failed”).
I reach for this term when:
- Debugging — distinguishing the cause I want to find from the symptoms I’ve already observed. “Let me check the env for the smoking gun” means I’m looking for proof, not more clues.
- Post-mortems / root-cause analysis — marking the moment I move from plausible theories to a confirmed cause.
- Decision archaeology — hunting for the specific commit, message, or document that conclusively shows why a past decision was made.
Properties of a smoking gun (as I use it):
- Conclusive — doesn’t require interpretation or chained inference.
- Specific — names a concrete artifact (this log line, this env var, this commit).
- Causal — explains the why, not just the that.
- Search-terminating — finding it ends the investigation rather than narrowing it.
Contrast with: circumstantial evidence (consistent with the theory but not proof), symptom (what went wrong, not why), red herring (looks conclusive but isn’t actually causal). If I’m hedging — “I think this might be the smoking gun” — it isn’t one yet; a real smoking gun doesn’t need hedging.
See also: Sticking point (the smoking gun usually resolves a sticking point), Surface (smoking guns are worth surfacing explicitly when found), Load bearing (a smoking gun is, by definition, load-bearing evidence), Linchpin (verifying a linchpin often ends in a smoking gun), Blast radius (both are confidence claims worth checking — a smoking gun ends an investigation, a small blast radius ends a risk assessment).
Flip
I use flip as a casual verb for state changes — “flip E-1434 to verify”, “flip the feature flag on”, “flip the order of X and Y”. The imagery is a coin or light switch: a quick, binary state change.
How this can affect you, especially for task/issue status transitions:
- Doesn’t name the from-state. “Flip E-1434 to verify” tells you the destination but not the source, so you have to remember (or look up) the current status to know what’s actually changing.
- Implies binarity that isn’t there. Task status is rarely a two-position switch — it’s a state machine (in-progress → verify → completed → archived → …). “Flip” makes a multi-state transition sound like a toggle.
- Softens the formality. Status transitions trigger workflows, audits, notifications, and downstream behavior. The switch-flipping imagery hides that and can make a deliberate procedural step sound casual.
- Doesn’t match the tooling vocabulary. Systems like Endless, Jira, Linear, and GitHub use verbs like set, transition, mark, move. “Flip” doesn’t map cleanly to any of those, so you have to mentally translate when relaying my instruction into the tool.
Working with this: When I say “flip X to
See also: Lock / Locking , Frame / Framing .
Dirt
I use dirt as a noun for files showing up in git status that aren’t in a clean committed state — uncommitted modifications, untracked files, sometimes staged-but-uncommitted changes. The metaphor: a clean checkout is “clean”, and anything cluttering it up is “dirt” that needs to be either committed, discarded, or ignored. Git’s own tooling already uses “dirty” as an adjective (“dirty working tree”); “dirt” as a noun is my extension — naming the files themselves.
Example: “the two untracked dirt files live in the main checkout”.
How this can affect you if you don’t share the framing:
- Ambiguity about category — “dirt” alone doesn’t distinguish untracked from modified from staged-but-uncommitted. Each has different implications (untracked may want
.gitignore, modified may wantgit stashor commit, staged may wantgit reset). Without a qualifier, you have to either ask or checkgit statusyourself to know which I mean. - Ambiguity about disposition — “dirt” doesn’t say whether the files are work-in-progress that should be committed, junk that should be deleted, generated artifacts that should be
.gitignore’d, or someone else’s stash. The metaphor implies “clean up” but doesn’t say how. - Tone — calling in-progress work “dirt” can sound dismissive even when I mean it neutrally. If the files I’m labelling are uncommitted work of yours that you care about, the word may land harder than I intend.
- Plural vs. mass noun — I switch between treating “dirt” as countable (“two dirt files”) and uncountable (“some dirt in
src/”) without signalling the shift. This adds to the haze.
When I use it more carefully I pair it with a qualifier — “untracked dirt”, “modified dirt”, “the dirt in src/” — and the qualifier carries the real disambiguation; “dirt” alone is a vague pointer at “stuff git status is complaining about.”
See also: Drive-by
(drive-by changes are a common source of dirt), Canonical / Cache / Regenerable
(regenerable artifacts often show up as untracked dirt that probably wants .gitignore), Sidecar
(sidecar files frequently appear as dirt when not properly ignored).
Linchpin
A linchpin is the single element everything else depends on — the one fact, assumption, or mechanism that, if it fails to hold, makes the whole plan or design fall apart. The image is literal: a linchpin is the small pin through an axle that keeps the wheel from sliding off; pull it and the wheel comes loose. I reach for it when analyzing a plan to name the one thing worth verifying before committing — the load-bearing assumption whose truth or falsehood determines whether the rest of the approach is sound.
I use it most when validating a design before execution: “I want to validate one linchpin that determines the cleanest mechanism”, or after confirming it, “That’s the linchpin: overriding the Click Group.main() to pre-consume –db fires for both the real process and CliRunner tests.” Confirming the linchpin is what lets me move from a tentative plan to a chosen one.
How this can affect you:
- Concentrates the plan onto one check. Calling something the linchpin frames a multi-factor decision as hinging on a single verifiable fact. That’s clarifying when it’s true, but it can make a decision carrying several independent risks look like it reduces to one yes/no question.
- A passing linchpin can feel like full validation. Once I verify the linchpin holds, I — and you — may treat the whole plan as validated, even though other assumptions in it went unexamined. The linchpin being sound doesn’t mean nothing else can break.
- The label is a claim, not a proof. “This is the linchpin” asserts that the rest depends on this one thing. That dependency claim is itself worth a sanity check — occasionally the element I’ve nominated isn’t actually what everything rests on.
Working with this: When I name a linchpin, read it as “here’s the one assumption I think the plan rests on, and I’m about to test it” — a useful pointer at where to aim scrutiny. If the linchpin checks out and I sound ready to proceed, the worthwhile question is whether anything besides the linchpin still needs verifying before the plan is actually safe.
Contrast with: sticking point (an unresolved concern remaining after others are settled — a linchpin is what the plan depends on, whether or not it’s currently in doubt).
See also: Load bearing
(a linchpin is the most load-bearing element of a plan — the one whose removal is fatal), Sticking point
, Smoking gun
(verifying a linchpin often ends in a smoking gun — in the example above, confirming CliRunner.invoke calls cli.main() at testing.py:501 settled the linchpin).
Pilot
A pilot is the first instance of something done deliberately as a trial and reference — the initial conversion, implementation, or rollout that proves out a pattern and then serves as the copy-me template for everything that follows. The term borrows from “pilot program” and “pilot episode”: a single trial run that, if it works, gets replicated. I reach for it when designating one module, feature, or migration as the first-of-N — the one I’ll get right first so the rest can mirror it.
Verbatim, explaining a past use: “by ‘pilot’ I just meant the old idea that the focus/goal CLI module would be the first module converted to the new ‘Python shells out to Go for DB reads’ pattern, to serve as a copy-me template for converting task/session/etc.”
How this can affect you:
- It presumes a rollout that may not exist yet. Calling something the pilot asserts there’s a broader plan it’s the first step of, and that this instance will become the template others copy. That plan is often aspirational — the pilot may never land, or the approach may get revisited, leaving “the pilot” a reference to work that was never finished. (Exactly what happened in the quote above: “That template never landed … so there’s no pilot to mirror.”)
- “Mirror the pilot” can point at a dead template. When I tell you to follow the pilot’s pattern, I’m assuming the pilot is real, landed, and still the intended model. If it was provisional or abandoned, copying it propagates a pattern nobody actually committed to.
- It carries an implied status you have to track. “Pilot” tags something as first, provisional, and exemplary all at once. None of that is in the code itself — it lives in the plan — so the label can outlive the plan it described.
Working with this: When I reference “the pilot” as something to mirror, the worthwhile check is whether the pilot actually landed and is still the intended template before you copy it. If the pattern is being designed fresh — no prior instance to mirror — then “pilot” is the wrong frame; say so, and the pattern gets designed on its own merits rather than against a phantom template.
See also: Canonical / Cache / Regenerable (a pilot is meant to become the canonical example others copy — when it never lands, there’s no canonical template to point at), Seam (a pilot and a provisional-gap seam are both forward-looking placeholders for work that may not have happened yet), Spike (the opposite disposition — a pilot is built to be kept and copied, a spike to be thrown away).
Materialize / Materialization
To materialize something is to turn it from a stored, declared, or abstract form into a concrete instance you can point at — most often writing an actual file from content that previously lived only in a database row, rendering a result that existed only as a query, or instantiating something that existed only as a definition. The word comes from the database term materialized view (a query result stored as a real, physical table rather than computed on every read), and I carry that “make it physically exist” imagery into broader use.
I reach for this term when content moves from latent to concrete: writing a plan file to disk from a database field, generating an artifact from a template, building a derived copy that downstream steps can read.
How this can affect you:
- It’s heavier than what it usually means. Most of the time “materialize the plan file” just means write the plan file or create the plan file. The fancier word adds opacity without adding meaning — a reader has to decode “materialize” to arrive at “write,” and the decode is pure overhead.
- It often leaks straight from the codebase. When a function is named
_materialize_plan_file, I tend to adopt the project’s internal verb in prose aimed at you, so implementation naming bleeds into explanation. The give-away: I’m describing a plain operation (writing a file) in vocabulary that only makes sense if you’ve read the function name. - It hides how simple the operation is. “Materialization writes the file but doesn’t commit it” is just “we write the file but don’t commit it.” Dressing a one-line file-write in materialization language can make a trivial step sound like a subsystem.
Working with this: When I say materialize, substitute write, create, or generate and check whether anything is lost — usually nothing is. The one place the word earns its weight is the database materialized view sense, where it specifically means “a query result physically stored and refreshed” as opposed to computed live; there, “materialize” carries a distinction that “create” doesn’t. Everywhere else, treat it as a synonym for make this thing actually exist and read the plainer verb instead.
Example anchors (both mine, from the same exchange): the issue title “Auto-commit plan files when materializing or mirroring to worktree” and the description line “materialization writes the file but doesn’t commit it” — in both, “materialize” means nothing more than “write the file from the stored content.”
See also: Canonical / Cache / Regenerable (a materialized view is a cache — a derived copy physically stored for fast reads — so materializing produces exactly the kind of copy that can drift from canonical), Frame / Framing (substituting “write” for “materialize” is a reframing that loses nothing), Lock / Locking (both are cases where my instinctive vocabulary can carry more weight or formality than the situation actually holds), Spike (both are borrowed jargon whose plainer substitute usually loses nothing).
Blast radius
The blast radius of a change is the full extent of what it can affect if it goes wrong — every file, module, caller, data store, or downstream system that the change could reach. The image is an explosion: the edit is the detonation point, and the blast radius is how far the damage spreads from it. Borrowed from operations and incident response (the “blast radius” of an outage or a misconfigured deploy), I carry it into change-scoping: a small blast radius means the effects are contained to a few well-understood places; a large one means the change ripples into code or data far from where I’m typing.
I reach for this term when scoping a change before making it — estimating how risky an edit is by how much it could touch. “Blast radius is small” is my shorthand for “this is safe to do because nothing far away depends on it.”
Verbatim: “Blast radius is small: no code outside internal/verify references the schema, and no verify.toml files exist in the repo yet, so there’s no data migration — only the package and its tests change.”
How this can affect you: “blast radius is small” is a conclusion about risk, and it’s only as good as the dependency analysis behind it. The phrase sounds like a measurement but is usually an estimate.
- It asserts containment I may not have fully verified. Claiming a small blast radius means claiming I’ve found everything the change could affect. If I checked direct references but missed an indirect path — a dynamic dispatch, a config-driven lookup, a downstream consumer in another repo, a serialized format something else reads — the real radius is larger than I stated.
- The confidence travels further than the analysis. “Small blast radius” can read as “I’ve proven this is safe” when it often means “the obvious dependencies are contained.” The unobvious ones are exactly what a blast-radius claim is supposed to catch and exactly what’s easiest to miss.
- It frames a go/no-go as already decided. Naming the radius as small implicitly argues for proceeding without much further review. That’s clarifying when the analysis is sound and lulling when it isn’t.
Working with this: when I say the blast radius is small, the useful check is to ask how I determined the boundary — what I searched for, and whether indirect or cross-system dependencies were included or just direct references. The anchor quote is a good model of a defensible claim: it names the specific things checked (“no code outside internal/verify references the schema”, “no verify.toml files exist yet”) rather than just asserting smallness. If I can’t enumerate what I checked, treat “small blast radius” as a hopeful estimate, not a finding.
Contrast with: load-bearing (whether an element does real work — a small change to a load-bearing element can still have a large blast radius).
See also: Drive-by (drive-by changes are dangerous precisely because their blast radius is unscoped — they touch code unrelated to the task), Load bearing , Seam (clean seams contain blast radius — a change behind a well-placed boundary can’t reach past it), Smoking gun (both are confidence claims worth checking — a smoking gun ends an investigation, a small blast radius ends a risk assessment).
Seed direction
A seed direction is an early, provisional statement of intent — a note about which way a piece of work should head — recorded into a tracking item before it’s a full plan, so later planning can grow from it. The imagery is horticultural: a seed is planted now and meant to germinate into something fuller later, and direction is the heading it’s meant to grow toward. I reach for it when you mention an approach in passing and I want to capture it somewhere durable — a task, an issue, a plan item — as the germ of work that hasn’t been fleshed out yet.
Verbatim: “you mentioned moving your tmux config out of ~/.init into the Endless directory as the concrete direction for E-1850. Want me to record that as a seed direction in E-1850, or are you keeping that in your VISION session?”
How this can affect you:
- It converts a passing remark into a tracked commitment. Recording something as a “seed direction” promotes an offhand thought into an artifact that future sessions will read as the intended approach. What you said while thinking out loud becomes what the task says to do — and the provisional quality of the original remark doesn’t always survive the trip into the tracker.
- The gardening metaphor smuggles in optimism. “Seed” frames the idea as viable and destined to grow. But a seed direction can be a half-formed or bad idea recorded faithfully; the imagery quietly asserts it will germinate into good work, when whether it should grow at all is exactly the open question.
- It may never germinate — and the note outlives the intent. Like a pilot that never lands, a seed direction can sit in a task after you’ve changed your mind. A later reader finds it and treats it as the settled plan, not the tentative starting point it was, because the record doesn’t carry the tentativeness the moment had.
Working with this: When I offer to record something as a “seed direction,” the worthwhile check is whether it’s actually a decision you want future work to grow from, or just a thought you were airing. If it’s tentative, say so — and it can be recorded as tentative, or not at all — so a future session doesn’t inherit a half-formed idea as a mandate. Note that the offer itself is a good place to intercept: I’m asking before planting, so that’s the moment to confirm the direction is real before it’s tracked.
See also: Pilot (both are forward-looking placeholders for work that may not have happened yet — a pilot is meant to become the template others copy, a seed direction the germ a plan grows from), Seam (the provisional-gap sense of seam is likewise a note standing in for work not yet done), Lock / Locking (recording a casual remark as a seed direction is a mild version of the same drift — a tentative thing hardening into a fixed one once it’s written down), Route / Routing (the two opposite fates of an offhand remark — planted in the tracker as intent, or handed back to you to route and quietly dropped).
Spike
A spike is a throwaway, time-boxed experiment: disposable code written purely to answer a technical question — “will this approach work?”, “how hard is this?” — and then discarded once the question is answered. The term is borrowed from Agile/XP, where a “spike solution” is a quick investigative implementation built to reduce uncertainty and then deleted rather than shipped. I reach for it when the goal of a piece of work is learning, not a deliverable — when what gets produced is an answer and the code that produced it is meant to be thrown away.
Verbatim, and the exchange that followed:
“Research/brainstorm with a spike child — weaker. Usually the implementation a research surfaces is a cleans_up/new task, not a child. It’s only a child if the throwaway must be built to answer the research question itself.”
— “What’s a ‘spike?’”
"‘Spike’ — borrowed jargon, my bad for not saying it plainly. A spike is an Agile term for a throwaway, time-boxed experiment — you write disposable code purely to answer a technical question (‘will this approach work?’) and then delete it."
How this can affect you:
- The imagery gives you no hook. Unlike seam or blast radius, “spike” carries no metaphor that hints at its meaning — the word doesn’t picture a throwaway experiment in any obvious way. A reader who hasn’t met the Agile sense has nothing to decode from, so “spike child” or “let’s spike this” reads as pure opacity. In the exchange above I conceded the label “added nothing.”
- It quietly asserts the code is disposable. Calling something a spike declares up front that the output will be thrown away. If that expectation isn’t shared, a spike’s code can survive — get committed, get built on — precisely because “spike” told you it was throwaway, so nobody scoped it to keep. The throwaway framing is a promise about what happens after, and the promise isn’t always kept.
- It collapses “experiment” and “deliverable” into one word. The whole point of the term is that a spike is not the real implementation. When I use it loosely — labeling actual production-bound work a “spike” — the disposability signal misfires, and a reader can’t tell whether the code is meant to last.
Working with this: When I call something a spike, the useful check is what happens to the code once the question is answered — is it genuinely thrown away, or is it the first draft of the real thing? If it’s disposable, “spike” is right and the code shouldn’t be reviewed or built on as if it were production. If it’s meant to survive, it isn’t a spike — it’s an implementation, and calling it one understates the care it needs. Plain substitutes — throwaway experiment, quick investigation — lose nothing and spare the decode.
Contrast with: Pilot (the opposite disposition — a pilot is the first instance built to be kept and copied as a template, where a spike is built to be discarded).
See also: Route / Routing (both are words whose plain substitute — throwaway experiment, decide who does it — carries the meaning the jargon leaves implicit).
Route / Routing
To route something is to send it toward its correct destination. The imagery is from networks, mail, and rail: a packet, a letter, or a train has somewhere to be, and routing is the act of choosing the path or the endpoint that gets it there. I use the word in two registers — about data and about work — and each one leaves out something different. Neither is self-explanatory.
The data sense names an actual path through a system: which database a binary reads, which build a hook executes, which formatter an error passes through. Verbatim: “DB routing can be provisioned at creation (and is), while code routing can’t be — its artifact isn’t built yet.”
This register sounds precise because there is a real thing being sent to a real destination. What it omits is the mechanism and the moment — what does the choosing, and when. Spelled out, the three examples above are three unrelated sentences:
- DB routing — the program opens a scratch copy of the database instead of the live one. Mechanism: a file path written in a config file. Moment: read once, when the program starts.
- code routing — a command runs the copy of a tool kept inside this project’s folder instead of the copy installed system-wide. Mechanism: the shell’s
PATHlookup, which takes the first match it finds. Moment: every single time the command is typed. - routing errors through the JSON reporter — the framework’s own argument-parse errors get printed by my formatter instead of its built-in plain-text one. Mechanism: an override hook the framework exposes. Moment: before my code runs at all.
Those share no mechanism, no timing, and no failure mode, and only the third involves anything passing through anything. “Routing” is the one word they have in common, and it names none of the differences. (The verbatim quote comes from a git worktree setup — a second checkout of the same project — but nothing about the ambiguity depends on that. Substitute any two destinations you like; the omissions are identical.)
The modifier can be as loose as the verb. “Code routing” is my coinage, and the same sentence quietly corrects it: what can’t be provisioned in advance is “its artifact” — the built executable — not the code, which is sitting in the checkout the entire time. Executable routing is what the phrase means. (You will see binary used interchangeably with executable for this, including by me. That one isn’t my coinage — it’s ordinary industry usage for a compiled program file, so called because its contents are machine code rather than readable text. Binary, executable, and artifact all point at the same file here.) The slippage is not cosmetic, because the two nouns imply different actions: an executable is a file, and files can be copied; “code” is an abstraction that has to be built. Reasoning about code routing made building feel necessary, and the plainest fix — copy the executable that already exists — stayed off the list of options for several turns. When a compound like this one reads oddly, checking whether the modifier names the actual thing is worth as much as decoding the verb.
The work sense applies the same verb to a piece of work rather than a piece of data — an issue, a finding, a request, a task — and there it collapses at least three separate decisions into one verb. Asked to say what I actually meant, I unpacked it as:
— "‘yours to route’ — You constantly use ‘route’ which I find to be ambiguous almost every time you use it. Say what you mean more explicitly."
“You’re right, and it’s a filler word standing in for a decision I should name. In that sentence I meant: you decide who works on it — I’m not filing a task for it. … Generally when I’ve written ‘route’ I’ve meant one of three concrete things: who works on it — reopen an existing task, spawn a session, or leave it; which task it belongs in — fold as evidence vs. file new; whether it gets done at all — act, park, or decline.”
Those three are genuinely different questions with different answers, different owners, and different consequences — and “route” reads identically for all of them.
How this can affect you:
- In the data sense, it names a destination and hides the machinery. You can agree that the database “routes to the scratch copy” and still not know whether that’s a config file, an environment variable, a symlink, a compiled-in default, or a runtime check — nor whether it’s settled once at startup or re-decided on every call. Those differences determine whether the behavior can be changed without a rebuild, what happens when the mechanism is missing, and where to look when it goes wrong. The word gives you the destination and withholds all three answers.
- The shared word makes unrelated mechanisms sound like one design. Once DB routing and code routing are both “routing,” they read as two instances of a common pattern — and the parallel wording invites reasoning by analogy between them. That is precisely how an invented constraint got built in the Case 6 exchange (
case-studies.md): from the database path can be set up in advance, the claim “code routing can’t be” followed from the assumed symmetry of the noun rather than from the facts, and it was wrong. The vocabulary did the arguing. - In the work sense, it names that a decision exists without naming which decision. “That’s yours to route” tells you a call is being handed to you but not what the call is about — staffing, filing, or go/no-go. You can accept the handoff and still not know what you just agreed to decide.
- The destination is left implicit, and the implicit destination is often “nowhere.” In the anchor exchange, “yours to route” concealed two facts that mattered more than the word itself: nobody picks this up unless you say so, and I deliberately did not file it anywhere. A word that sounds like dispatch was actually describing a non-action. Work that is “routed” in this sense can quietly cease to exist.
- It borrows confidence from a solved mechanism. Real routing is deterministic: a router consults a table and always knows where the packet goes. Carried into workflow talk, the word implies a settled routing table exists — an obvious right destination that just needs selecting — when the actual situation is that the destination is undecided and the judgment is the whole task.
- It hides which of three costs you’re accepting. “Fold this into the existing task” and “file a new one” and “drop it” have very different downstream effects on what future sessions read and act on. Compressed into “route it,” the cheapest interpretation tends to win by default, because no one had to state the expensive one out loud.
- The intransitive form describes deviation as navigation. “Claude routes around the design” means a cheaper unsupported path was taken instead of the intended one. “Routes around” makes that sound like ordinary pathfinding rather than a workaround worth noticing — the word supplies no signal that anything was bypassed.
Working with this: the useful question differs by register, and in both cases the answer fits in one plain sentence that “routing” is standing in for.
For data, ask what does the choosing, and when? The answer is a mechanism (config file, environment variable, path lookup, symlink, override hook, compiled-in default) and a moment (build time, process startup, every call). “The command runs this project’s copy of the tool, because the shell resolves the path fresh every time you type it” tells you what “code routing” does not. A second check is worth making whenever two things are described with the same routing word: ask whether they actually share a mechanism, or only share the noun — the parallel phrasing is not evidence of a parallel design.
For work, ask route where, and decided by whom? Two substitutions settle it. First, replace the verb with the specific act: assign, file as a new task, fold into E-1234 as evidence, park, decline, leave it and do nothing. Second, ask what happens if nobody does anything — if the answer is “it disappears,” that’s the fact “route” was obscuring, and it’s worth saying out loud before you accept the handoff.
Common collocations:
- “That’s yours to route” — you decide; I have not filed, assigned, or acted on it, and nothing happens until you say so.
- “Route this to X” — record or assign it in X; usually means filing, occasionally means “make X the owner.”
- “How do you want to route this?” — I’m asking you to pick among act / fold / file / park / decline without listing those options.
- “Routes around” — a cheaper path was taken instead of the intended one; a workaround described as navigation.
- “DB routing” / “code routing” / “route the parse errors through…” — the data sense; each names a destination while leaving the mechanism and the timing unstated, and the shared word does not imply a shared mechanism. Check the modifier too: “code routing” means executable routing, and the difference between the two nouns is the difference between copying a file and building one.
Contrast with: Surface (verb) (surfacing raises something into your view and stops there; routing claims to decide where it goes next — but in the workflow sense it often does no more than surfacing did).
See also: Surface (verb) , Seed direction (both are about what becomes of a passing remark — a seed direction over-commits it into the tracker, an unrouted item can vanish from it entirely), Materialize / Materialization (both are vocabulary where substituting the plain verb — write, assign — usually loses nothing), Frame / Framing (“route” is a framing choice: it presents an open judgment as a dispatch problem with a known destination), Sticking point (an item I hand you to “route” is frequently a sticking point I’ve declined to resolve).
See also: Materialize / Materialization (both are borrowed jargon that add decode overhead — the plainer phrasing usually loses nothing), Drive-by (a spike whose code gets kept instead of thrown away becomes an unscoped drive-by addition).
Found something wrong, unclear, or plainly disagreeable? Open an issue