I shipped a small CLI tool last week and ran it for the first time on my own machine. The output had a number that read 1,28,000 instead of 128,000. I stared at it for a minute, ran the same code in a node REPL, got the same wrong number back, and realized my locale was doing it. A few hours later I had four entries in my CLAUDE.md file that I should have written months ago.
Here they are.
1. Always pass an explicit locale to toLocaleString
Bare (128000).toLocaleString() is a trap. It uses whatever the system locale happens to be. On my machine that's en-IN, which renders 128000 as 1,28,000. On a US-locale machine the same code returns 128,000. The bug only shows up where the locale is set, which means CI passes, your unit tests on a fresh container pass, and the wrong separators land in production output.
// don't
total.toLocaleString()
// do
total.toLocaleString('en-US')
The rule I added: any time you generate number-formatting code for CLI or any user-facing text, pass an explicit locale. Never call it bare.
2. Keep CLI output for AI-editor tools under five lines
I learned this one by watching myself ignore my own tool. I'd built a small command for inspecting build artifacts and ran it inside an AI assistant's terminal. The result was a 12-line printout with the answer near the bottom. The assistant collapsed it behind a Ctrl+O to expand prompt, and I never expanded it. The agent reading the output never saw the result either.
If a CLI is designed to run inside an AI assistant's bash, the design constraint is that assistant's read window, not your own terminal. Result plus summary in 4 to 5 lines max. Verbose mode behind a flag.
✓ build ok
3 packages, 412kb gzipped
fastest: core (180ms)
slowest: ui (910ms)
That fits. Anything more elaborate gets folded behind the expand prompt and effectively disappears from both you and the model.
3. npx <package> fails inside the package's own monorepo
I burned half an afternoon on this one. I was developing the CLI inside a pnpm workspace, ran npx my-cli to smoke-test it, and got resolver errors. The package built fine. The bin field was correct. Outside the repo it ran clean. Inside the workspace, the resolver had different ideas about which version of which thing to use, because workspace context confuses it.
The fix is not a fix, it's a docs entry. If a CLI lives in a monorepo, your README should say install globally with npm install -g or run from outside the project directory. The rule I added to CLAUDE.md tells the assistant to never suggest npx <pkgname> as a smoke test from inside the same repo that defines the package.
4. Shared-library fixes need version bumps on both sides
I had a CLI that depends on a small library of mine as an external npm package, not a bundled module. I found a bug in the library, fixed it, ran the CLI's tests against the local working tree, everything passed, and shipped. The bug was still live.
The CLI's package.json was pinned to the previous library version. Fixing the library does nothing downstream until you publish a new version of the library AND bump the consumer's dependency to match. Local test runs lie because they resolve to your working tree, not the published artifact.
The rule, copy-paste:
If a fix touches a shared library that the consumer depends on as
an external npm package (not vendored, not workspace-linked):
1. Publish the library with a new version
2. Bump the consumer's dep range
3. Publish the consumer
Otherwise the fix doesn't ship.
I added that to CLAUDE.md as a checklist the assistant walks through before claiming a bug is fixed.
Closing
If you want to copy one of these into your own setup, here's the format that works in CLAUDE.md, cursor rules, or copilot instructions:
When generating any number-formatting code for CLI output or user-facing text, always pass an explicit locale to
toLocaleString(typically'en-US'). Never call it bare. System locale varies by region and produces wrong thousands separators (e.g.1,28,000instead of128,000).
Add it once, save yourself the next version of this same day.
Top comments (0)