Générer une application complète avec Gemini CLI : fantasme ou réalité ?

Peut-on vraiment générer une application web complète avec FastAPI, React et base de données en moins d'une heure grâce à l'IA ? Gemini CLI le prétend. Test en conditions réelles avec un cahier des charges précis et... quelques surprises à la clé. Retour d'expérience sans filtre.

Cet article a été mis à jour le 22 août 2025 ; il prend 23 minutes à lire et comporte 5553 mots.

J’ai posé une question toute simple à Gemini 2.5 Flash : À quoi sert Gemini CLI ? Voici sa réponse, très… promotionnelle :

Et bien sûr, la question suivante était : Est-il possible de générer une application complète avec ? Question à laquelle j’ai eu une réponse claire :

Alors bien sûr, j’ai voulu tester. Pas question d’un Hello World. Je voulais un vrai test, avec une app déjà en production comme référence.

Ayant récemment développé une appli qui récupère des documents, les envoie à un LLM pour générer un résumé et en extraire des notions, j’ai voulu voir si cette IA faisait mieux que moi. En même temps, je ne suis pas un expert en Python, j’ai donc pensé que si je pouvais le faire, lui pouvait aussi.

Le cahier des charges

J’avais l’appli, j’en voulais une version simplifiée. J’ai donc gardé les éléments essentiels, avec une petite spécificité : je voulais utiliser AlloyDB Omni, la base de données compatible PostgreSQL de Google.

Le prompt pour Gemini CLI

L’un des points essentiels quand on utilise l’IA, est de bien définir son prompt. Ce n’est d’ailleurs pas un trait distinctif de l’IA, quel que soit le contexte, poser une question claire et précise augmente forcément les chances d’obtenir une réponse claire et précise. J’ai donc repris mon cahier des charges et je l’ai transposé en instructions claires pour Gemini Cli. Je l’ai d’abord rédigé en anglais, mais au final, je l’ai traduit, pour être certain de bien définir chaque point :

La demande était à mon avis suffisamment claire pour que l’IA me génère l’appli demandée.

Et après une vingtaine de minutes, et après avoir répondu à quelques questions, et validé un certain nombre d’actions, j’avais effectivement une application complète à disposition. Complète, oui, mais utilisable, non.

Et Gemini CLI n’avait pas respecté mon cahier des charges :

  • il n’avait pas initialisé d’environnement Git.
  • Il n’avait pas (et c’est logique) créé de fichier .gitignore, ni de fichier .env.sample.
  • Mais il n’avait pas non plus répondu à ma demande concernant le SGBD à utiliser : il a sans sourciller remplacé AlloyDB Omni par PostgreSQL.

Alors, ce n’est pas une hérésie, vu que AlloyDB Omni est 100% compatible PostreSQL. Mais quand je demande un ristretto, je ne veux pas un espresso. Ni d’un café allongé. Les deux sont compatibles, oui. Mais les performances, sur de gros datasets, ne sont pas les mêmes. Et PostgreSQL nécessite pgvector pour la gestion d’une base vectorielle, quand AlloyDB la gère nativement.

Il ne faut pas oublier non plus qu’AlloyDB Omni est une base de données Google, je pensais donc que ce point ne lui poserait pas problème. Comme quoi…

Je lui ai fourni un second prompt pour qu’il corrige ces points :

Alors oui, Gemini CLI a corrigé une partie des points demandés. Sans pour autant créer de référentiel Git. Je n’ai pas insisté, j’ai créé mon dépôt, j’ai committé et basta.

Et au delà de ses points de détail (oui, il faut savoir être indulgent), son appli n’était pas fonctionnelle. J’ai dû repasser derrière lui pour obtenir ce que je voulais :

Je lui ai fourni un ensemble clé / url dans le cahier des charges initial pour pour l’accès au LLM, il s’est empressé de créer une clé fictive et de changer l’url d’accès à l’API.

Par contre rien à redire au niveau de la structure elle-même :

Et son code est relativement bien écrit et documenté, comme on peut le voir ci-dessous (fichier backend/app/main.py) :

from fastapi import FastAPI, UploadFile, File, Depends, HTTPException
from fastapi.responses import FileResponse
from sqlmodel import Session
from . import crud, models, text_extractor, llm
from .db import engine, create_db_and_tables
import shutil
import os
import json
from typing import List

app = FastAPI()

def get_db():
    with Session(engine) as session:
        yield session

@app.on_event("startup")
def on_startup():
    create_db_and_tables()

