diff --git a/book/src/SUMMARY.md b/book/src/SUMMARY.md
index 1208320ee6098275e12a220b21519a5257bcca8c..db3a86acc42af5cdcbcc65f9db07bf0051860d06 100644
--- a/book/src/SUMMARY.md
+++ b/book/src/SUMMARY.md
@@ -14,4 +14,5 @@
 - [Part 09](./part09.md)
 - [Part 10](./part10.md)
 - [Part 11](./part11.md)
+- [CLI](./cli.md)
 - [Part 12](./part12.md)
diff --git a/book/src/cli.md b/book/src/cli.md
new file mode 100644
index 0000000000000000000000000000000000000000..80d0a41f10a7b44a371bac5f71ce51066c228f19
--- /dev/null
+++ b/book/src/cli.md
@@ -0,0 +1,388 @@
+# Interface en ligne de commande et entrées / sorties
+
+## Concepts
+
+Les concepts abordés dans cet exemple sont:
+
+1. [L'interface en ligne de commande et l'utilisation de librairies externes.](#linterface-à-la-ligne-de-commande-et-lutilisation-de-librairies-externes)
+2. [Les entrées / sorties.](#les-entrées--sorties)
+3. Une gestion des erreurs plus ergonomique.
+
+## Discussion
+
+L'écosystème de Rust contient énormément de librairies ergonomiques et efficaces. Dans ce chapitre, nous
+parlerons de [clap](https://github.com/clap-rs/clap), une librairie pour construire des interfaces en ligne de commande.
+Nous en profiterons pour discuter également les entrées / sorties et en particulier comment écrire dans des
+fichiers. Finalement, nous verrons également avoir une gestion d'erreur un peu plus ergonomique à
+l'aide de l'opérateur `?` et de la fonction `map_err()`.
+
+Vous pouvez trouver plus d'informations aux liens suivants:
+
+- [Tutoriel pour le pattern `builder`](https://docs.rs/clap/latest/clap/_tutorial/index.html)
+- [Tutoriel pour le pattern `derive`](https://docs.rs/clap/latest/clap/_derive/_tutorial/index.html)
+- [Chapitre du livre sur les entrées sorties](https://doc.rust-lang.org/book/ch12-00-an-io-project.html)
+- [Command Line Applications in Rust](https://rust-cli.github.io/book/index.html)
+
+## L'interface à la ligne de commande et l'utilisation de librairies externes
+
+Dans cette section nous allons voir une façon différente
+de lire la ligne de commande (par rapport à ce que nous avons fait dans la [partie 07](part07.md)).
+
+Cette façon de faire est trop complexe pour construire une vraie application et
+rajouterait beaucoup d'efforts à chaque fois qu'on veut en reconstruire une:
+elle demanderait un parsing long et fastidieux de la ligne de commande manuel.
+La [librairie clap](https://github.com/clap-rs/clap), la librairie de CLI la plus populaire
+pour Rust, nous permet de de construire une interface pour un programme avec arguments
+nommés, optionnel, et un menu d'aide de façon élégante et une bonne gestion des erreurs.
+
+Afin d'utiliser une librairie externe, il faut l'ajouter comme dépendance dans le fichier `Cargo.toml`
+de notre projet. Pour ce faire, il y a deux méthodes, et nous allons voir comment cela fonctionne pour `clap`:
+
+1. Ajouter la ligne 
+```toml
+clap = { version = "4.4.0", features = ["derive"] }
+```
+sous l'entrée `[dependecies]`.
+
+2. Utiliser l'outil `cargo` qui le fait pour nous
+```bash
+cargo add clap --features derive
+```
+Il y a énormément de fonctionnalités dans l'outil [cargo](https://doc.rust-lang.org/cargo/index.html).
+
+Ces deux façons sont équivalentes. Lors de l'ajout manuel, on doit choisir la version manuellement qu'on veut mettre dans
+le fichier `Cargo.toml` (cela permet de figer une version) ou on peut remplacer `4.4.0` par `*` pour avoir toujours
+la dernière version de la `crate` à utiliser. Cependant cette façon de faire n'est pas recommandée, car
+cela peut "casser" la compilation lors d'une mise à jour majeure (ou avoir des effets de sécurité
+indésirables).
+
+On note également, qu'on a un champs `features` qui est optionnel, mais qui ici est mis à `derive`.
+Le langage Rust permet d'omettre une partie des fonctionnalités d'une librairies qui sont ajoutées
+à l'aide d'annotations lorsque la `feature` est activée. Nous n'entrerons pas dans les détails de ces annotations,
+mais avons besoin de la feature `derive` pour compiler notre code.
+
+Nous pouvons à présent commencer à écrire nos fonctions pour lire la ligne de commande
+à l'aide de la librairie `clap`. Nous allons voir deux façons différentes
+de créer une telle interface avec la librairie: les pattern [`builder`](#le-builder-pattern) et [`derive`](#le-derive-pattern) (c'est pour
+ce dernier que nous avons besoin de la feature `derive`).
+
+Le but de cette interface à la ligne de commande est pour l'utilisateur·trice de pouvoir
+choisir les options suivantes pour notre petit programme de calcul de minimum
+dans une liste.
+
+1. Entrer à la main une liste de nombres.
+2. Créer une liste de `count` nombres aléatoires qui seront lus depuis `/dev/urandom`.
+3. Écrire la liste de nombres et le minimum de la liste dans un fichier de sortie (en en fournissant le nom) ou sur l'écran.
+
+Il faut noter que l'option 1 et 2 son mutuellement exclusives. L'option 3
+écrira dans un fichier uniquement si un nom de fichier est fourni par l'utilisateur·trice.
+
+Il est fondamental que si les entrées sont mal formatées (on ne donne pas des nombres p.ex.)
+ou si on essaie d'utiliser les options 1 et 2 en même temps, on ait un bon traitement de l'erreur
+et un message d'erreur lisible.
+
+Des tentatives d'exécution typiques seraient
+```bash
+$ cargo run -- --numbers 1 2 3 4 5 6
+```
+où on donne une liste de nombres après l'option `--numbers` ou encore
+```bash
+$ cargo run -- --output fichier.txt --numbers 1 2 3 4 5 6
+```
+où `--output` permet de spécifier un nom de fichier. En revanche, on **doit** avoir une erreur
+si on essaie de faire
+```bash
+$ cargo run -- --count 10 --numbers 1 2 3 4 5 6
+```
+car on ne veut pas pouvoir générer deux listes de nombres, mais une seule.
+
+Ainsi on a trois arguments possibles et tous sont optionnels, mais deux sont exclusifs.
+
+### Le `builder` pattern
+
+Nous allons voir à présent comment construire une interface en ligne de commande à proprement parler avec `clap`. Pour ce faire et comprendre le fonctionnement interne de la librairie
+nous allons d'abord étudier le `builder` pattern, qui consiste à construire l'interface
+à l'aide de fonctions qui vont construire petit à petit notre application.
+
+La fonction qui va faire tourner notre application se trouve dans `src/io.rs`
+et a la signature suivante
+```rust,ignore
+pub fn read_command_line_builder() -> Result<(), String>
+```
+On remarque qu'elle ne prend aucun argument en paramètre et qu'elle retourne un `Result<(), 
+String>`. En d'autres termes, si tout s'est bien passé, nous ne retournons "rien". Dans l'éventualité
+où quelque chose ne s'est pas passé comme prévu, nous retournons une chaîne de caractères 
+qui contiendra un message d'erreur.
+
+Le création de la "commande" se trouve dans le code
+```rust,ignore
+{{#include ../../codes/rust_lang/cli/src/io.rs:matches}}
+```
+Ici nous effectuons diverses opérations. Nous commençons par créer une nouvelle commande
+dont le nom est `cli`[^1]
+```rust,ignore
+{{#include ../../codes/rust_lang/cli/src/io.rs:consts}}
+{{#include ../../codes/rust_lang/cli/src/io.rs:new_command}}
+```
+avec différents composants optionnels, comme le nom de l'auteur de l'application,
+sa version, etc. Cela permet maintenant d'ajouter les arguments sur cette application.
+
+Comme discuté plus haut nous voulons *trois* arguments (`numbers`, `output`, et `count`) qui sont ajouté dans un ordre
+qui n'a aucune importance.
+```rust,ignore
+{{#include ../../codes/rust_lang/cli/src/io.rs:new_command}}
+```
+L'appel à la méthode `.arg()` nous permet d'ajouter un nouvel argument, créé avec l'appel à
+```rust,ignore
+Arg::new(id)
+```
+où `id` est une chaîne de caractères qui permet d'identifier de façon unique l'argument.
+Puis viennent toutes les propriétés de notre argument:
+
+- `short('n')`: l'option peut être nommée `-n`,
+- `long("numbers")`: l'option peut être nommée `--numbers`, permettant d'appeler le programme avec
+```bash
+$ cargo run -- --numbers 1 2 3 4 5 6 
+$ cargo run -- -n 1 2 3 4 5 6 
+```
+- `help("A list of i32 numbers")`: le message d'aide si nous appelons 
+```bash
+⋊> ~/g/p/r/c/r/cli on 25-cli-i-o ⨯ cargo run -- --help    
+```
+```console
+Finished dev [unoptimized + debuginfo] target(s) in 0.01s
+     Running `target/debug/cli --help`
+Usage: cli [OPTIONS]
+
+Options:
+  -n, --numbers <numbers>...  A list of i32 numbers
+  -c, --count <count>         How many random numbers we want?
+  -o, --output <output>       Should we write output in a file?
+  -h, --help                  Print help
+  -V, --version               Print version
+```
+- `num_args(1..)`: qui permet d'avoir plusieurs valeurs dans l'argument et savons qu'il doit y en avoir plus d'un. Sans cet argument, l'appel
+```bash
+$ cargo run -- --numbers 1 2 3 4 5 6
+```
+considérerait le `2` comme la valeur d'un autre argument et ne ferait pas partie de `numbers`.
+Puis viennent encore
+- `allow_negative_numbers(true)`: pour autoriser les nombres négatifs (sinon `-` est parsé comme nouvel argument)
+- `value_parser(value_parser!(i32))`: on ne veut que des `i32` (les nombres à virgules, les lettres, etc sont automatiquement rejetées et un message d'erreur est affiché)
+- `required(false)`: est-ce que l'argument est obligatoire (ici ce n'est pas le cas)? En d'autres termes est-ce l'exécution suivante est valide?
+```bash
+$ cargo run -- # sans option numbers
+```
+Si l'argument est `required(true)` alors il est nécessaire de spécifier l'option sinon on aura un message d'erreur.
+
+Dans la suite du code on crée encore deux arguments `count` et `output`. Nous avons déjà couvert
+les différentes fonctions appelée, à l'exception d'une:
+- `conflicts_with("numbers")`: ici nous spécifions que l'argument `count` ne peut pas être
+présent **en même temps** que l'argument `numbers` (peu importe l'ordre d'appel). Ainsi si nous essayons d'exécuter 
+```bash
+$ cargo run -- --numbers 1 2 3 4 5 6 -c 6
+```
+nous aurons le message d'erreur
+```console
+error: the argument '--numbers <numbers>...' cannot be used with '--count <count>'
+
+Usage: cli --numbers <numbers>...
+
+For more information, try '--help'
+```
+
+Après avoir construit les arguments, nous devons appeler la fonction `get_matches()` qui
+termine la construction de la commande et vérifie s'il n'y a pas d'arguments qui sont contradictoires (un message d'erreur sera produit à l'exécution si cela est le cas).
+
+Lorsque ce code est exécuté, notre programme peut maintenant parser la ligne de commande
+lorsqu'il est exécuté. A nous maintenant d'utiliser correctement les différents arguments.
+Ici, nous devons traiter deux "groupes" d'arguments:
+- `numbers` et `count` qui sont deux options exclusives,
+- `output` qui est optionnel également.
+
+Le traitement de 
+```rust,ignore
+{{#include ../../codes/rust_lang/cli/src/io.rs:numbers_matches}}
+```
+crée la liste de nombre que nous voulons avoir pour calculer le minimum.
+
+Comme les deux arguments sont optionnels, nous voyons que pour les déstructurer,
+il faut passer par une construction `if let Some() = ...`.
+Dans le cas de l'argument `count` nous savons que nous voulons un `usize` dont l'identifiant
+est `"count"`. Si l'argument est présent,
+```rust,ignore
+{{#include ../../codes/rust_lang/cli/src/io.rs:get_one_matches}}
+```
+retourne `Some(&usize)` (nous obtenons une référence vers l'argument) 
+et nous appellerons la fonction `read_from_urandom()` (que nous discuterons plus bas). Sinon, nous devons vérifier si l'argument `numbers` est présents
+et quelles valeurs lui sont assignées. Ainsi, si l'argument est présent
+```rust,ignore
+{{#include ../../codes/rust_lang/cli/src/io.rs:get_many_matches}}
+```
+retournera un nombre arbitraire de références d'entiers, qui seront ensuite
+transformés en `Vec<i32>` à l'aide de la ligne
+```rust,ignore
+numbers.copied().collect()
+```
+qui commence par faire une copie des valeurs de la liste de références pour pouvoir
+en devenir les propriétaires, puis les met dans un `Vec<i32>` (il faut noter que le type
+de `numbers` est *inféré* grâce au reste du code). A la fin de ce `if let Some() = ...` nous retournons un `Vec<i32>` (qui peut être vide)
+qui sera utilisé dans la suite de la fonction. 
+
+Il nous reste à décider si nous allons écrire les sorties de notre programme (la liste de nombre et son minimum) dans un fichier ou dans la sortie standard à l'aide du code
+```rust,ignore
+{{#include ../../codes/rust_lang/cli/src/io.rs:output_matches}}
+```
+Rien de très nouveau ici, si `"output"` est présent
+```rust,ignore
+{{#include ../../codes/rust_lang/cli/src/io.rs:get_one_string_matches}}
+```
+nous pouvons déstructurer le retour de la fonction et obtenir le nom du fichier
+dans lequel nous allons écrire dans la fonction `write_to_file()` ou le cas échant
+écrire dans la sortie standard .
+
+#### Gestion d'erreur un peu simplifiée
+
+Aussi bien les appels à `read_from_urandom()` que `write_to_file()` sont suivis d'un `?`.
+Ces fonctions doivent manipuler des fichiers et peuvent donc échouer à n'importe quel moment
+(si le fichier n'existe pas, s'il ne peut être créé, etc). Elles retournent
+donc des `Result`. L'opérateur `?` en Rust est très pratique. Il est utilisé pour répercuter
+les erreurs de façon courte dans les fonctions. En gros il répond à la question:
+"Est-ce que la fonction a retourné `Ok()` ou `Err()`?" Si la réponse est `Ok()` il retourne ce 
+qui est contenu dans le `Ok()` qui peut être assigné à une variable (ou retourné de la fonction). 
+En revanche si la réponse est `Err()`, on retourne l'erreur de la fonction courante.
+Cet opérateur permet d'éviter d'alourdi le code avec du pattern matching à chaque appel
+qui peut échouer et est très utilisé dans le code Rust.
+
+### Le `derive` pattern
+
+Nous avons vu en grand détail comment construire une commande avec un `builder`
+design. Nous allons voir à présent de façon très succincte comment faire la même
+chose avec le pattern `derive`. Ici, tout le code écrit plus haut sera généré
+pour nous à l'aide de `macro` Rust, et nous avons uniquement besoin de spécifier
+ce qui doit être généré. Afin de créer une interface en ligne de commande nous devons uniquement
+créer une `struct` annotée
+```rust,ignore
+{{#include ../../codes/rust_lang/cli/src/io.rs:derive}}
+```
+qui contient différent champs qui sont annotés (ou pas).
+
+La ligne
+```rust,ignore
+#[derive(Parser)]
+```
+va dire au compilateur de Rust de générer automatiquement tout le parsing d'arguments
+en fonction de ce qu'il va trouver dans la structure en dessous, ici `CliMin`.
+Puis vient la commande préprocesseur
+```rust,ignore
+#[command(author, version, about, long_about = None)]
+```
+qui va créer la nouvelle commande à proprement parler. Elle correspond à 
+```rust,ignore
+{{#include ../../codes/rust_lang/cli/src/io.rs:new_command}}
+```
+A la différence de cette ligne où on spécifie explicitement l'auteur, etc., ici,
+le contenu du champs author, version, etc. est directement récupéré du `Cargo.toml`.
+Ensuite la structure `CliMin` possède trois membres: `numbers`, `count`, et `output`
+qui sont annotés avec un `#[arg()]`. 
+```rust,ignore
+{{#include ../../codes/rust_lang/cli/src/io.rs:arg}}
+```
+Cette annotation va dire au compilateur de générer
+automatiquement le code pour toutes les paires clés valeurs se trouvant entre les parenthèses.
+Si une valeur est absente alors un comportement par défaut est appliqué.
+Ainsi, `long` va générer automatiquement que l'option en version longue pour la variable `numbers` est `--numbers`. De façon similaire, par défaut la version `short` de
+numbers sera `-n` (la première lettre de `numbers`). Cette façon de faire par défaut permet de réduire la quantité de code. Par contre, elle est également dangereuse, car si deux
+champs commencent par le même nom, seul le premier aura le `short` qui lui correspondra.
+
+Le reste des arguments correspondent à toutes les méthodes de la version `builder`
+vues dans le chapitre précédent. Il y a deux grandes différences:
+
+1. On ne trouve pas
+d'équivalent à `required(false)`. En fait, l'obligation ou non de spécifier un argument
+est directement inféré par le type de l'argument: si c'est une `Option` alors l'argument est...
+optionnel.
+2. `numbers` est directement parsé en `Vec<i32>`, pas besoin de faire des conversions.
+
+Le reste du code est relativement trivial. Pour utiliser notre interface en ligne de commande
+```rust,ignore
+{{#include ../../codes/rust_lang/cli/src/io.rs:read_command_line_derive}}
+```
+Il faut appeler la fonction `parse()`
+```rust,ignore
+{{#include ../../codes/rust_lang/cli/src/io.rs:parse}}
+```
+et les champs `cli.cout`, `cli.numbers`, et `cli.output` seront automatiquement assignés
+aux valeurs dans la `cli` si elles sont compatibles avec les formats spécifiés dans les
+arguments correspondants. Sinon des erreurs seront affichées.
+
+## Les entrées / sorties
+
+Il y a deux fonctions qui gèrent la lecture / écriture de fichiers dans notre programme.
+1. La fonction `read_from_urandom()` permet de lire le fichier `/dev/urandom` qui contient
+dans les systèmes unix des "vrais" nombres aléatoires générés par le bruit du système.
+2. La fonction `write_to_file()` qui permet d'écrire la liste de nombre, ainsi que le minimum
+dans un fichier. Nous allons brièvement discuter ces fonctions, afin de comprendre un peu
+mieux comment faire des entrées / sorties depuis le disque en Rust.
+
+### Lecture de fichier
+
+Pour la lecture de fichier, nous nous concentrons sur la fonction
+```rust,ignore
+{{#include ../../codes/rust_lang/cli/src/io.rs:read_from_urandom}}
+```
+L'ouverture d'un fichier en lecture se fait avec la fonction `File::open()`
+qui peut échouer si le fichier n'existe pas par exemple. Dans le cas d'une
+erreur, nous nous empressons de convertir l'erreur dans un message d'erreur
+avec la fonction `map_err()` qui prend en argument une fonction anonyme qui a pour argument
+ce qui est encapsulé dans le type `Err()` et qui retourne une nouvelle valeur qui sera
+encapsulée dans une nouvelle `Err()`. Cette façon de faire n'est pas très idiomatique
+pour Rust, mais elle nous satisfait pour le moment, afin d'avoir des types de retour homogènes
+et de pouvoir utiliser l'opérateur `?` (voir [plus haut](#gestion-derreur-un-peu-simplifiée)).
+
+Comme nous lisons dans le fichier `/dev/urandom` qui est un flux continu d'octets, nous définissons
+une mémoire tampon sur le fichier et allons lire exactement `4 * count` fois octets, soit
+exactement l'équivalent de `count` entiers 32-bits soit `i32`
+```rust,ignore
+{{#include ../../codes/rust_lang/cli/src/io.rs:read}}
+```
+Finalement, notre mémoire tableau `numbers` (qui est rien d'autre qu'une suite d'octets)
+est convertie en `Vec<i32>` grâce à la puissance des itérateurs. 
+```rust,ignore
+{{#include ../../codes/rust_lang/cli/src/io.rs:convert_to_i32}}
+```
+Dans un premier temps
+le tableau est découpé en tranches de 4 éléments grâce à la méthode `.chunks(4)` (l'itérateur est maintenant une suite
+d'itérateurs de 4 éléments). Puis chacun des éléments de l'itérateur (soit 4 octets)
+est transformé en `i32`, grâce à la méthode `map(|i| i32::from_be_bytes(i.try_into().unwrap()))`.
+Il faut noter qu'ici nous utilisons la fonction `try_into()` qui peut échouer si nous n'avons pas
+4 octets à disposition quand nous faisons la conversion. Ici, par construction cela ne peut pas se produire et pouvons `unwrap()` le résultat. Finalement, à l'aide de `collect()`,
+nous créons un `Vec<i32>` à partir de l'itérateur obtenu et l'encapsulons dans un `Ok()`,
+car le résultat de notre fonction est un succès, si tout s'est bien passé.
+
+### Écriture dans un fichier
+
+Pour l'écriture dans un fichier, nous nous concentrons sur la fonction
+```rust,ignore
+{{#include ../../codes/rust_lang/cli/src/io.rs:write_to_file}}
+```
+Nous commençons par créer un fichier à l'aide de la fonction `File::create()`
+qui prend en argument le chemin où créer le fichier. 
+```rust,ignore
+{{#include ../../codes/rust_lang/cli/src/io.rs:create}}
+```
+Si un fichier existe déjà
+il est écrasé par défaut. Si la création est impossible, une erreur est retournée.
+De plus le fichier est ouvert en mode écriture. Il faut noter que nous allons **modifier le fichier**, et il est donc **mutable**.
+Ainsi, nous pouvons écrire dans le fichier à l'aide des macros `write!` et `writeln!`
+qui s'utilisent comme `print!` et  `println!` à l'exception qu'elles prennent
+des fichier en argument et retournent une erreur en cas d'échec.
+```rust,ignore
+{{#include ../../codes/rust_lang/cli/src/io.rs:write}}
+```
+A nouveau, toutes les erreurs sont transformées en messages (des chaînes de caractères)
+pour simplifier les concepts abordés dans ce code.
+
+[^1]: Cet identifiant permet d'identifier de façon unique la commande
+dans le cas où nous en créerions plusieurs dans la même application ce qui n'est pas le cas
+ici.
\ No newline at end of file
diff --git a/codes/rust_lang/cli/Cargo.toml b/codes/rust_lang/cli/Cargo.toml
new file mode 100644
index 0000000000000000000000000000000000000000..9c4c4a46016670aa7335153995bbbf12d46beb70
--- /dev/null
+++ b/codes/rust_lang/cli/Cargo.toml
@@ -0,0 +1,9 @@
+[package]
+name = "cli"
+version = "0.1.0"
+edition = "2021"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+clap = { version = "4.4.0", features = ["derive"] }
diff --git a/codes/rust_lang/cli/src/io.rs b/codes/rust_lang/cli/src/io.rs
new file mode 100644
index 0000000000000000000000000000000000000000..47d75e27cfc1a00ccccac85cd83f1763ee1e7080
--- /dev/null
+++ b/codes/rust_lang/cli/src/io.rs
@@ -0,0 +1,185 @@
+use std::{
+    fs::File,
+    io::{BufReader, Read, Write},
+};
+
+// ANCHOR: use_clap
+use clap::{value_parser, Arg, Command, Parser};
+// ANCHOR_END: use_clap
+
+// ANCHOR: consts
+const COMMAND: &str = "cli";
+const AUTHOR: &str = "Orestis Malaspinas";
+const VERSION: &str = "0.1.0";
+// ANCHOR_END: consts
+
+use crate::something_or_nothing::find_min;
+
+// ANCHOR: read_from_urandom
+fn read_from_urandom(count: usize) -> Result<Vec<i32>, String> {
+    // ANCHOR: open
+    let file = File::open("/dev/urandom").map_err(|_| "Could not open /dev/urandom")?;
+    // ANCHOR_END: open
+    // ANCHOR: read
+    let mut buf_reader = BufReader::new(file);
+    let mut numbers = vec![0; count * 4];
+    buf_reader
+        .read_exact(&mut numbers)
+        .map_err(|_| "Could not read numbers")?;
+    // ANCHOR_END: read
+    // ANCHOR: convert_to_i32
+    Ok(numbers
+        .chunks(4)
+        .map(|i| i32::from_be_bytes(i.try_into().unwrap()))
+        .collect::<Vec<_>>())
+    // ANCHOR_END: convert_to_i32
+}
+// ANCHOR_END: read_from_urandom
+
+// ANCHOR: write_to_file
+fn write_to_file(output: &str, numbers: &[i32]) -> Result<(), String> {
+    // ANCHOR: create
+    let mut file = File::create(output).map_err(|_| format!("Failed to create {output}"))?;
+    // ANCHOR_END: create
+    // ANCHOR: write
+    writeln!(file, "Among the Somethings in the list:")
+        .map_err(|_| "Failed to write header into file.")?;
+    for n in numbers {
+        write!(file, "{n} ").map_err(|_| format!("Failed to write {n} into file."))?;
+    }
+    writeln!(file,).map_err(|_| "Failed to write carriage return into file.")?;
+    writeln!(file, "{}", find_min(numbers).to_string())
+        .map_err(|_| "Failed to write minimum value into file.")?;
+    // ANCHOR_END: write
+    Ok(())
+}
+// ANCHOR_END: write_to_file
+
+/// Reads i32 from the command line and returns a [Vec] containing
+/// these numbers. Returns errors when the parsing fails.
+pub fn read_command_line_builder() -> Result<(), String> {
+    // ANCHOR: matches
+    let matches = 
+    // ANCHOR: new_command
+        Command::new(COMMAND)
+            .author(AUTHOR)
+            .version(VERSION)
+    // ANCHOR_END: new_command
+    // ANCHOR: new_args
+            .arg(
+                Arg::new("numbers") // id
+                    .short('n')         // version courte -n
+                    .long("numbers")    // ou longue --numbers
+                    .help("A list of i32 numbers") // l'aide
+                    .num_args(1..) // combien il y a d'entrées
+                    .allow_negative_numbers(true) // on peut avoir des négatifs
+                    .value_parser(value_parser!(i32)) // on veut s'assurer que ça soit des nombres
+                    .required(false), // optionnel
+            )
+            .arg(
+                Arg::new("count")
+                    .short('c')
+                    .long("count")
+                    .help("How many random numbers we want?")
+                    .value_parser(value_parser!(usize))
+                    .conflicts_with("numbers") // impossible d'avoir -c et -n
+                    .required(false),
+            )
+            .arg(
+                Arg::new("output")
+                    .short('o')
+                    .long("output")
+                    .help("Should we write output in a file?")
+                    .required(false),
+            )
+    // ANCHOR: new_args
+            .get_matches();
+    // ANCHOR_END: matches
+
+    // ANCHOR: numbers_matches
+    let numbers = 
+        if let Some(count) = 
+        // ANCHOR: get_one_matches
+            matches.get_one::<usize>("count") 
+        // ANCHOR_END: get_one_matches
+        {
+            read_from_urandom(*count)?
+        } else if let Some(numbers) = 
+        // ANCHOR: get_many_matches
+            matches.get_many::<i32>("numbers") 
+        // ANCHOR_END: get_many_matches
+        {
+            numbers.copied().collect()
+        } else {
+            Vec::new()
+        };
+    // ANCHOR_END: numbers_matches
+
+    // ANCHOR: output_matches
+    if let Some(output) = 
+        // ANCHOR: get_one_string_matches
+        matches.get_one::<String>("output") 
+        // ANCHOR_END: get_one_string_matches
+    {
+        write_to_file(output, &numbers)?;
+    } else {
+        println!("Among the Somethings in the list:");
+        print_tab(&numbers);
+        println!("{}", find_min(&numbers).to_string());
+    }
+    // ANCHOR_END: output_matches
+
+    Ok(())
+}
+
+/// Does not compile without the feature derive
+// ANCHOR: derive
+#[derive(Parser)]
+// ANCHOR: command
+#[command(author, version, about, long_about = None)]
+// ANCHOR_END: command
+struct CliMin {
+    // ANCHOR: arg
+    #[arg(short, long, help = "A list of i32 numbers", num_args=1.., allow_negative_numbers=true, value_parser = clap::value_parser!(i32))]
+    numbers: Option<Vec<i32>>,
+    // ANCHOR_END: arg
+    #[arg(short, long, help = "How many random numbers we want?", value_parser = clap::value_parser!(usize), conflicts_with = "numbers")]
+    count: Option<usize>,
+    #[arg(short, long, help = "Filename for writing the numbers.")]
+    output: Option<String>,
+}
+// ANCHOR_END: derive
+
+/// Reads i32 from the command line and returns a [Vec] containing
+/// these numbers. Returns errors when the parsing fails.
+// ANCHOR: read_command_line_derive
+pub fn read_command_line_derive() -> Result<(), String> {
+    // ANCHOR: parse
+    let cli = CliMin::parse();
+    // ANCHOR_END: parse
+    let numbers = if let Some(count) = cli.count {
+        read_from_urandom(count)?
+    } else if let Some(numbers) = cli.numbers {
+        numbers
+    } else {
+        Vec::new()
+    };
+    if let Some(output) = cli.output {
+        write_to_file(&output, &numbers)?;
+    } else {
+        println!("Among the Somethings in the list:");
+        print_tab(&numbers);
+        println!("{}", find_min(&numbers).to_string());
+    }
+    Ok(())
+}
+// ANCHOR_END: read_command_line_derive
+
+/// Prints all the elements of the `tab`.
+/// Tab is borrowed here
+pub fn print_tab(tab: &Vec<i32>) {
+    for t in tab {
+        print!("{} ", t);
+    }
+    println!();
+}
diff --git a/codes/rust_lang/cli/src/lib.rs b/codes/rust_lang/cli/src/lib.rs
new file mode 100644
index 0000000000000000000000000000000000000000..eaabc144a5c0a8c7f7312def661b1e86484bfc37
--- /dev/null
+++ b/codes/rust_lang/cli/src/lib.rs
@@ -0,0 +1,59 @@
+/*!
+cli illustrates the use of [Vec] and the Error Handling with [Option] and [Result].
+It also showcases struct enums.
+*/
+
+pub mod io;
+mod minimum;
+pub mod something_or_nothing;
+
+#[cfg(test)]
+mod tests {
+    use crate::minimum::Minimum;
+    use crate::something_or_nothing::{find_min, SomethingOrNothing};
+
+    #[test]
+    fn test_creation() {
+        let n1: SomethingOrNothing<i32> = SomethingOrNothing::default();
+        assert!(n1 == SomethingOrNothing::default());
+        let n2: SomethingOrNothing<i32> = SomethingOrNothing::new(1);
+        assert!(n2 == SomethingOrNothing::new(1));
+    }
+
+    #[test]
+    #[should_panic]
+    fn test_failure_creation() {
+        let n2: SomethingOrNothing<i32> = SomethingOrNothing::new(1);
+        assert!(n2 == SomethingOrNothing::default());
+        assert!(n2 == SomethingOrNothing::new(2));
+    }
+
+    #[test]
+    fn test_min() {
+        let a = vec![1, 5, -1, 2, 0, 10, 11, 0, 3];
+        let min = find_min(&a);
+        assert!(min == SomethingOrNothing::new(-1));
+    }
+
+    #[test]
+    fn test_min_i32() {
+        let x = 5;
+        let y = 10;
+        assert_eq!(Minimum::min(x, y), x);
+        assert_eq!(Minimum::min(y, x), x);
+        assert_eq!(Minimum::min(x, x), x);
+        assert_eq!(Minimum::min(y, y), y);
+    }
+
+    #[test]
+    fn test_min_something_or_nothing() {
+        let x = SomethingOrNothing::new(5i32);
+        let y = SomethingOrNothing::new(10i32);
+        let z = SomethingOrNothing::default();
+        assert!(x.min(y) == x);
+        assert!(y.min(x) == x);
+        assert!(z.min(y) == y);
+        assert!(y.min(z) == y);
+        assert!(z.min(z) == z);
+    }
+}
diff --git a/codes/rust_lang/cli/src/main.rs b/codes/rust_lang/cli/src/main.rs
new file mode 100644
index 0000000000000000000000000000000000000000..f0a0a1a29abde0af7daa44bd8cad68507dc7a68c
--- /dev/null
+++ b/codes/rust_lang/cli/src/main.rs
@@ -0,0 +1,6 @@
+use cli::io;
+
+fn main() -> Result<(), String> {
+    io::read_command_line_builder()?;
+    Ok(())
+}
diff --git a/codes/rust_lang/cli/src/minimum.rs b/codes/rust_lang/cli/src/minimum.rs
new file mode 100644
index 0000000000000000000000000000000000000000..7d7a654b8f2c43bc76e35616813465c6142a0bff
--- /dev/null
+++ b/codes/rust_lang/cli/src/minimum.rs
@@ -0,0 +1,15 @@
+// If we remove Copy, we have a problem with the t in tab
+// in the computation of the minimum.
+pub trait Minimum: Copy {
+    fn min(self, rhs: Self) -> Self;
+}
+
+impl Minimum for i32 {
+    fn min(self, rhs: Self) -> Self {
+        if self < rhs {
+            self
+        } else {
+            rhs
+        }
+    }
+}
diff --git a/codes/rust_lang/cli/src/something_or_nothing.rs b/codes/rust_lang/cli/src/something_or_nothing.rs
new file mode 100644
index 0000000000000000000000000000000000000000..75ffecc1f05373eafb2701c20308b149c0651a94
--- /dev/null
+++ b/codes/rust_lang/cli/src/something_or_nothing.rs
@@ -0,0 +1,80 @@
+use std::fmt::Display;
+
+use crate::minimum::Minimum;
+
+/// An generic enumerated type that encapsulates and Option<T>.
+#[derive(Clone, Copy)]
+pub struct SomethingOrNothing<T>(Option<T>);
+
+impl<T: Minimum + Display> SomethingOrNothing<T> {
+    pub fn new(val: T) -> Self {
+        SomethingOrNothing(Some(val))
+    }
+    /// A static function that prints the content of a SomethingOrNothing.
+    pub fn to_string(&self) -> String {
+        match self.0 {
+            None => String::from("Nothing."),
+            Some(val) => format!("Something is: {}", val),
+        }
+    }
+}
+
+impl<T> Default for SomethingOrNothing<T> {
+    /// By Default a [SomethingOrNothing] is a nothing.
+    fn default() -> Self {
+        SomethingOrNothing(None)
+    }
+}
+
+impl<T: PartialEq + Minimum> PartialEq for SomethingOrNothing<T> {
+    fn eq(&self, other: &Self) -> bool {
+        match (self.0, other.0) {
+            (None, None) => true,
+            (Some(lhs), Some(rhs)) => lhs == rhs,
+            _ => false,
+        }
+    }
+}
+
+impl<T: Minimum + Display> Minimum for SomethingOrNothing<T> {
+    fn min(self, rhs: Self) -> Self {
+        match (self.0, rhs.0) {
+            (None, None) => SomethingOrNothing(None),
+            (Some(lhs), Some(rhs)) => SomethingOrNothing::new(lhs.min(rhs)),
+            (None, Some(rhs)) => SomethingOrNothing::new(rhs),
+            (Some(lhs), None) => SomethingOrNothing::new(lhs),
+        }
+    }
+}
+
+/// Computes the minimum of an Array of a type T which implements the [Minimum] trait.
+/// Returns a [Some] containing the the minimum value
+/// or [None] if no minimum value was found.
+///
+/// # Examples
+///
+/// ```
+/// # use cli::something_or_nothing::{SomethingOrNothing, find_min};
+/// # fn main() {
+/// let tab = vec![10, 32, 12, 43, 52, 53, 83, 2, 9];
+/// let min = find_min(&tab);
+/// assert!(min == SomethingOrNothing::new(2));
+/// # }
+/// ```
+///
+/// ```
+/// # use cli::something_or_nothing::{SomethingOrNothing, find_min};
+/// # fn main() {
+/// let tab: Vec<i32> = vec![];
+/// let min = find_min(&tab);
+/// assert!(min == SomethingOrNothing::default());
+/// # }
+/// ```
+pub fn find_min<T: Minimum + Display>(tab: &[T]) -> SomethingOrNothing<T> {
+    let mut minimum: SomethingOrNothing<T> = SomethingOrNothing(None);
+    // Here is T is Copyable. Which means that t is not moved in the loop
+    for t in tab {
+        minimum = minimum.min(SomethingOrNothing::new(*t));
+    }
+    minimum
+}