The Engineering of Intent, Chapter 34: Language-Specific Field Notes

This is Part 34 of a series walking through my book The Engineering of Intent. In the previous chapter, we built a personal OS. Chapter 34 moves from the general to the specific: field notes on how Vibe Coding plays out in eight different languages.


Same Patterns. Different Textures.

The underlying patterns in this book transfer across languages. The textures don’t. Chapter 34 is eight field notes — read the ones relevant to you.


The Eight, Compressed

  1. TypeScript. The language where Vibe Coding works most smoothly. Strict mode always. Ban as any in conventions; a type error is a real signal. Change types before writing bodies.
  2. Python. Most tempting to do sloppily. Permissive language means strict tooling: type hints, mypy/pyright strict, ruff, black, pytest. Agents love one-liners; if a one-liner takes longer to read than a three-line loop, the three-line loop wins.
  3. Go. Least-surprising agent output. Errors as values. Never panic in library code. context.Context first. Push back on JavaScript-flavored cleverness; idiomatic Go is flat.
  4. Rust. Most rewarding and most demanding. Expect a two-pass workflow (attempt → compiler rejection → revise). Watch for .clone() everywhere — usually the fix is borrowing correctly, not cloning.
  5. Java/Kotlin. Agents default to Java 8 style. Pin the target (“we’re on Java 21; use records, pattern matching, text blocks”). Kotlin lands as Java-flavored unless you push; lean on val, data classes, coroutines.
  6. Ruby. Agents pick the clever over the idiomatic. Metaprogramming is a minefield — justify any method_missing in a comment linking to design discussion. Specify whether the project is Rails or not in agents.md.
  7. C# / .NET. Well-represented in training. Nullable reference types everywhere. Records for data. async/await discipline is non-negotiable; agents occasionally forget ConfigureAwait. Pin the target framework.
  8. Shell. The language I trust agents least with. Not because the shell is bad, but because shell silently fails in so many ways that even correct-looking shell can destroy things. set -euo pipefail at the top. Quote every expansion. Never eval. Shellcheck is authoritative.
💡 The cross-language pattern: In every language, agents default to the idiom most represented in public training data. That’s usually 2–5 years behind the current best practices in a professionally-run codebase. The fix is always the same: pin your target version and idiom explicitly in agents.md. Without pinning, you’re getting the average of the internet, not your codebase.

The TypeScript Prompt Worth Stealing

“Propose a change to the types before writing implementation. Show me the type signatures; do not write bodies yet.” Changing types first forces design thinking. Implementation is easier after types stabilize. Versions of this prompt work in every typed language — Rust, Go, Java, C#, Kotlin. Borrow it.”

âš  The one you’re least expecting: Ruby. Agent-generated Ruby looks beautiful and is often painful to maintain. The metaprogramming that makes Ruby expressive also makes it nearly impossible to debug when it goes wrong. Prefer explicit code over metaprogramming in any project that will outlive its author — and push back when the agent reaches for a method-missing solution.

Next up — Chapter 35: A Short Bestiary of Vibe Coders. If Chapter 34 catalogs the languages, Chapter 35 catalogs the people — a short bestiary of the archetypes you’ll encounter on AI-native teams, how to recognize each, and how to work with each productively.


📖 Want the full picture?

The chapter walks all eight languages with specific practices, agent-specific pitfalls, reference prompts, and the idioms to pin in agents.md for each.

Get The Engineering of Intent on Amazon →

2026-05-20

Sho Shimoda

I share and organize what I’ve learned and experienced.