I tried an experiment on myself: lean hard on tab completion and IntelliSense-ish shell helpers for two weeks, and deliberately not study exit codes beyond vibes. I wanted to see how far ergonomics carry you.
Far enough to look productive. Not far enough to be safe.
The seductive part
Tab completion reduces spelling errors. It surfaces parameters. It makes PowerShell feel modern. Students love it. I love it. This post is not anti-completion.
It’s anti-substituting UX for semantics.
Where I got burned
Pipelines that “looked fine”
A native tool failed halfway. The screen still printed something. Because I didn’t check $LASTEXITCODE / %ERRORLEVEL%, a later step ran on partial output. Tab completion had helped me type the broken pipeline faster.
CI vs laptop gap
Locally, aliases and profile helpers padded mistakes. In CI, bare shells told the truth. Completion wasn’t available in the same way; exit codes suddenly mattered and I had no muscle memory.
False green in batch wrappers
A .bat called a tool, ignored failure, exited 0 by accident of flow. The wrapper “completed.” Completion never enters that story. Semantics do.
The tiny model that actually saves you
Processes signal outcome with an exit code. By convention, 0 means success; non-zero means failure (with program-specific meanings).
PowerShell complications worth learning early:
-
$LASTEXITCODEfor native executables. -
-not $?/$true$falsepatterns for shell-level success. - Cmdlet errors vs native exit codes—different channels.
CMD:
mytool.exe
echo %ERRORLEVEL%
PowerShell:
mytool.exe
$LASTEXITCODE
Put that reflex before you chase prettier prompts.
The i_tried rule I kept afterward
For every new tool, I practice one happy run and one forced failure, then read the code. Tab-complete the flags. Still read the code.
When teaching, I now introduce completion as a speed tool after a first intentional failure exercise. Otherwise learners optimize for “command accepted by the completer,” not “operation succeeded.”
Product note
Two-week experiment protocol (replicable)
- Week A: completion on, exit-code checks off (honor system).
- Week B: completion still on, but every native call followed by an explicit status check in a learning log.
My log’s Week A was full of “looked fine.” Week B caught three silent partial failures I’d have pasted into a ticket as “weird output.”
Teaching script you can steal
- Run a command that succeeds; show
0. - Run a command that fails; show non-zero.
- Chain with
&&/||(CMD) or PowerShell equivalents carefully. - Only then celebrate tab completion as speed—not as truth.
PowerShell-specific footgun
Cmdlet errors and native exit codes aren’t the same channel. A pipeline can look chatty while $LASTEXITCODE still says the native tool failed. Completion won’t narrate that. Your checklist must.
Incident postmortem one-liner
“The command looked correct and the completer accepted it” is not a root cause. “We didn’t check the exit code before the next step” often is. Write that on a card. Completion stays; accountability stays harder.
Pairing exercise (five minutes)
Driver types a failing command on purpose. Navigator must state the exit code before suggesting a fix. No googling until the code is spoken aloud. It feels pedantic. It builds the reflex completion can’t.
Speed without a status check is just faster fiction.
Interactive drills are perfect for this: hide the next step behind a checked exit code. That’s a pattern I use while refining CMD Master—completion optional, outcome mandatory.
Ergonomics help you type. Exit codes tell you whether you should have.
Top comments (0)