Developer Tools

Tooling should make the safe path short

3 min read

Tooling should make the safe path short.

That sounds obvious until you watch a team under pressure.

If the careful workflow takes five commands and the risky workflow takes one, people will use the risky workflow. They will mean well. They will know better. They will tell themselves this change is tiny. Then the one-command path becomes the real process and the documented careful path becomes theater.

command length is policy

Every repo has an unofficial policy encoded in command length.

If pnpm build is fast and pnpm check is slow, developers will build more often than they check. If the deploy command skips tests, that is the deploy process, regardless of what the wiki says. If opening a PR is easy and writing a useful description is manual, descriptions will rot. If the rollback command is scary, people will hesitate during the window when speed matters.

The tool path becomes the culture.

boring scripts beat heroic memory

I like boring scripts because they turn the careful thing into one handle.

{
  "scripts": {
    "check": "astro check && rumdl check . && vitest run",
    "preflight": "pnpm check && pnpm build",
    "dev:clean": "pnpm stop && pnpm reset && pnpm dev"
  }
}

Those names are not clever. They give people a short handle for the careful thing.

safety should be the default branch

Dangerous operations should require extra intent. Safe operations should be cheap.

For example, a deploy tool should probably default to a preview or staged environment:

deploy              -> preview
deploy --prod       -> production
deploy --prod --yes -> production without prompt

The flags tell a story. Production is possible, but it is not the accidental path.

The same principle applies to database tools, migration runners, file cleanup scripts, AI agents, and local reset commands.

receipts matter

A short safe path should not be invisible.

If the tool fixes formatting, it should say which files changed. If it runs migrations, it should print the migration names. If it deploys, it should print the version, commit, environment, and URL. If it asks an AI agent to edit code, it should record the goal and the verification command.

preflight
  commit: 9f31a2c
  markdown: pass
  astro: pass
  build: pass
  artifact: dist/

That output is small, but it gives the next person a receipt.

the recovery path is part of safety

It is not enough to prevent mistakes. Tools should help recover from ordinary ones: stale dev servers, stuck ports, failed migrations, half-written generated files, dirty build artifacts, abandoned branches, broken caches.

pnpm dev:clean is a better command than making everyone remember a sequence of stop, reset, and start steps. The same logic applies to production: a deploy tool should know the last good version, and a migration tool should say whether rollback exists.

Safety without recovery becomes anxiety.

cheap checks belong near the change

A check that takes twenty minutes has a different job than a check that takes ten seconds.

I like layered checks:

save:      format touched file
precommit: typecheck changed package
prepush:   test affected packages
ci:        full test and build matrix
release:   smoke deployed artifact

Put the cheap signal close to the person making the change. Put the expensive signal where it can run without blocking every thought.

If the only safe path is slow, people will invent a faster unsafe path.

That applies hard to agent workflows too. If asking the agent to verify the change is harder than asking it to edit the file, verification will be skipped. The safe path should be the short one.

Jeremy London

About Jeremy London

Engineering leader and builder in Denver. I write about AI platforms, agents, security, reliability, homelab infrastructure, and the parts of engineering work that have to survive production.