Introduction
Aaah... Choisir son shell!
Voilà une préoccupation majeure de la population en âge de voter qui mérite un peu plus d'attention.
C'est qui la dernière personne qui vous a parlé de son shell? Ça peut même pas être moi pour une fois. Enfin je pense.
Le shell ZSH (prononcé ziiii chail) n'a rien de récent ni "cool" (date de 1990 lol). Pourtant, il est populaire chez les plus bricoleurs d'entre-nous en plus d'être le shell par défaut sur Mac.
La plupart des gens l'accompagnent d'une config nommée OhMyZsh pour avoir une invite de commande de HACKER.
En fait on a pas du tout besoin de ce truc et je vais même vous proposer une alternative plus moderne et très probablement plus rapide, avec une config minimale que même votre petit frère pourra comprendre.
Au programme on aura:
- Une invite de commande moderne générée par Starship.rs;
- L'auto suggestion ZSH basée sur l'historique;
- Des top-cool fonctionnalités de recherche de l'historique avec fzf;
- La coloration syntaxique ZSH si ça vous intéresse.
En pratique ce dont je parle dans cet article fonctionne aussi sur Mac mis à part que les programmes et comment les installer diverge (Homebrew devrait cependant disposer de toutes les ressources), et vous aurez déjà une config .zshrc existante sur le Mac qu'il faudra bien sauvegarder et utilser comme point de départ.
C'est quoi cette histoire de shell?
Le shell est en réalité un terme générique qui désigne vaguement un programme permettant d'interagir de manière interactive avec un ordinateur.
Il tourne typiquement en mode "utilisateur" mais permet d'accéder aux fonctionnalités du noyau du système d'exploitation comme créer et lire des fichiers, d'où son nom qui signifie carapace ou enveloppe à imaginer autour du dit noyau.
Un peu comme un marron et sa bogue mais je pouvais pas prendre ça comme exemple parce que quelqu'un a décidé que bogue voulait dire autre chose dans un contexte de programmation d'ordinateurs mais bon voilà je viens de le dire quand même.
Quand les gens parlent de shell, ce qui apparaît dans votre tête est générallement une ligne de commande (ou un singe qui joue des cymbales).
Pour utiliser la ligne de commande depuis les années 2000 on passe générallement par deux programmes distincts:
- Un émulateur de terminal;
- Un shell (OH BEN ÇA ALORS).
L'émulateur de terminal est plutôt appelé juste "terminal" par les gens normaux.
Peu de gens savent qu'il se comporte vaguement comme les plus anciens terminaux humains. Enfin, pas ceux en pierre sur lesquels on dessine des bisons avec son caca mais on en est pas très très loin non plus.
Le nom TTY qu'on peut parfois observer sous Linux ou BSD fait référence à une machine "teletype".
Ces terminaux servaient à envoyer et recevoir des TELEGRAMMES. Oui, les messages en morse envoyés sur une ligne électrique dont on parle dans les vieux dessins animés où on voit un opérateur appuyer en rythme sur un gros bouton qui fait beep beep.
Les opérateurs ont rapidement été remplacés par le chatGPT du télégramme, ces fameuses machines Teletype.