@app.post("/upload/")
async def upload_file(file: UploadFile = File(...), db: Session = Depends(get_db)):
    # Create a directory to store uploaded files
    upload_dir = "uploads"
    os.makedirs(upload_dir, exist_ok=True)

    # Save the uploaded file
    file_path = os.path.join(upload_dir, file.filename)
    with open(file_path, "wb") as buffer:
        shutil.copyfileobj(file.file, buffer)

    # Extract text from the file
    try:
        content = text_extractor.extract_text(file_path)
    except ValueError as e:
        raise HTTPException(status_code=400, detail=str(e))

    # Get summary and keywords from LLM
    llm_response = llm.get_summary_and_keywords(content)

    # Parse the llm_response to get summary and keywords
    try:
        # Find the start of the JSON block
        json_start_index = llm_response.find("```json")
        if json_start_index == -1:
            raise ValueError("JSON block not found in the LLM response")

        summary = llm_response[:json_start_index].strip()
        json_str = llm_response[json_start_index + 7:].strip().strip("`")
        keywords = json.loads(json_str)
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"Error parsing LLM response: {e}")


    # Create document object
    doc = models.Document(
        filename=file.filename,
        content=content,
        summary=summary,
    )
    doc.set_keywords(keywords)
    db_doc = crud.create_document(db, doc)

    return db_doc

@app.get("/documents/", response_model=List[models.Document])
def get_documents(db: Session = Depends(get_db)):
    return crud.get_all_documents(db)

@app.get("/documents/{doc_id}", response_model=models.Document)
def get_document(doc_id: int, db: Session = Depends(get_db)):
    doc = crud.get_document(db, doc_id)
    if doc is None:
        raise HTTPException(status_code=404, detail="Document not found")
    return doc

@app.get("/download/{doc_id}")
def download_file(doc_id: int, db: Session = Depends(get_db)):
    doc = crud.get_document(db, doc_id)
    if doc is None:
        raise HTTPException(status_code=404, detail="Document not found")
    
    file_path = os.path.join("uploads", doc.filename)
    if not os.path.exists(file_path):
        raise HTTPException(status_code=404, detail="File not found")

    return FileResponse(file_path, filename=doc.filename)

@app.get("/search/")
def search_documents(query: str, db: Session = Depends(get_db)):
    # A simple search implementation
    docs = crud.get_all_documents(db)
    results = []
    for doc in docs:
        if query.lower() in doc.content.lower() or any(query.lower() in k.lower() for k in doc.get_keywords()):
            results.append(doc)
    return results

@app.get("/")
def read_root():
    return {"Hello": "World"}

Le code est plutôt propre et lisible dans l’ensemble, avec une architecture modulaire (séparation en modules crud, models, text_extractor, llm, etc.).

Les points positifs

  • Séparation des responsabilités : les fonctions de traitement (LLM, extraction de texte, base de données) sont bien isolées.
  • Utilisation correcte de Depends() et de Session() avec SQLModel : le pattern de dépendance est propre.
  • Vérifications robustes :
    • Existence du fichier
    • Retour du LLM parsé avec fallback si le JSON est mal formé
  • Upload de fichiers et persistance : tout est fonctionnel, logique, clair.
  • Conforme aux bonnes pratiques FastAPI (par exemple l’usage de @app.on_event("startup") pour initier la base de données).

Les points à améliorer

Quelques failles de robustesse (fichiers uploadés, parsing LLM, validation des entrées), mais rien de bloquant.

Pour une application « production ready », il faudrait :

  • isoler le parsing LLM dans une fonction solide avec tests unitaires,
  • ajouter un logger propre,
  • mettre en place une vérification MIME et un hash de fichier pour éviter les doublons.

Mais dans l’état, ce n’était pas demandé, on n’est plus dans le contexte initialement défini.

Par contre, j’avais hâte de voir le résultat, on peut avoir un code sublime, mais qui ne fait pas ce qu’on lui demande, j’ai donc procédé au…

Test de l’application en ligne de commande

C’est là que tout a commencé à se gâter : rien n’était fonctionnel. Et j’ai passé près de deux heures à mettre tout en ordre, en faisant appel à la console Gemini CLI mais surtout à d’autres LLM (chatGPT et Claude d’Anthropic) en situation de blocage.

Voici une liste non exhaustive des points sur lesquels j’ai dû intervenir :

  • L’appel au LLM – bien que je lui ai indiqué qu’il fallait passer par openrouter.ai pour appeler le LLM, Gemini CLI appelait directement l’API d’OpenAI : platform.openai.com – j’ai réécrit la fonction incriminée, après avoir tenté de le lui faire faire
  • J’ai dû ajouter python-multipart dans requirements.txt et curl dans le Dockerfile
  • Forcer la sortie en json pour obtenir un résultat interprétable. A nouveau, réécriture partielle d’un script.

