Developer Tooling That Compounds Over a Career
The tools, shell setup, editor configuration and workflow automations that compound over a career — and how to build a setup that gets out of your way.

The Tooling Multiplier
Every developer has a setup that's either working for them or against them. The compounding effect of good tooling is dramatic over a career — if your tools save you 30 minutes per day, that's 120 hours per year. More importantly, reduced friction keeps you in flow states longer.
This is not about chasing the latest tools. It's about investing once in things that pay back every day.
Terminal: The Foundation
Your terminal is your command center. Time spent here is time multiplied.
Shell Configuration That Stays Out of Your Way
# .zshrc — the essentials
# Better history search
bindkey '^R' history-incremental-search-backward
# Fuzzy file finder — changes how you navigate
[ -f ~/.fzf.zsh ] && source ~/.fzf.zsh
export FZF_DEFAULT_COMMAND='fd --type f --hidden --follow --exclude .git'
export FZF_CTRL_T_COMMAND="$FZF_DEFAULT_COMMAND"
# Smarter cd — jumps to frecent directories
eval "$(zoxide init zsh)"
# z myproject → jumps to ~/code/projects/myproject
# Aliases that earn their keep
alias g='git'
alias gs='git status'
alias gl='git log --oneline --graph --decorate -20'
alias gco='git checkout'
alias gcob='git checkout -b'
alias gd='git diff'
alias gds='git diff --staged'
alias ..='cd ..'
alias ...='cd ../..'
alias ll='ls -la'Git Aliases for Daily Operations
# ~/.gitconfig
[alias]
st = status
co = checkout
br = branch
ci = commit
unstage = reset HEAD --
last = log -1 HEAD
visual = !gitk
# Undo last commit, keep changes staged
undo = reset --soft HEAD^
# Show files changed in last commit
show-files = diff-tree --no-commit-id -r --name-only -r HEAD
# Clean up merged branches
cleanup = "!git branch --merged | grep -v '\\*\\|master\\|main\\|develop' | xargs -n 1 git branch -d"
# Pretty log
lg = log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commitEditor: VS Code Configuration That Scales
The editor is where you spend most of your time. A well-configured editor removes constant tiny frictions.
// .vscode/settings.json — project-level settings committed to the repo
{
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit",
"source.organizeImports": "explicit"
},
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.tabSize": 2,
"editor.rulers": [100],
"editor.minimap.enabled": false,
"editor.bracketPairColorization.enabled": true,
"editor.inlineSuggest.enabled": true,
"files.trimTrailingWhitespace": true,
"typescript.preferences.importModuleSpecifier": "non-relative",
"typescript.updateImportsOnFileMove.enabled": "always",
"search.exclude": {
"**/node_modules": true,
"**/.next": true,
"**/dist": true,
"**/.git": true
}
}Extensions Worth Installing
For a TypeScript/React stack, these are the ones I reinstall on every machine:
ESLint — inline linting in the editor
Prettier — auto-formatting on save
GitLens — git blame, history, and diff in the editor
Error Lens — surfaces errors inline instead of on hover
Import Cost — shows bundle size of each import
Tailwind CSS IntelliSense — autocomplete for Tailwind classes
Thunder Client — lightweight API testing (replaces Postman for quick checks)
The Project Scaffold That Saves Hours
Every new project starts from scratch differently. A personal scaffold or template repository eliminates the "setup hour" at the start of every project.
# package.json scripts that the whole team uses
{
"scripts": {
"dev": "next dev --turbo",
"build": "next build",
"lint": "eslint . --max-warnings 0",
"lint:fix": "eslint . --fix",
"format": "prettier --write .",
"format:check": "prettier --check .",
"type-check": "tsc --noEmit",
"test": "jest",
"test:watch": "jest --watch",
"check": "npm run type-check && npm run lint && npm run format:check",
"prepare": "husky"
}
}# .husky/pre-commit — catch issues before they reach CI
#!/bin/sh
npx lint-staged// lint-staged.config.js — run only on changed files
{
"*.{ts,tsx}": ["eslint --fix", "prettier --write"],
"*.{css,md,json}": ["prettier --write"]
}Automation: The Things You Should Never Do Manually Twice
#!/bin/bash
# scripts/new-feature.sh — start a feature branch with all setup done
BRANCH_NAME="feat/$1"
git checkout main
git pull origin main
git checkout -b "$BRANCH_NAME"
echo "Branch $BRANCH_NAME created and ready"
echo "Remember to: create a draft PR early, enable CI"// scripts/check-env.ts — validate env vars at startup
const required = ["DATABASE_URL", "NEXTAUTH_SECRET", "NEXTAUTH_URL"] as const;
const missing = required.filter((key) => !process.env[key]);
if (missing.length > 0) {
console.error(
`Missing required environment variables: ${missing.join(", ")}`,
);
console.error("Copy .env.example to .env.local and fill in the values");
process.exit(1);
}The Compounding Habit
The best tooling improvements compound because they change behavior:
- Format on save eliminates formatting discussions from code review
- Pre-commit hooks eliminate lint failures from CI
- Good git aliases make branching feel effortless — so you branch more freely
- A fast terminal makes you more comfortable in the command line
Invest one afternoon setting up your environment properly. Then invest another whenever you catch yourself doing something manual that feels repetitive. Over a year, the accumulated return on that time is enormous.
The goal isn't the fanciest setup — it's a setup where the tools are invisible and you're thinking only about the problem.


