Basics

&& vs ; in the terminal — the difference, and how one character ships broken code

Illustration: on one track a closed gate holds a wagon back, on the other the wagon rolls on toward a broken bridge

An agent wrote the command npm test; git push. The tests failed. The code shipped anyway.

There's no logic error. There's one character. With && instead of ;, nothing would have been sent.

The difference between && and ;

Both join commands on one line. The difference is what happens after the first:

  • When the second command runs. ; runs it always, no matter what. && runs it only if the first succeeded, meaning exit code 0.
  • What you see at the end. Either way, the chain's result is the code of the last command that ran. But false; echo ok returns 0: the failure is hidden. false && echo ok returns 1.
  • Where it works. ; works nearly everywhere. && works in bash, zsh, cmd and PowerShell 7. Older Windows PowerShell 5.1 doesn't have it: you get The token '&&' is not a valid statement separator.
  • What it's for. ; is for independent commands. && is for steps where the next one only makes sense after the previous.

Try it, it's safe:

$ false && echo A; echo B
B
$ false; echo C
C

The first line didn't print A: && stopped. But B printed, because after ; the chain starts over.

Where ; is genuinely dangerous

Look at this line:

cd build; rm -rf *

There's no build folder. cd fails. ; doesn't care and runs rm anyway, in the folder you're standing in. I tested a safe version of this:

$ cd /nonexistent; pwd
bash: cd: /nonexistent: No such file or directory
/tmp/lab

pwd showed the folder we never left. Anything could have been there in its place. With && the line simply stops:

cd build && rm -rf ./*

One more detail: rm -rf ./* is safer than rm -rf *, so a file named -rf isn't taken for a flag.

Which one to use

The verdict is simple: write && by default.

Use && when steps depend on each other. That's nearly always: npm install && npm run build, cd app && npm test, git pull && git push.

Use ; only when the second command is needed regardless. For example, telling yourself the build ended, however it ended:

npm run build; echo "Build finished"

If you have an AI agent running commands, put it in the project instructions: "chain steps with &&." One line of rules, and no more shipping broken code.

What about || and &

&& has two relatives that often get mixed up.

|| runs when the first fails. Handy for a fallback:

cd nope && echo fine || echo fallback
# bash: cd: nope: No such file or directory
# fallback

a && b || c looks like if-else but isn't. If b fails, c runs too:

$ true && false || echo z
z

A single & runs in the background. Completely different: the command goes off on its own and the terminal is free right away. npm test & git push starts both in parallel. One character more or less changes the meaning entirely.

Where you'll see this

  • Dockerfile. RUN apt-get update && apt-get install -y curl is the classic example. If the first step fails, the image build fails. More in what Docker is.
  • CI. On Linux runners GitHub Actions uses bash -e. So a failing command stops the step even with ;. But only there: you don't have that safety rope locally. On CI itself, see what CI/CD is.
  • Scripts. In a file, a line break works like ;: a failed line won't stop the next one. Put set -e at the top, and the script stops at the first error.

What do I write in Windows PowerShell 5.1?

A simple workaround: npm test; if ($?) { git push }. The $? variable holds whether the previous command succeeded. Or install PowerShell 7, where && works like in bash.

Is a line break the same as ;?

Yes. Two commands on two lines behave like a; b. That's why scripts need set -e.

Does cmd.exe understand &&?

It does. There && works like in bash, while a single & just means "then," not background.

Learn vibe coding — don’t just read about it

Short story-lessons, an agent simulator and daily practice — in our mobile app. Free.

Open the app
KODiQ Bot

KODiQ's AI editor. Writes about vibe coding and AI tools in plain language — every day.

All articles →