Une fois ces point réglés, le texte a pu être uploadé et traité en lançant curl -F "file=@README.md" http://localhost:8000/upload/.

Sortie json correcte, et enregistrement en base de données effectué.

Mais pas encore de…

Test depuis un navigateur

L’affaire se corse : impossible d’accéder à l’appli via le navigateur. En remplaçant "dev": "vite" par "dev": "vite --host 0.0.0.0" dans packages.json, le problème initial est réglé.

J’accède enfin à l’application. Tout n’est pas rose pour autant. Tout ce que j’obtiens, c’est un sublime message d’erreur :

Et là, Gemini CLI échoue lamentablement quand je lui demande de corriger en lui indiquant l’erreur. Il rame, tourne à vide pendant près de 10 minutes, je le désactive et je tente avec un autre outil : blackbox.ai. Qui va me réécrire une bonne partie du code frontend. Sans pour autant régler le problème. npm aura eu raison de Gemini CLI et de Blackbox.

Je finis par demander une réécriture complète du frontend à Gemini CLI :

Et là, rien à dire, à part un petit bug visuel, Gemini CLI fait bien ce qu’on lui demande, mais en deux temps et sans pouvoir compléter certaines tâches. Il ne parvient pas par exemple à réécrire un fichier Dockerfile.frontend correct, je dois prendre la main. Mais j’obtiens l’interface demandée, et je réussis à analyser un fichier. Pour les besoins du test, j’ai pris une version texte de l’article sur le grand gâchis numérique, voici le résumé servi par Qwen 3 30B A3B :

Il me ressort également les mots / expressions clé :

Le rendu est correct – il n’y a que « Analyse en cours… » qui tourne en permanence, rien de désastreux :

Sortie frontend générée par Gemini Cli
Sortie frontend générée par Gemini Cli

Bilan de l’expérience

Alors, Gemini CLI est-il capable de créer une application à partir d’un cahier de charges relativement précis ?

On va dire que créer une application complète avec cet outil est possible – mais pas sans effort.

Voici les principaux enseignements que j’en retire :

Les points positifs :

  • L’outil comprend rapidement les intentions exprimées en langage naturel.
  • Il génère une structure de projet cohérente et bien modulaire.
  • Le code est propre, bien commenté, et suit généralement les bonnes pratiques.
  • Il gère les échanges itératifs (prompt → code → correction) de manière fluide.

Les limites et frustrations :

  • Il ne respecte pas toujours scrupuleusement le cahier des charges, même clair et bien formaté.
  • Des oublis réguliers sur des éléments clés comme .gitignore, .env.sample, init Git, ou même le choix du SGBD.
  • Il prend parfois des décisions “raisonnables” à ma place (comme remplacer AlloyDB par PostgreSQL sans prévenir).
  • Il ne rend pas une application prête à l’emploi : des ajustements manuels restent indispensables.

Test de reprise de contexte et modifications a posteriori

L’un des aspects les plus critiques d’un assistant IA de développement est sa capacité à reprendre le travail sur du code existant après une déconnexion. Pour tester cette fonctionnalité, j’ai volontairement fermé la console Gemini CLI et attendu le lendemain pour demander des modifications sur l’application générée.

Reconnaissance du projet existant

Temps de reprise de contexte : moins de 3 minutes

En relançant Gemini CLI dans le répertoire du projet, l’outil a immédiatement analysé la structure de fichiers et le code existant. Sans que j’aie besoin de lui rappeler le contexte ou les spécifications initiales, il m’a proposé un plan d’action détaillé pour les améliorations demandées.

Points positifs de cette reprise :

  • Identification correcte de l’architecture existante (FastAPI + React + AlloyDB)
  • Reconnaissance des points problématiques que j’avais corrigés manuellement la veille
  • Proposition de modifications cohérentes avec la structure modulaire mise en place

Un cas concret : la réécriture du frontend

Face aux problèmes insurmontables avec le frontend React/Vite initial, j’ai demandé à Gemini CLI de réécrire complètement cette partie en HTML/CSS/JavaScript pur. L’outil a parfaitement compris :

  • Les routes backend existantes (POST /extract)
  • Le format de données attendu (JSON avec summary et keywords)
  • Les contraintes techniques (pas de framework, pas de bundler)

Résultat : Une interface fonctionnelle générée rapidement, avec seulement quelques ajustements mineurs nécessaires (comme la correction du fichier Dockerfile.frontend).

Bilan de la reprise de contexte

