Ce guide va vous permettre de détecter automatiquement tous les liens cassés dans votre documentation en moins de 5 minutes. Vous apprendrez à installer Lychee, vérifier vos fichiers Markdown/HTML, et l'intégrer dans votre pipeline CI/CD pour ne plus jamais publier de liens morts.
Ce que vous apprendrez :
- à l'installer rapidement (Docker, cargo, gestionnaire de paquets)
- à vérifier des fichiers, des dossiers et des pages web
- à le configurer pour vos besoins spécifiques (cache, exclusions, formats de sortie)
- à l'intégrer dans un pipeline CI/CD (GitHub Actions, GitLab CI, hook Git)
- à diagnostiquer et corriger les liens cassés ou les faux positifs
Pourquoi Lychee ?
Section intitulée « Pourquoi Lychee ? »Imaginez que vous maintenez une documentation technique de 200 pages. Chaque page contient 10 à 20 liens vers d'autres pages, des sites externes, des dépôts GitHub. Au fil des mois, les liens morts s'accumulent :
- Des articles de blog changent d'URL
- Des projets GitHub sont archivés ou renommés
- Vos propres pages internes sont déplacées
- Des APIs changent de domaine
Résultat : vos lecteurs tombent sur des erreurs 404. Ils perdent confiance, quittent votre site, et votre réputation en prend un coup.
Lychee résout ce problème en parcourant tous vos fichiers et en testant chaque lien (HTTP, HTTPS, mailto, ancres). Il est asynchrone (vérifie plusieurs liens en parallèle), rapide (écrit en Rust), et facile à intégrer dans un workflow CI/CD.
Qu'est-ce que Lychee ?
Section intitulée « Qu'est-ce que Lychee ? »Lychee est un vérificateur de liens (link checker) ultra-rapide écrit en Rust. Il scanne vos fichiers Markdown, HTML, ou les pages web que vous lui indiquez, pour détecter les liens cassés ou invalides.
Liens officiels :
Fonctionnalités clés
Section intitulée « Fonctionnalités clés »Voici les capacités qui distinguent Lychee des autres vérificateurs de liens. Ces fonctionnalités répondent aux besoins réels des équipes qui maintiennent de la documentation à grande échelle :
| Fonctionnalité | Description | Exemple d'usage |
|---|---|---|
| Multi-formats | Markdown, HTML, texte brut | Documentation, blog, site statique |
| Asynchrone | Vérifie plusieurs liens en parallèle | Beaucoup de liens vérifiés en même temps |
| Cache | Évite de re-vérifier les mêmes URLs | Accélère les scans répétés |
| JSON output | Sortie structurée pour l'automatisation | Parsing dans un script CI/CD |
| Exclusions | Ignore certains domaines ou patterns | Exclure localhost, liens privés |
| Ancres | Vérifie les #fragment dans les URLs | S'assure que page.html#section existe |
| Email check | Valide les adresses mailto: | Détecte les emails invalides |
Pourquoi l'utiliser ?
Section intitulée « Pourquoi l'utiliser ? »Lychee a été créé par Matthias Endler pour maintenir le dépôt analysis-tools.dev, qui liste des centaines d'outils. Les liens cassaient régulièrement, et les solutions existantes présentaient des lacunes majeures qui rendaient leur utilisation difficile en production :
- Trop lentes (vérifications synchrones)
- Obsolètes (projets non maintenus)
- Limitées (pas de support Markdown, pas de cache)
Résultat : Lychee combine un contrôle asynchrone, un cache et la lecture native du Markdown, ce qui lui permet de vérifier de gros volumes de liens sans ralentir un pipeline.
Prérequis
Section intitulée « Prérequis »Avant de commencer, assurez-vous que votre environnement répond aux critères suivants. La bonne nouvelle : Lychee étant un binaire statique, les dépendances sont minimales.
Connaissances :
- Utilisation basique du terminal (Linux/macOS/Windows)
- Notions de Markdown ou HTML (optionnel mais utile)
Système :
- Linux, macOS, ou Windows (WSL2 recommandé)
- Docker ou Rust/Cargo ou gestionnaire de paquets
Outils (un seul suffit) :
- Docker (méthode la plus simple)
- Cargo (si vous développez en Rust)
- Gestionnaire de paquets : pacman, Homebrew, Scoop, Nix, etc.
Installation
Section intitulée « Installation »Lychee est distribué comme un binaire statique : pas de dépendances système compliquées. Choisissez la méthode qui vous convient.
La façon la plus simple, sans rien installer sur votre système :
docker run --init -it --rm \ -v "$(pwd)":/input \ lycheeverse/lychee:0.24.2@sha256:e2d19e57cf6ab037026f20b8e449a1f30d9d7f81eef4194763aab2eab20bd28d /inputExplication :
--init: Gère correctement les signaux (Ctrl+C)-v $(pwd):/input: Monte le dossier courant dans le conteneur/input: Chemin à scanner dans le conteneur
Vérification :
docker run --rm lycheeverse/lychee:0.24.2@sha256:e2d19e57cf6ab037026f20b8e449a1f30d9d7f81eef4194763aab2eab20bd28d --version# Affiche : lychee 0.24.2Si vous avez Rust installé, utilisez cargo :
cargo install lycheeAvec fonctionnalités optionnelles :
cargo install lychee \ --features native-tls,email-checkLes features optionnelles permettent d'activer des fonctionnalités supplémentaires selon vos besoins. Voici celles disponibles :
Options disponibles :
native-tls: Utilise OpenSSL (par défaut)rustls-tls: Alternative pure Rust (pas d'OpenSSL)email-check: Valide les adresses emailvendored-openssl: Compile OpenSSL depuis les sources
Vérification :
lychee --version# Affiche : lychee 0.24.2sudo pacman -S lycheebrew install lycheescoop install lycheenix-env -iA nixpkgs.lycheeUtilisation de base
Section intitulée « Utilisation de base »Une fois installé, Lychee s'utilise en ligne de commande. Voici les scénarios les plus courants.
-
Vérifier un fichier Markdown
Fenêtre de terminal lychee README.mdRésultat attendu (aucune erreur) :
🔍 10 Total (in 0s) ✅ 10 OK 🚫 0 ErrorsSi liens cassés :
Issues found in 1 input. Find details below.[README.md]:[ERROR] https://old-blog.example.com/post | Network error: Connection failed🔍 11 Total (in 8s) ✅ 6 OK 🚫 3 Errors 👻 1 Excluded 🔀 1 Redirects -
Vérifier tous les fichiers d'un dossier
Scanne récursivement tous les Markdown/HTML :
Fenêtre de terminal lychee docs/Ou avec un pattern spécifique :
Fenêtre de terminal lychee "docs/**/*.md" -
Vérifier les liens d'une page web
Lychee télécharge la page indiquée et teste les liens qu'elle contient :
Fenêtre de terminal lychee https://blog.stephane-robert.infoLychee ne suit pas les liens d'une page à l'autre pour explorer tout un site : il vérifie uniquement les liens trouvés dans la page indiquée. Il n'existe pas d'option de profondeur (
--max-depth) dans la version 0.24.2. Pour contrôler un site entier, scannez plutôt son dossier de build (voir « Site statique (HTML) » plus bas) ou fournissez la liste de ses pages. -
Vérifier plusieurs sources en une fois
Fenêtre de terminal lychee README.md docs/ https://example.com -
Lire les URLs depuis stdin
Utile pour piper depuis un autre outil :
Fenêtre de terminal echo "https://github.com" | lychee -Ou depuis un fichier :
Fenêtre de terminal cat urls.txt | lychee - -
Utiliser un glob pattern avancé
Fenêtre de terminal lychee "**/*.{md,html,txt}"Scanne tous les
.md,.html, et.txtrécursivement.
Exemple de sortie
Section intitulée « Exemple de sortie »Voici ce que vous verrez lors d'un scan typique :
$ lychee docs/
12/12 ━━━━━━━━━━━━━━━━━━━━ Finished extracting links
Issues found in 1 input. Find details below.
[README.md]: [ERROR] https://old-blog.example.com/post | Network error: Connection failed
🔍 12 Total (in 8s) ✅ 7 OK 🚫 3 Errors 👻 1 Excluded 🔀 1 RedirectsChaque indicateur de la ligne de résumé a une signification précise :
| Indicateur | Signification |
|---|---|
| Total | Nombre total de liens trouvés |
| OK | Liens valides (codes 200-299) |
| Errors | Liens cassés ou inaccessibles |
| Excluded | Liens exclus par la configuration |
| Redirects | Redirections détectées (301, 302) |
| Cached | Résultats provenant du cache |
Configuration avancée
Section intitulée « Configuration avancée »Exclure certains liens
Section intitulée « Exclure certains liens »Certains liens sont volontairement cassés (exemples dans la doc) ou privés (localhost, intranets). Vous pouvez les exclure.
Option 1 : Ligne de commande
lychee --exclude 'localhost|127\.0\.0\.1' docs/Les valeurs de --exclude sont des expressions régulières, interprétées par le moteur de Rust : | sépare des alternatives, \. désigne un point littéral (un . seul accepte n'importe quel caractère) et \d+ un ou plusieurs chiffres. Cette syntaxe de base est la même que dans les autres langages : la leçon Expressions régulières en Python en détaille les symboles, et Expressions régulières de base sous Linux couvre celle de grep -E.
Option 2 : Fichier de configuration
Créez un fichier lychee.toml. Les guillemets simples y définissent des chaînes littérales : les antislashs des motifs restent intacts. La clé exclude ne peut apparaître qu'une fois : regroupez-y localhost, IPs privées et domaines à ignorer.
# Exclure localhost, les IPs privées et des domaines d'exempleexclude = [ 'localhost', '127\.0\.0\.1', '192\.168\.\d+\.\d+', '10\.\d+\.\d+\.\d+', 'example\.com', 'placeholder\.org']
# Ignorer certains chemins de fichiersexclude_path = [ 'node_modules/', '.git/', 'vendor/']Utilisation :
lychee --config lychee.toml docs/Activer le cache
Section intitulée « Activer le cache »Par défaut, Lychee re-vérifie tous les liens à chaque exécution. Avec le cache, il se souvient des liens déjà validés.
lychee --cache docs/Le cache est stocké dans un fichier .lycheecache, créé dans le répertoire où vous lancez la commande. Pensez à l'ajouter à votre .gitignore.
Au second run, les résultats mis en cache apparaissent :
[ERROR] https://broken-site.com | Error (cached)🔍 11 Total (in 0s) ✅ 7 OK 🚫 1 Error 👻 4 ExcludedVider le cache :
rm .lycheecacheFormats de sortie
Section intitulée « Formats de sortie »Lychee supporte plusieurs formats pour intégrer les résultats dans d'autres outils. Choisissez le format adapté à votre cas d'usage : lecture humaine en console, automatisation dans un script, ou rapport à inclure dans votre documentation.
| Format | Usage | Commande |
|---|---|---|
| Texte | Lecture humaine (défaut) | lychee docs/ |
| JSON | Parsing automatisé | lychee --format json docs/ |
| Markdown | Rapport à inclure dans un README | lychee --format markdown docs/ |
| CSV | Import dans Excel/Sheets | lychee --format csv docs/ |
Exemple JSON :
{ "total": 11, "successful": 6, "unknown": 0, "unsupported": 0, "timeouts": 0, "redirects": 1, "excludes": 1, "errors": 3, "cached": 0, "error_map": { "README.md": [ { "url": "https://old-blog.example.com/post", "status": { "text": "Network error: Connection failed", "details": "Connection failed. Check network connectivity" } } ] }}Redirection vers un fichier :
lychee --format json docs/ > report.jsonVérifier les ancres (fragments)
Section intitulée « Vérifier les ancres (fragments) »Par défaut, Lychee vérifie uniquement que https://example.com/page répond. Pour vérifier que https://example.com/page#section contient bien l'ancre #section :
lychee --include-fragments docs/Cas d'usage : Vous avez des liens vers des sections précises d'une page (#installation, #configuration). Si la section est renommée, le lien devient invalide.
Gérer les rate limits
Section intitulée « Gérer les rate limits »Certains sites limitent le nombre de requêtes par seconde. Lychee peut être trop rapide et se faire bloquer.
Ralentir les requêtes :
lychee --max-concurrency 5 docs/Ajouter un délai entre les requêtes vers un même hôte, avec --host-request-interval (50 ms par défaut) :
lychee --host-request-interval 1s docs/ # 1 seconde de pauseHeaders personnalisés (pour contourner des blocages) :
lychee --header "User-Agent: Mozilla/5.0" docs/Intégration CI/CD
Section intitulée « Intégration CI/CD »GitHub Actions
Section intitulée « GitHub Actions »L'usage principal de Lychee est de vérifier les liens à chaque commit pour éviter de publier des liens cassés.
Lychee fournit une GitHub Action officielle qui simplifie l'intégration dans vos workflows.
Exemple de workflow (.github/workflows/links.yml) :
name: Vérification des liens
on: push: branches: [main] pull_request:
jobs: link-check: runs-on: ubuntu-latest steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Vérifier les liens avec Lychee uses: lycheeverse/lychee-action@e7477775783ea5526144ba13e8db5eec57747ce8 # v2.9.0 with: args: --verbose --no-progress './**/*.md' './**/*.html' fail: true # Échoue si liens cassés env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}Avec cache pour accélérer les vérifications :
- name: Vérifier les liens uses: lycheeverse/lychee-action@e7477775783ea5526144ba13e8db5eec57747ce8 # v2.9.0 with: args: --cache --verbose './**/*.md' fail: true env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}Ajouter un commentaire sur la PR en cas d'erreur :
- name: Commenter la PR if: failure() uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 with: script: | github.rest.issues.createComment({ issue_number: context.issue.number, owner: context.repo.owner, repo: context.repo.repo, body: 'Des liens cassés ont été détectés. Voir les logs CI.' })GitLab CI
Section intitulée « GitLab CI »Pour GitLab CI, la configuration est encore plus simple puisque Lychee fournit une image Docker officielle, épinglée ici par version et par digest. Voici un job minimal qui s'exécute à chaque push :
link-check: image: lycheeverse/lychee:0.24.2@sha256:e2d19e57cf6ab037026f20b8e449a1f30d9d7f81eef4194763aab2eab20bd28d script: - lychee --cache --verbose --format json --output lychee-report.json './**/*.md' artifacts: when: on_failure paths: - lychee-report.jsonPipeline local (pre-commit)
Section intitulée « Pipeline local (pre-commit) »Vérifiez les liens avant de commit avec un hook Git. L'option --offline ne teste que les liens vers des fichiers locaux, sans requête réseau : le hook reste instantané et évite de pousser des liens internes cassés, ce qui économise du temps CI. Les liens externes restent à la charge du pipeline.
Créez un fichier dans votre dépôt avec ce contenu :
.git/hooks/pre-commit :
#!/bin/bashlychee --offline README.md docs/if [ $? -ne 0 ]; then echo "Liens cassés détectés. Corrigez avant de commit." exit 1fiRendre le hook exécutable :
chmod +x .git/hooks/pre-commitDépannage
Section intitulée « Dépannage »Problème : Timeouts fréquents
Section intitulée « Problème : Timeouts fréquents »Symptôme :
[ERR] https://slow-site.com (Timeout after 20s)Cause : Le site est lent ou votre connexion est instable.
Solution : Augmenter le timeout :
lychee --timeout 60 docs/Problème : Rate limit atteint
Section intitulée « Problème : Rate limit atteint »Symptôme :
[429] https://api.github.com/repos/... (Too Many Requests)Cause : Trop de requêtes en parallèle vers la même API.
Solution 1 : Réduire la concurrence et espacer les requêtes vers un même hôte :
lychee --max-concurrency 2 --host-request-interval 1s docs/Solution 2 : Ajouter un token GitHub (pour les URLs GitHub) :
export GITHUB_TOKEN=ghp_your_tokenlychee docs/Problème : Faux positifs (liens valides marqués cassés)
Section intitulée « Problème : Faux positifs (liens valides marqués cassés) »Symptôme : Un lien fonctionne dans le navigateur mais échoue dans Lychee.
Cause : Le site bloque les requêtes sans User-Agent ou cookies.
Solution : Ajouter des headers :
lychee --header "User-Agent: Mozilla/5.0" \ --header "Accept: text/html" \ docs/Ou exclure le domaine si c'est un cas isolé :
lychee --exclude 'problematic-site\.com' docs/Problème : Ancres non détectées
Section intitulée « Problème : Ancres non détectées »Symptôme : #section marquée comme invalide alors qu'elle existe.
Cause : Par défaut, Lychee ne vérifie pas les fragments.
Solution :
lychee --include-fragments docs/Problème : Liens locaux cassés
Section intitulée « Problème : Liens locaux cassés »Symptôme :
[ERR] ./assets/image.png (File not found)Cause : Chemin relatif incorrect ou fichier réellement absent.
Solution 1 : Vérifier que le fichier existe :
ls -la ./assets/image.pngSolution 2 : Utiliser --base-url si votre site n'est pas servi depuis la racine :
lychee --base-url https://example.com/blog/ docs/Exemples de configuration réels
Section intitulée « Exemples de configuration réels »Les sections précédentes vous ont montré les options une à une. Voici maintenant trois configurations complètes, prêtes à l'emploi, pour des cas d'usage fréquents. Copiez celle qui correspond à votre projet et ajustez-la.
Documentation technique (Markdown)
Section intitulée « Documentation technique (Markdown) »Cas d'usage : Dépôt GitHub avec des guides en Markdown.
Cette configuration est optimisée pour un dépôt de documentation classique. Elle active le cache pour accélérer les scans répétés, exclut les répertoires de build, et vérifie les ancres pour détecter les liens internes cassés.
lychee.toml :
# Exclure les exemples et localhostexclude = [ 'localhost', 'example\.(com|org|net)', '127\.0\.0\.1']
# Vérifier les ancresinclude_fragments = true
# Cache activécache = true
# Timeout augmenté (certains sites de docs sont lents)timeout = 30
# Format JSON pour parsingformat = "json"
# Ignorer node_modules et .gitexclude_path = [ 'node_modules/', '.git/', 'vendor/', 'dist/']Commande :
lychee --config lychee.toml .Site statique (HTML)
Section intitulée « Site statique (HTML) »Cas d'usage : Site généré par Hugo/Jekyll/Astro.
Pour un site web généré, cette configuration se concentre sur le dossier de build final (public/ ou dist/). Elle exclut les domaines tiers (analytics, CDN) qui peuvent causer des faux positifs.
# Vérifier uniquement le build finalbase_url = "https://blog.stephane-robert.info"
# Exclure les domaines analytics et CDNsexclude = [ 'google-analytics\.com', 'googletagmanager\.com', 'cdn\.jsdelivr\.net']
# Vérifier les fragments (ancres de navigation)include_fragments = true
# Format Markdown pour rapportformat = "markdown"
# Ignorer les répertoires de buildexclude_path = [ 'node_modules/', '.cache/', 'dist/', 'public/']Commande :
lychee --config lychee.toml public/Blog personnel
Section intitulée « Blog personnel »Cas d'usage : Blog avec des liens externes vers des articles de référence.
Cette configuration est adaptée aux blogs qui citent beaucoup de sources externes. Elle augmente le timeout pour gérer les sites lents, ajoute des tentatives (max_retries) pour la résilience, et ralentit les requêtes pour éviter les rate limits.
# Timeout augmenté (certains blogs sont lents)timeout = 45
# Exclure les liens sponsorisésexclude = [ 'bit\.ly', 'goo\.gl', 't\.co']
# Cache activécache = true
# Réessayer 3 fois en cas d'échecmax_retries = 3
# Délai minimal entre requêtes vers un même hôte (rate limits)host_request_interval = "500ms"À retenir
Section intitulée « À retenir »- Lychee détecte automatiquement les liens cassés dans Markdown, HTML, et sites web.
- Installation simple : Docker, cargo, ou gestionnaire de paquets.
- Usage basique :
lychee README.mdpour un fichier,lychee docs/pour un dossier. - Pas d'exploration de site : Lychee teste les liens de la page ou du dossier indiqués et ne suit pas les liens d'une page à l'autre (pas de
--max-depth). - Cache et exclusions : Accélérez les scans et ignorez les faux positifs ;
--excludeprend des expressions régulières. - Rate limits :
--max-concurrencyet--host-request-intervalespacent les requêtes vers un même hôte. - Intégration CI/CD : GitHub Actions, GitLab CI, ou hooks Git pour vérifications automatiques.
- Configuration TOML : Centralisez vos règles dans
lychee.tomlpour éviter les longues commandes. - Formats de sortie : JSON, Markdown, CSV pour automatisation ou rapports.
- Vérification des ancres : Utilisez
--include-fragmentspour valider les#section.
Prochaines étapes
Section intitulée « Prochaines étapes »Ressources supplémentaires
Section intitulée « Ressources supplémentaires »- Site officiel Lychee : Documentation complète et guides
- Dépôt GitHub lycheeverse/lychee : Code source, issues et releases
- Changelog : Nouvelles fonctionnalités et corrections
- GitHub Action lychee-action : Intégration CI/CD officielle
FAQ : questions fréquentes
Section intitulée « FAQ : questions fréquentes »mailto, ancres) pour détecter ceux qui sont cassés. Asynchrone et rapide, il s'intègre facilement dans un pipeline CI/CD.lychee suivi d'un fichier, d'un dossier ou d'un glob : lychee README.md, lychee docs/, ou lychee '**/*.md'. Sans rien installer, on peut aussi utiliser l'image Docker officielle lycheeverse/lychee. Lychee scanne récursivement et teste tous les liens trouvés.--exclude ou un fichier lychee.toml (clé exclude). Pour les sites qui bloquent les robots, on ajoute un User-Agent (--header), on augmente le timeout, on réduit la concurrence (--max-concurrency) ou on espace les requêtes vers un même hôte (--host-request-interval 1s). Il n'existe pas de clé exclude_domains, seulement exclude.lycheeverse/lychee-action) et une image Docker utilisable dans GitLab CI. On peut aussi l'appeler dans un hook pre-commit pour bloquer les liens cassés avant le push, et persister son cache entre les runs pour accélérer.