The license that flipped Apple
Bash 4.0 was released in 2009 under GPLv3. Apple's lawyers do not like GPLv3 (it adds patent and anti-tivoization clauses they read as risky for an OS vendor), so the macOS bash stayed at 3.2 — the last GPLv2 release — for more than a decade. By 2019 that bash was 12 years out of date. macOS Catalina switched the default login shell to zsh, which ships under the permissive MIT-style zsh license, and Apple has been on a current release ever since.
What zsh gives you over bash 3.2
- Real completion engine —
compinitplus thousands of community completion files. Tab ongitshows branches, onkubectlshows pods. - Recursive globbing —
**/*.pymatches every Python file under the current directory. Nofindneeded for the common case. - Glob qualifiers —
*(.om[1])means "the most recently modified plain file in this directory." Compact and fast. - Themed prompts — Powerlevel10k, Starship, Pure. Git branch, Python venv, Kubernetes context, all in the prompt without scripting.
- Plugin ecosystems — Oh-My-Zsh, Prezto, zinit. Drop in auto-suggestion, syntax highlighting, history search.
What zsh keeps from bash
Almost all interactive bash habits work — $(...), [[ ]], $?, $0, here-docs, set -e, arrays. The differences only show up in tricky places: word splitting, glob behavior, read flags, array indexing (zsh starts at 1 by default — see the scripting track).
When to script in zsh vs bash
For scripts you keep on your own laptop, zsh is fine. For scripts you ship to servers, container images, CI runners, or other developers' machines, write bash or POSIX sh — bash is on every Linux distro, zsh is not. The shebang decides; the body has to match.