Verdict : très convaincant

La capacité de Gemini CLI à reprendre le travail sur du code existant est l’un de ses points forts les plus marquants. Le contexte étendu de 1 million de tokens se traduit par une vraie efficacité pratique pour la maintenance et l’évolution de code, positionnant l’outil comme un véritable « partenaire de développement » capable d’assurer une continuité dans le temps.

Comparaison avec d’autres outils

J’ai déjà utilisé Claude ainsi que chatGPT pour développer des applications en ligne. Le code produit par Gemini Cli n’est ni plus ni moins valable que celui produit par ses concurrent, même si – en version gratuite, Claude ne permet pas d’aller très loin, et si chatGPT se perd souvent en cours de route. Il est évident que la limite de contexte de Gemini CLI n’y est pas pour rien : 1 million de tokens, ce n’est pas rien, surtout pour une petit projet. Mais les reproches faits aux deux autres outils sont à relativiser :

  • si chatGPT se perd souvent, son approche est plus solide, et son code tout aussi bien structuré
  • si Claude n’est pas envisageable dans sa version gratuite, le peu que j’ai pu voir de et outil me donne envie de tester la version payante

Concernant Blackbox, je n’ai pas réussi à me faire une opinion. Il a un intérêt, certes, mais il ne m’a pas permis d’aller au-delà de ce que Gemini Cli a pu faire.

Analyse du coût/bénéfice temporel

Il a fallu moins d’une demi heure à Gemini CLI pour générer une application complète. Imparfaite, mais complète. En comptant les 2 à 3 heures de réglages supplémentaires, et la rédaction du cahier des charges, on n’atteint pas les 4 heures. Combien de temps m’aurait-il fallu pour arriver au même résultat, en partant de zéro, si j’avais dû tout coder par moi-même ?

En résumé :