Pourquoi je parle de tout ça? He bien mes amis, ces machines avaient déjà des séquences d'échappement spéciales basées sur un genre de touche Ctrl et aussi Esc.
Par exemple, Ctrl+C avait pour effet d'interrompre ce qu'il se passe (et peut-être aussi passer en "mode commande" je vais pas prétendre être expert en terminaux des années 60) exactement comme dans nos émulateurs de terminaux en 2025.
- Mais attends une minute monsieur du blog, Ctrl+C c'est COPIER DANS LE PRESSE PAPIER, NON?
BEN NON. Jamais. Pas dans un émulateur de terminal. Il faut générallement utiliser Ctrl+Shift+C de nos jours, et le "presse papier" n'existait évidemment pas dans les années 60. Et 70. Et 80.
- J'ai le Windows Terminal sur mon système d'exploitation moderne basé sur MSDOS (lol) et Ctrl+C copie dans le presse papier.
Effectivement mais uniquement parce que Microsoft a décidé de se couper en 1000 pour le permettre, parce qu'ils doivent tout de même autoriser Ctrl+C à envoyer un signal d'interruption sans quoi certains programmes ne pourront plus être arrêtés.
Il en résulte tout un plan où le Windows Terminal détecte si du texte est sélectionné, auquel cas il n'envoie pas de signal d'interruption et copie le dit texte dans le presse papier.
En pratique personne se casse les billes à faire ça à part Microsoft et tu dois apprendre par la douleur ce que certaines de ces vieilles séquences de contrôle font. Par exemple Ctrl+R ou Ctrl+Z (un des plus rigolos par ailleurs).
Alors oublie ton copier coller et revenons dans les années 60 0KAY??
Et dans les années 70, 80 et toutes les autres aussi parce que les terminaux d'accès des gros ordinateurs qui suivront hériterons tout autant d'à peu près les même séquences de contrôle et d'échappement.
Bon et le shell alors?
L'autre programme qui tourne dans l'émulateur de terminal est un shell en ligne de commande.
Il en existe plusieurs, même sous Windows. Citons par exemple le vénérable cmd.exe héritier du glorieux passé MSDOS de Windows, ou encore PowerShell: un shell assez novateur dans son approche qui consiste à utiliser des objets en entrée et sortie des commandes plutôt que du texte, et d'avoir les noms de commande les plus longs et foireux possibles au monde.
D'ailleurs, je livre une petite astuce gratuite totalement hors sujet pour nos amis qui utilisent Windows: Il y a deux Powershell.
Celui qui est installé avec Windows est en fait lent (je n'ai absolument aucune idée de pourquoi) et dénué de certaines fonctionnalités dont la suggestion automatique de commandes de l'historique pendant une saisie.
Vous voyez peut-être pas de quoi je parle par autosuggestion, on en reparlera plus tard parce qu'il s'agit d'un aspect que les gens attendent de zsh et demande l'ajout d'un script externe (alors que c'est natif sur PowerShell (et fish) vous l'imaginez ça?).
Pour installer le "vrai" PowerShell depuis Windows 11, ouvrez une invite du PowerShell null et entrez:
winget install Microsoft.PowerShell
Une entrée "PowerShell 7" devrait ensuite apparaître dans les programmes ainsi que dans les profils de Windows Terminal (à condition de le relancer).
A vous de constater non seulement l'autosuggestion liée à l'historique mais aussi la coloration syntaxique (un autre truc qu'on ajoutera à zsh):
Okay je pense qu'on s'est un peu égarés, revenons au sujet.
Pourquoi pas utiliser bash?
J'utilise moi-même Bash.
C'est le shell le plus utilisé sous Linux qui est presque toujours celui par défaut (à moins d'être dans un container "léger" ou une distribution étrange).
Pourquoi? Il est étroitement lié au projet GNU et les ajouts de bash en terme de script sont couramment utilisés.
On peut tout à fait utiliser des scripts "pour bash" depuis zsh, mais ce qui se passe c'est qu'ils sont exécutés avec bash. Et pas zsh.
Ce qui n'est toujours pas un problème mais signifie qu'on a de toutes manières besoin de bash pour les script donc tant qu'à faire autant qu'il soit le shell par défaut.
Par contre, bash manque de fonctionnalités: pas d'autosuggestion, coloration syntaxique, positionnement d'infos sur la droite de l'invite de commande, et cetera.
Les fans de zsh citent souvent que le binaire de bash est plus volumineux que celui de zsh. Mais ça veut absolument rien dire, on peut avoir un énorme binaire juste parce qu'il est rempli de texte, documentation, etc.
Néanmoins, je suis d'accord que bash est capable de moultes exploits relativement peu usités, et j'ai vu des pseudo-preuves que zsh serait un peu plus rapide pour exécuter du script sauf que, comme je le disais plus haut, ces scripts sont toujours prévus pour invoquer /bin/bash, ou /bin/sh qui est soit un lien vers bash, soit un lien vers un "shell léger" qui sera plus rapide que zsh dans tous les plans de l'univers.
Je suis plus intéressé par une invite qui est réactive chaque fois qu'on tape sur Enter, et c'est pour ça que j'utilise personnellement bash et pas zsh (avec fzf pour la recherche dans l'historique, que je proposerai plus tard avec zsh aussi).
Alors, disons-le tout de suite, sur un ordi assez balaise vous ne verrez aucune différence. Sur mon ancien ordi portable avec Manjaro (une distribution qui utilise zsh par défaut avec quelques plugins), ça se sentait.
Enfin bon, ma config bash est hors sujet de cet article en plus d'être assez inintéressante.
Et euh... Pourquoi Zsh?
Ben je sais pas trop.
Il y a un autre shell, fish, qui a pas mal de fonctionnalités natives qu'on doit ajouter à zsh par après.
Ceci dit je pense qu'il est plus lent. Je pense?
Ce post pourrait être une bonne intro pour savoir si vous avez envie d'aller plus loin dans cette histoire de shell.
En soi, zsh n'est pas vraiment plus récent que bash, ils datent tous les deux des années 90.
C'est surtout que l'un est sous licence GPL et jaillit du projet GNU, l'autre euh... Vient d'ailleurs, avec une licence plus permissive et moins contagieuse.
Je pense qu'une raison importante de choisir zsh dans le passé c'était Oh My Zsh.
Je dis "dans le passé" puisque cet article démontre qu'on en a pas besoin.
Et c'est pas mieux "OhMyZsh" que Starship?
Starship ne s'occupe que de personnaliser l'apparence de l'invite de commande, OhMyZsh fait plus de choses.
Starship est plutôt comparable à Powerlevel10k qui est utilisé par défaut dans la distribution Linux Manjaro, par exemple.
Tout ceci implique d'exécuter plus de choses qu'avant à chaque presse de la touche Entrée.
Est-ce que c'est pire d'exécuter un programme à part entière comme Starship (écrit en Rust) ou le subshell assez complexe de Powerlevel10k ou autre?
Ben écoutez, j'en sais rien, ça a l'air impossible de mesurer la performance de la "vitesse d'apparition" de l'invite de commande, vous allez devoir le VIVRE.
Personnellement j'utilise bash avec une invite ultra simple mais je me souviens que l'invite de Manjaro était un peu lente sur un ordi modeste.
Et, de fait, si on compare la variable $PS1 (contrôle le formattage de l'invite de commande) de Manjaro (zsh) avec la mienne (bash):

Quoi qu'il arrive l'invite doit, par exemple, lancer git status et regarder d'autres choses dans le répertoire courant.
Au moins, Starship peut le faire avec plusieurs threads et n'a peut-être pas besoin d'invoquer des programmes externes.
Je n'ai aucune idée de ce qu'ils font en pratique mais c'est plausible que ça soit un poil plus performant que les autres Powerline et OhMyZsh.
Prérequis
Les commandes d'installation sont celles de la famille Debian (inclus Ubuntu) mais ça devrait être facile à transposer pour d'autres familles Linux.
Pour la base, vous pouvez déjà vous assurer d'avoir ceci:
sudo apt install git curl
LE Nerd Font
Première étape: s'assurer de disposer d'une NERD FONT et de la configurer dans votre émulateur de terminal.
Ce sont des polices de caractère qui ont été modifiées pour supporter une grosse pelletée de symboles supplémentaires.
Le concept s'appelle "nerd font" car totalement inutile mis à part pour des applications en ligne de commande, en particulier ce bon vieux Neovim ou encore LSD et alors, bien sûr, les quelques projets d'invite de commande pimpée.
Il existait d'autres types de polices patchées avant les Nerd Font mais ces dernières ce sont imposées ces dernières années.
Rendez-vous sur leur page de téléchargement pour en choisir une ou deux selon vos goûts, votre police préférée est peut-être dans la liste.
Si vous utilisez Wezterm ou Ghostty comme émulateur de terminal, ils embarquent la version Nerd Font de JetBrains Mono et l'activent par défaut.
Je pense que Wezterm dispose par ailleurs d'un artifice qui substitue automatiquement les symboles de cette police si vous en utilisez une autre qui ne les as pas, mais je me trompe peut-être sur ce coup-là.
fzf
Si vous ne l'aviez pas encore, c'est toujours bon à avoir.
Il s'agit d'un adaptateur de recherche floue qui agit sur des lignes de texte à lui fournir comme un bon utilitaire suivant la philosophie UNIX.
Il y a générallement un paquet "fzf" dans le gestionnaire de paquets des distributions Linux, mais celui de la famille Debian est super vieux.
Sur Arch vous aurez sans doute une version qui va bien à installer avec Pacman.
Nous autres sur Ubuntu et connexes, on va devoir l'installer manuellement.
Rendez-vous sur la page de releases du projet et choisissez le bon paquet cadeau pour votre architecture sur la dernière version.
Par exemple, je suis sur du PéCé standard donc je prends l'archive pour amd64.
Décompressez l'archive et bougez-moi ça dans /usr/local/bin (ou .local/bin ou autre si vous préférez) — Voici une procédure complète pour une version ultra spécifique et mon architecture:
wget https://github.com/junegunn/fzf/releases/download/v0.67.0/fzf-0.67.0-linux_amd64.tar.gz
tar -xf fzf-0.67.0-linux_amd64.tar.gz
rm fzf-0.67.0-linux_amd64.tar.gz
sudo mv fzf /usr/local/bin
Et voilà pour fzf.
Installation
Commencer par Starship.rs tant qu'on y est:
curl -sS https://starship.rs/install.sh | sh
Normalement c'est mieux d'aller voir d'abord ce que fait ce script avant de l'exécuter automatiquement. D'autant plus que les droits d'administration vous seront demandés mais uniquement pour copier l'exécutable dans /usr/local/bin.
On peut laisser starship reposer et passer à zsh suivi du changement de shell de votre utilisateur:
sudo apt install zsh
chsh -s /usr/bin/zsh
Reste à relancer la session en cours (déco-reco suffit normalement, redémarrage complet est plus sûr) et vérifier si vous êtes bien dans zsh:
echo $0
# OU BIEN
echo $SHELL
Normalement zsh devrait vous montrer un écran d'accueil avec un dilemme numéraire complexe à réaliser — Si cet écran ne s'affiche pas, entrez simplement la commande "zsh" et ça devrait apparaitre:
Prenez l'option 2 pour voir ce qui est proposé par défaut même s'il y a peu de chances qu'un programme des années 90 change de config par défault dans les 2 ou 3 ans mais bon qui sait.
Configuration
Commençons par éditer le fichier .zshrc qui vient d'être créé à l'étape précédente et qui devrait se trouver en plein milieu de votre répertoire HOME.
Vous pouvez déjà virer les premières lignes qui parlent de prompt comme montré ici:
Laissez bien les options d'historique et le bindkey -e.
Ajouter ces deux lignes pour que Ctrl+Droite et Ctrl+Gauche permettent de se déplacer de mot en mot, comme un peu partout ailleurs dans le monde (fonctionne dans les navigateurs par exemple (et aussi VS Code) et ça change la vie):
bindkey "^[[1;5C" forward-word
bindkey "^[[1;5D" backward-word
Ce comportement est par défaut avec bash.
Modifiez ensuite HISTSIZE et SAVEHIST pour leur donner une valeur bien plus élevée, par exemple:
HISTSIZE=15000
SAVEHIST=15000
Il devrait déjà y avoir de quoi obtenir la coloration syntaxique de ls lors de complétion avec tab, mais pas quand on utilise ls normalement.
Du coup, à moins que vous soyez passés sur LSD (auquel cas il vous faudra de toutes manières un alias), voici les lignes à ajouter pour avoir la coloration de ls et grep:
alias ls='ls --color=auto'
alias grep='grep --color=auto'
alias fgrep='fgrep --color=auto'
alias egrep='egrep --color=auto'
A la fin du fichier on va ajouter la config fzf suivie de la config starship qui doit absolument être la dernière ligne (enfin, c'est ce qu'ils disent dans la doc):
source <(fzf --zsh)
eval "$(starship init zsh)"
Après avoir sauvegardé ces changements, on peut déjà tester à quoi ça ressemble avec un petit:
source ~/.zshrc
Ce qui devrait afficher quelque chose dans ce genre si vous avez bien suivi toutes les étapes préalables:
Un petit élément de base de Starship est la couleur du chevron (ou flèche?): vert si la dernière commande avait un code de retour de 0, rouge autrement.
Ajout de quelques extras pour zsh
Il nous manque l'autosuggestion et peut-être la coloration syntaxique.
Ce sont des "plugins" dans d'autres contextes d'utilisation de zsh, qui dispose par ailleurs de plusieurs "gestionnaires de plugins".
Mais en fait on en a pas besoin, il suffit de cloner un repo git puis ajouter une ligne source à .zshrc.
On va bourrer tout ces extras dans un répertoire ~/.zsh pour cet exemple mais vous mettez ça où vous voulez:
mkdir -p ~/.zsh
cd ~/.zsh
git clone https://github.com/zsh-users/zsh-autosuggestions ~/.zsh/zsh-autosuggestions
git clone https://github.com/zsh-users/zsh-syntax-highlighting ~/.zsh/zsh-syntax-highlighting
Il s'agit ensuite d'éditer .zshrc et ajouter ces lignes quelque part avant la ligne eval pour Starship:
ZSH=~/.zsh
source "$ZSH/zsh-autosuggestions/zsh-autosuggestions.zsh"
source "$ZSH/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh"
Appliquez les changements avec un petit source du fichier et vous devriez déjà constater l'autosuggestion et la coloration syntaxique.
La coloration syntaxique affiche les commandes non-existantes en rouge, met le contenu de divers guillemets en exergue, et... C'est à peu près tout.
Il existe beaucoup d'autres plugins, je vous laisse une vieille liste ici.
Au final j'ai ça comme config:
setopt histignorealldups sharehistory
# Use emacs keybindings even if our EDITOR is set to vi
bindkey -e
bindkey "^[[1;5C" forward-word
bindkey "^[[1;5D" backward-word
# Keep 1000 lines of history within the shell and save it to ~/.zsh_history:
HISTSIZE=10000
SAVEHIST=10000
HISTFILE=~/.zsh_history
# Use modern completion system
autoload -Uz compinit
compinit
zstyle ':completion:*' auto-description 'specify: %d'
zstyle ':completion:*' completer _expand _complete _correct _approximate
zstyle ':completion:*' format 'Completing %d'
zstyle ':completion:*' group-name ''
zstyle ':completion:*' menu select=2
eval "$(dircolors -b)"
zstyle ':completion:*:default' list-colors ${(s.:.)LS_COLORS}
zstyle ':completion:*' list-colors ''
zstyle ':completion:*' list-prompt %SAt %p: Hit TAB for more, or the character to insert%s
zstyle ':completion:*' matcher-list '' 'm:{a-z}={A-Z}' 'm:{a-zA-Z}={A-Za-z}' 'r:|[._-]=* r:|=* l:|=*'
zstyle ':completion:*' menu select=long
zstyle ':completion:*' select-prompt %SScrolling active: current selection at %p%s
zstyle ':completion:*' use-compctl false
zstyle ':completion:*' verbose true
zstyle ':completion:*:*:kill:*:processes' list-colors '=(#b) #([0-9]#)*=0=01;31'
zstyle ':completion:*:kill:*' command 'ps -u $USER -o pid,%cpu,tty,cputime,cmd'
alias ls='ls --color=auto'
alias grep='grep --color=auto'
alias fgrep='fgrep --color=auto'
alias egrep='egrep --color=auto'
ZSH=~/.zsh
source "$ZSH/zsh-autosuggestions/zsh-autosuggestions.zsh"
source "$ZSH/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh"
source <(fzf --zsh)
eval "$(starship init zsh)"
Les "presets" de Starship
L'invite de commande sur deux lignes par défaut est plutôt chouette je trouve.
Starship propose aussi quelques configurations incluses dans le binaire à générer avec une petite commande.
Voici celle que j'utilise pour les exemples, légèrement modifée (voir plus loin):
starship preset catppuccin-powerline -o ~/.config/starship.toml
Etant donné que starship est invoqué chaque fois qu'on presse Entrée, le changement est immédiat.
Voici la "pastel powerline" par exemple, j'ai choisi Catppuccin plus haut parce qu'elle produit un fichier de config un peu plus fourni et donc plus pratique à bidouiller:
Config Starship supplémentaire
En option, on peut s'offrir une menue personnalisation de notre nouvelle invite de commande.
Ouvrez ~/.config/starship.toml dans votre éditeur favori (ce fichier a été créé en choisissant un preset au préalable — Sinon il est absent).
Remarquez les symboles et variables utilisés dans l'invite. Ils viennent généralement de ce projet (inclus dans les Nerd Fonts) qui mentionne les codes UTF dans leur README.md.
Comme ça si vous voulez ajouter des flammes comme sur le pot POLINI de votre booster Piagio, vous pouvez ajouter les glyphes idoines.
Dans vim ça se fait en tapant Ctrl+v suivi du code du symbole, par exemple "ue0c0".
Les changements que je propose:
- Virer les lignes avec $os et $username, je sais qui je suis et je sais sur quel ordi je suis, je remplace ça par un emoji:
[🌈](bg:red)\
- Je retire $time parce que j'ai pas besoin de l'heure — Certains apprécient d'avoir une indication de "quand a été lancé cette commande";
- Je retire cmd_duration pour le mettre dans une nouvelle section à ajouter en dessous:
right_format = """
$cmd_duration\
"""
Ce qui a pour effet d'afficher la durée des "longues" commandes à droite. C'est une caractéristiques de zsh d'avoir une zone à droite de l'invite qui est utilisable. Vous pouvez y mettre ce que vous voulez, l'heure par exemple.
Voici le résultat de ces modifications:

Le début de mon starship.toml ressemble désormais à ceci (c'est normal s'il manque la moitié des caractères spéciaux ici):
"$schema" = 'https://starship.rs/config-schema.json'
format = """
[](red)\
[🌈](bg:red)\
[](bg:peach fg:red)\
$directory\
[](bg:yellow fg:peach)\
$git_branch\
$git_status\
[](fg:yellow bg:green)\
$c\
$rust\
$golang\
$nodejs\
$php\
$java\
$kotlin\
$haskell\
$python\
[](fg:green bg:sapphire)\
$conda\
[](fg:sapphire bg:lavender)\
[ ](fg:lavender)\
$line_break\
$character"""
right_format = """
$cmd_duration\
"""
palette = 'catppuccin_mocha'
Le monde est votre huitre pour le reste de la personnalisation.
Intégration de fzf et zsh
Vous le saviez pas mais fzf est déjà intégré à votre shell depuis la config initiale de zsh.
Les touches pour l'utiliser sont les touches "emacs". J'en parle parce qu'il existe un mode vi pour zsh (et bash, et fish, et beaucoup de choses dans le monde) avec des combinaisons de touches différentes.
J'utilise vim comme éditeur mais pas le mode vi des invites de commande pour plusieurs raisons:
- J'utilise Ctrl+C en lieu et place de Esc et ça le fait absolument pas du tout dans un shell puisque Ctrl+C est essentiel pour envoyer le signal d'interruption;
- Je me connecte sur des serveurs divers et variés dans le cadre de mon travail (oui, j'ai un travail) et j'ai pas envie de taper set -o vi toutes les 10 minutes de ma vie. Les serveurs sont aussi la raison pour laquelle j'utilise Ctrl+C comme Esc dans vim.
Cette parenthèse inutile derrière nous, le raccourci le plus important est Ctrl+R pour rechercher dans l'historique des commandes.
Ce n'est pas exclusif à zsh, j'utilise la même chose avec bash.
Notons également Ctrl+T pour ouvrir une sélection floue de fichiers pour compléter la commande actuelle, et Esc+c pour rechercher dans les répertoires, par exemple pour compléter une commande cd:

Trop chouette ou quoi?
Je rappelle que fzf s'intègre à d'autres shells en plus d'être un outil assez utile pour réaliser vos propres scripts en ligne de commande.













Commentaires
Il faut JavaScript activé pour écrire des commentaires ici