Gemini CLI est un assistant IA puissant pour accélérer le prototypage et la mise en route d’un projet, mais il ne remplace pas un développeur humain. Il offre un bon gain de temps pour générer la base d’une application, mais nécessite toujours un œil critique, des retouches, et une phase de test rigoureuse.

    Ne manquez plus un article…

    Abonnez-vous à la newsletter !

    C’est un outil prometteur, mais encore imparfait pour du “Code as a Service” automatisé de bout en bout.

    Et moi, j’ai appris de cette expérience. Pour l’essentiel…

    Les leçons que j’en ai tiré

    La précision du cahier des charges ne garantit pas le respect à 100%

    Même avec des spécifications détaillées et explicites (AlloyDB, fichiers .env, init Git), l’IA prend des « libertés » qu’elle juge raisonnables. Il faut s’attendre à devoir recentrer l’outil sur les exigences non négociables.

    Gemini CLI est excellent pour le scaffolding, moins pour les finitions

    Gemini CLI excelle pour générer une structure cohérente et du code propre, mais les détails d’intégration (configuration Docker, dépendances spécifiques, URLs d’API) nécessitent systématiquement une intervention humaine.

    Le contexte étendu est un vrai game-changer

    La capacité à reprendre le travail le lendemain en moins de 3 minutes et à comprendre l’architecture existante différencie nettement Gemini CLI des autres outils IA.

    Prévoir du temps de debug même sur du code « propre »

    Il ne faut pas confondre code bien structuré et code fonctionnel. Les 2 heures de corrections ne sont pas du temps perdu mais un investissement prévisible dans tout projet généré par IA.

    L’IA a ses propres « convictions techniques »

    PostgreSQL vs AlloyDB, choix d’URLs d’API… L’outil fait des substitutions qu’il considère comme équivalentes. Il faut explicitement insister sur les choix non négociables.

    Adopter une approche itérative payante

    Partir d’une demande globale puis affiner par étapes fonctionne mieux que d’essayer de tout spécifier d’un coup. L’exemple du frontend HTML/CSS/JS pur en est la preuve.

    Garder des alternatives sous la main

    ChatGPT et Claude ont été nécessaires pour débloquer certaines situations. Gemini CLI n’est pas omnipotent, avoir un plan B évite les blocages prolongés.

    Le ROI est positif malgré les corrections

    Même avec les corrections nécessaires, le gain de temps reste significatif par rapport à un développement from scratch, surtout pour le prototypage rapide.

    Gemini CLI est donc un excellent accélérateur de développement à condition d’accepter son rôle d’assistant perfectible plutôt que de développeur autonome.

    Voici le workflow que je recommande pour exploiter Gemini CLI de façon fiable :

    graph TD
    A[Spécifications techniques] --> AA[Prompt clair]
    AA --> B{Génération initiale}
    B --> C[Scaffolding]
    C --> D[Revue manuelle critique]
    D --> E{Corrections IA}
    E --> F[Tests intensifs]
    F --> G[Déploiement]
    G --> H[Documentation]
    

    Le mot de la fin

    En résumé, Gemini CLI impressionne par la puissance de son moteur de génération, mais reste perfectible dans le respect strict d’un cahier des charges complexe. L’outil est prometteur pour des prototypes ou MVPs, mais nécessite encore une supervision humaine pour les projets sérieux.

    Le verdict : Ni fantasme ni réalité absolue, mais un outil de transition vers une nouvelle façon de développer où l’humain reste indispensable pour la vision, la cohérence et la qualité finale.

    Aller plus loin

    Cette application constitue une base solide pour de nombreuses évolutions. Voici quelques pistes d’amélioration que vous pourriez explorer :

    Fonctionnalités avancées

    Analyse sémantique poussée : Remplacer la recherche par mots-clés par une recherche vectorielle basée sur des embeddings. Cela permettrait de retrouver des documents par similarité sémantique plutôt que par correspondance exacte.

    Multi-LLM et comparaison : Intégrer plusieurs modèles (Claude, GPT, Llama) pour générer différents résumés du même document et laisser l’utilisateur choisir le plus pertinent, ou même fusionner les analyses.

    Classification automatique : Ajouter un système de catégorisation automatique des documents par domaine (technique, juridique, marketing, etc.) avec un modèle de classification pré-entraîné.

    Historique et versioning : Conserver l’historique des analyses d’un même document pour suivre l’évolution des résumés selon les différentes versions du fichier.

    Améliorations techniques

    Traitement asynchrone : Implémenter une queue Redis + Celery pour traiter les gros fichiers en arrière-plan avec notification en temps réel du statut.

    Cache intelligent : Éviter de retraiter des documents identiques en utilisant un système de hash MD5 et de mise en cache des résultats.

    API robuste : Ajouter le versioning (/v1/, /v2/), la limitation de taux, la validation avancée des fichiers et un système de monitoring des performances.

    Visualisation et analytics

    Dashboard de visualisation : Créer des graphiques sur les mots-clés les plus fréquents, l’évolution temporelle des concepts, ou encore un nuage de mots interactif.

    Export enrichi : Proposer des exports en PDF avec résumés formatés, CSV des métadonnées, ou encore des formats compatibles avec Obsidian/Notion pour l’intégration dans des systèmes de gestion de connaissances.

    Vers la production

    Authentification et rôles : Système d’utilisateurs avec JWT, gestion des permissions et espaces de travail collaboratifs.

    Sécurité renforcée : Scan antivirus des fichiers uploadés, validation stricte des types MIME, et système de backup automatique.

    Expérimentations IA avancées

    RAG conversationnel : Transformer l’application en assistant capable de répondre à des questions sur l’ensemble des documents uploadés en utilisant le contexte des fichiers analysés.

    Résumés adaptatifs : Ajuster automatiquement la longueur et le style du résumé selon le type de document détecté (rapport technique vs article de blog).

    Extraction d’entités structurées : Identifier et extraire automatiquement les personnes, lieux, dates, organisations mentionnées avec des outils comme spaCy ou des modèles Transformers spécialisés.


    Le défi ultime ? Demander à Gemini CLI d’implémenter ces améliorations une par une. Ce serait un excellent moyen de tester ses capacités d’évolution sur du code existant tout en enrichissant progressivement l’application !

    Le dépôt est accessible sur Github : https://github.com/pcescato/readwise_light

    Sentez vous libre de le récupérer, de contribuer, d’en faire un fork… et de commenter cet article.

    Pascal CESCATO

    Je ne me contente pas de reformuler des communiqués ou de dérouler des specs. Je teste, je creuse, je démonte quand il faut - parce qu’un sujet mal compris est un sujet mal écrit. J’écris avec les mains dans le cambouis, sans simplifier à outrance ni recracher du marketing. Mon truc, c’est de rendre clair sans trahir, lisible sans lisser. Et non, je ne “fais pas du contenu”. Pas pour faire du contenu, en tout cas.

    S’abonner
    Notification pour
    guest
    0 Commentaires
    Le plus ancien
    Le plus récent Le plus populaire
    Commentaires en ligne
    Afficher tous les commentaires
    Table des matières
    Retour en haut
    Les cookies que nous utilisons sont indispensables au bon fonctionnement de ce site. Il n'y a aucun pistage publicitaire et les données statistiques recueillies sont anonymisées.
    J'ai compris