- packs/essentiels : 20 prompts en 4 catégories (Général, Écriture, Code, Analyse), en-têtes conformes au parseur, variables déclarées = utilisées - tests/run_tests.ahk : suites Frontmatter, Variables, JSON, Recherche, encodage UTF-8 (à exécuter sous Windows avec AutoHotkey v2) - scripts/check_pack.py + .gitea/workflows/ci.yml : cohérence du pack - build.ps1 : tests puis compilation Ahk2Exe et zip portable - docs : document d'architecture et de conception v1.0
72 KiB
PromptKey — Gestionnaire de prompts pour IA sous AutoHotkey
Architecture et conception — v1.0 — 2026-10-11 Statut : document de conception, à valider avant implémentation Nom de travail : PromptKey (à confirmer, §20-Q1) Environnement cible : Windows 10 / 11, AutoHotkey v2.0 (64 bits)
Table des matières
- Résumé décisionnel
- Le problème et les cas d'usage
- Périmètre : ce que PromptKey fait, et ce qu'il ne fait pas
- Pourquoi AutoHotkey — et ses limites assumées
- Décisions structurantes (D1 à D8)
- Architecture d'ensemble
- Modèle de données : un prompt = un fichier Markdown
- Le Quick Picker : la surface principale
- Le Gestionnaire et l'Éditeur
- Le moteur de variables
- Le moteur d'injection : livrer le prompt à l'IA
- Profils de destination (les « IA cibles »)
- Raccourcis globaux et hotstrings
- Recherche : index en mémoire et classement flou
- Historique, favoris et statistiques d'usage
- Import, export et packs de prompts
- Paramètres, portabilité et synchronisation
- Sécurité et vie privée
- Architecture du code AutoHotkey v2
- Maquettes des écrans (ASCII)
- Packaging, installation et mises à jour
- Tests et critères de qualité
- Plan d'implémentation en phases (tickets)
- Risques et mitigations
- Alternatives écartées
- Décisions ouvertes pour Bruno
- Annexe A — Exemple complet d'un fichier prompt
- Annexe B — Algorithme de classement de la recherche
- Annexe C — Séquence d'injection, pas à pas
- Annexe D — Pack de démarrage proposé (20 prompts)
1. Résumé décisionnel
PromptKey est une petite application Windows, écrite en AutoHotkey v2, qui vit dans la zone de notification (tray) et qui répond à un seul besoin, partout dans Windows, en moins de deux secondes :
« Je suis dans ChatGPT / Claude / Gemini / Qwen / un éditeur / un courriel. Je veux insérer le bon prompt, adapté à ce texte-ci, sans quitter le clavier ni fouiller dans un fichier de notes. »
Le geste central tient en trois touches et quelques frappes :
Ctrl+Alt+Espace → taper « résu… » → Entrée → remplir 1-2 variables → le prompt est collé, prêt à envoyer
Les cinq choix qui structurent tout le reste du document :
| # | Décision | En une phrase |
|---|---|---|
| D1 | AutoHotkey v2 uniquement | Pas de v1 : syntaxe moderne, classes, Map, meilleure maintenabilité. |
| D2 | Un prompt = un fichier .md |
Source de vérité en fichiers Markdown avec en-tête structuré : lisibles, éditables partout (dont Obsidian), versionnables sous Git/Gitea, jamais enfermés dans un format propriétaire. |
| D3 | Index en mémoire, pas de base de données en v1 | Chargement complet au démarrage + cache JSON ; suffisant et rapide jusqu'à ~5 000 prompts, zéro DLL externe. |
| D4 | Injection par presse-papiers restauré, par défaut | Coller via Ctrl+V après sauvegarde du presse-papiers, restauration après délai ; SendText en repli configurable pour les champs récalcitrants. |
| D5 | Aucun appel réseau, aucun envoi automatique | PromptKey insère du texte dans le champ actif ; il n'appelle aucune API d'IA et n'appuie jamais sur « Envoyer » à la place de l'utilisateur (option explicite par profil, désactivée par défaut). |
Conséquence directe : PromptKey est agnostique de l'IA. Il sert aussi bien une page web ChatGPT qu'une application de bureau, un terminal, Hermes, un client courriel ou un document Word — partout où un champ texte accepte un collage. Changer d'IA ne change rien à la bibliothèque de prompts ; seuls des profils de destination (§12) ajustent la forme (longueur, format, langue, touche d'envoi).
Livrable visé à la fin du plan (§23) : un PromptKey.exe portable compilé (Ahk2Exe), un dossier Prompts\ de départ (Annexe D), et ce document comme cahier des charges.
2. Le problème et les cas d'usage
2.1 Le problème, concrètement
Travailler avec plusieurs IA au quotidien produit le même cycle coûteux :
- Dispersion. Les bons prompts vivent dans des notes, des courriels, des fichiers texte, la mémoire — rarement retrouvés au moment voulu.
- Retapage. Le même prompt « résume ce texte en 5 points, ton neutre » est retapé, réadapté, dégradé à chaque usage.
- Perte du contexte. Le prompt idéal dépend du texte sélectionné, du presse-papiers, de la date, du projet — recopiés à la main.
- Friction de changement d'outil. Un prompt taillé pour une IA (format, longueur, consignes) est réécrit pour l'autre.
- Aucune mémoire d'usage. Impossible de savoir quels prompts servent vraiment, lesquels sont des doublons morts.
Le coût n'est pas le temps de frappe : c'est l'interruption de flux — quitter l'application, chercher, copier, revenir, recoller, réadapter.
2.2 Cas d'usage nominaux
| # | Cas | Déroulement cible |
|---|---|---|
| U1 | Prompt simple | Dans Claude (web), Ctrl+Alt+Espace → « traduis » → Entrée → le prompt de traduction est collé avec le texte sélectionné déjà incorporé. |
| U2 | Prompt à variables | « Revue de code » demande {{langage}} (liste : Python / JS / AHK…) et {{niveau}} (liste : rapide / strict) dans un mini-formulaire, puis colle le prompt résolu. |
| U3 | Prompt sur sélection | Sélectionner un paragraphe dans Word → raccourci → choisir « Reformuler » → le texte sélectionné est capturé automatiquement et injecté dans {{selection}}. |
| U4 | Prompt favori sans recherche | Ctrl+Alt+1 colle directement le prompt épinglé n° 1, sans ouvrir aucune fenêtre. |
| U5 | Abréviation tapée | Taper ::resu; dans n'importe quel champ le remplace par le prompt « Résumer » (hotstring, §13.2). |
| U6 | Bibliothèque qui grandit | Nouveau prompt créé depuis le Gestionnaire en 30 s, ou depuis la sélection (« Enregistrer la sélection comme prompt »), classé par catégorie et étiquettes. |
| U7 | Changement d'IA | Le même prompt « Explique » est utilisé dans Qwen avec le profil Qwen (consignes resserrées, réponse en français) et dans ChatGPT avec le profil par défaut — le corps du prompt ne change pas, le profil ajoute son préambule. |
| U8 | Partage / sauvegarde | Exporter une catégorie en un fichier .zip de .md (ou la versionner dans un dépôt Gitea) ; l'importer sur un autre poste en glisser-déposer. |
2.3 Personnes et contexte d'usage
Utilisateur unique, poste Windows personnel, usage au clavier d'abord. L'application doit rester utile hors ligne, sans compte, sans serveur — y compris quand l'IA cible est elle-même locale ou dans un terminal.
3. Périmètre : ce que PromptKey fait, et ce qu'il ne fait pas
3.1 Dans le périmètre (v1 visée par ce document)
- Bibliothèque locale de prompts : créer, modifier, dupliquer, supprimer, classer (catégories + étiquettes), épingler.
- Recherche instantanée floue (titre, étiquettes, catégorie, corps) et navigation 100 % clavier.
- Variables typées dans les prompts, résolues par mini-formulaire ou automatiquement (sélection, presse-papiers, date…).
- Injection du prompt résolu dans l'application active, par presse-papiers ou par frappe simulée.
- Profils de destination (préambule, format, option « envoyer après insertion » désactivée par défaut).
- Raccourcis globaux personnalisés par prompt + hotstrings.
- Historique d'usage local, favoris, compteurs (pour le classement « fréquents »).
- Import/export Markdown et JSON ; packs de prompts.
- Paramètres : raccourci principal, délais d'injection, thème, dossier de bibliothèque, démarrage avec Windows.
3.2 Hors périmètre (explicitement)
- Appeler une API d'IA. PromptKey ne parle à aucun modèle ; il prépare et insère du texte. (Une extension « envoyer à l'API et coller la réponse » est discutée en phase optionnelle §23.7, hors v1.)
- Gérer des conversations ou l'historique des réponses des IA.
- Synchroniser tout seul : la synchro passe par le dossier (Git, OneDrive, dossier partagé) — PromptKey détecte les changements de fichiers, il ne transporte rien (§17.3).
- Mac / Linux : AutoHotkey est Windows seulement (§4.2).
- Multi-utilisateur, partage en temps réel, permissions.
- Stocker des secrets : les prompts ne doivent pas contenir de clés d'API ; les variables de type « masqué » existent pour la saisie ponctuelle, jamais persistées (§18).
4. Pourquoi AutoHotkey — et ses limites assumées
4.1 Ce qu'AutoHotkey v2 apporte, exactement pour ce besoin
- Raccourcis globaux et hotstrings natifs, fiables dans presque toutes les applications Windows — c'est le cœur du besoin, et c'est la spécialité historique d'AHK.
- Manipulation du presse-papiers (
A_Clipboard,ClipWait) et envoi de frappes (Send,SendText) intégrés, sans dépendance. - GUI native (
Gui,ListView,TreeView,Edit) suffisante pour un sélecteur rapide et un gestionnaire en trois volets. - Exécutable autonome via Ahk2Exe : un seul
.exe, aucun runtime à installer chez l'utilisateur final (AHK v2 reste requis seulement pour développer). - Démarrage rapide, empreinte mémoire faible, processus tray discret — adapté à un outil invoqué 50 fois par jour.
4.2 Limites assumées (et leur traitement dans ce document)
| Limite | Traitement |
|---|---|
| Windows seulement | Assumé (§3.2). La bibliothèque en .md reste portable : si un équivalent Mac/Linux naît un jour, il relira les mêmes fichiers. |
| Applications élevées (administrateur) : un AHK non élevé ne peut pas leur envoyer de frappes | Détection + message clair (§11.5) ; option « relancer en administrateur » documentée, jamais forcée. |
| Champs riches (éditeurs web, contenteditable) où le collage formate ou échoue | Profils par application avec méthode d'injection dédiée (§12) ; repli SendText. |
Les .exe compilés AHK déclenchent parfois des faux positifs antivirus |
Distribution du .ahk source en parallèle, compilation reproductible documentée (§21.3) ; pas de comportement réseau qui aggraverait le score. |
| GUI native limitée (pas de « beau » framework) | Design fonctionnel : Picker minimal et rapide plutôt que joli ; soin porté à la typographie, au thème sombre et au clavier (§20). |
| Pas de vrai YAML ni de SQLite intégrés | Sous-ensemble d'en-tête strictement défini et parsé par un module dédié (§7.3) ; index en mémoire (§14). |
| Raccourcis déjà pris par d'autres applications | Détection de conflit à l'enregistrement et rapport dans les Paramètres (§13.3). |
5. Décisions structurantes (D1 à D8)
D1 — AutoHotkey v2.0 64 bits uniquement
Toute la base de code cible la syntaxe v2 : classes, Map(), fonctions fléchées, Gui orienté objet. Aucun code v1, aucune double compatibilité : mélanger les dialectes est la première source de bogues AHK. Version minimale épinglée : v2.0.10+ (correctifs ListView / DPI).
D2 — Un prompt = un fichier Markdown
Chaque prompt est un fichier Nom-du-prompt.md dans le dossier de bibliothèque :
- En-tête (frontmatter délimité par
---) : métadonnées structurées (§7.2). - Corps : le texte du prompt, avec ses variables
{{…}}.
Avantages décisifs pour l'usage visé : éditable dans n'importe quel éditeur (dont le Gestionnaire intégré, mais aussi VS Code ou Obsidian), cherchable par grep, versionnable sous Git (un dépôt Gitea privé fait une sauvegarde et un historique parfaits), partageable fichier par fichier. Le coût — un parseur d'en-tête maison — est borné par un sous-ensemble strict (§7.3) et couvert par des tests (§22).
Rejeté : base SQLite comme source de vérité (opaque, non éditable à la main, DLL externe) ; fichier JSON unique géant (conflits de fusion, illisible dès 100 prompts). Le JSON reste utilisé pour le cache d'index (§14.2) et l'export, jamais comme source.
D3 — Index en mémoire reconstruisible
Au démarrage, PromptKey lit tous les .md, construit l'index en mémoire et le met en cache (index-cache.json, invalidé par date/taille des fichiers). La recherche travaille sur l'index, pas sur le disque. Plafond de conception : 5 000 prompts, recherche < 100 ms. Au-delà, une phase ultérieure pourra adosser SQLite sans changer le format source (D2 reste intact).
D4 — Injection : presse-papiers restauré par défaut, frappe en repli
Comparatif tranché (§11 donne le détail) :
| Méthode | Vitesse | Fidélité (Unicode, sauts de ligne) | Risques |
|---|---|---|---|
Presse-papiers + Ctrl+V |
Instantanée | Excellente | Écrase brièvement le presse-papiers → sauvegarde/restauration obligatoires |
SendText (frappe simulée) |
Lente sur longs prompts | Bonne, mais sensible à la disposition clavier | Interférences (IMEs, champs qui interceptent), focus perdu = texte dans le vide |
Défaut : presse-papiers, avec restauration après un délai configurable (1,5 s par défaut) et abandon de la restauration si l'utilisateur a copié autre chose entre-temps (§11.3).
D5 — Insérer, ne pas envoyer
Après injection, le curseur reste chez l'utilisateur : il relit, ajuste, envoie lui-même. L'option « Entrée automatique après insertion » existe par profil de destination, désactivée par défaut, avec un délai de grâce de 800 ms annulable par Échap (§12.3). Principe : un mauvais prompt collé se corrige ; un mauvais prompt envoyé — éventuellement au mauvais fil — ne se rattrape pas.
D6 — Processus tray unique, aucune fenêtre au repos
Instance unique (#SingleInstance Force), icône tray, aucune fenêtre visible tant qu'on n'invoque pas PromptKey. Fermer une fenêtre = la masquer, jamais quitter (quitter se fait par le menu tray).
D7 — Zéro réseau en v1
Aucun appel sortant : ni télémétrie, ni vérification de mise à jour en ligne, ni « amélioration IA du prompt ». Cela simplifie la sécurité (§18), les antivirus (§4.2) et la confiance. Les mises à jour sont manuelles (§21.4).
D8 — Clavier d'abord, souris en appoint
Chaque action du Picker et du Gestionnaire a un chemin clavier complet ; les listes se naviguent aux flèches, Entrée valide, Échap ferme et rend le focus à l'application d'origine (§11.2 — le retour de focus est une fonction de premier rang, pas un détail).
6. Architecture d'ensemble
6.1 Vue logique
┌────────────────────────────────────────────────────────────────────┐
│ PromptKey.exe (AHK v2) │
│ │
│ ┌──────────────┐ ┌───────────────┐ ┌───────────────────────┐ │
│ │ Entrées │ │ Surfaces GUI │ │ Services (classes) │ │
│ │ │ │ │ │ │ │
│ │ Raccourcis │──▶│ Quick Picker │──▶│ PromptStore (fichiers)│ │
│ │ globaux │ │ Gestionnaire │ │ Index/Recherche │ │
│ │ Hotstrings │ │ Éditeur │ │ VariableEngine │ │
│ │ Menu tray │ │ Formulaire │ │ Injector │ │
│ │ Clic tray │ │ variables │ │ ClipboardGuard │ │
│ │ │ │ Paramètres │ │ HotkeyManager │ │
│ └──────────────┘ └───────────────┘ │ UsageStats │ │
│ ▲ │ Settings │ │
│ │ └──────────┬────────────┘ │
└─────────┼──────────────────────────────────────────┼───────────────┘
│ │
Clavier/souris Disque (local uniquement)
(toutes applications) ┌───────────────────────────────┐
│ Bibliothèque\ *.md (source) │
│ config.ini / index-cache.json │
│ usage.json / promptkey.log│
└───────────────────────────────┘
6.2 Flux principal (le « chemin heureux »)
1. L'utilisateur travaille dans l'application X (focus sur X).
2. Raccourci global → PromptKey mémorise la fenêtre active (hwnd X) et son titre.
3. Le Picker s'ouvre (déjà chargé : l'index est en mémoire), focus sur la recherche.
4. Frappe + flèches → le prompt choisi ; aperçu du corps à droite.
5. Si le prompt a des variables manuelles → mini-formulaire (les variables
automatiques — sélection, presse-papiers — sont déjà capturées, §10.3).
6. VariableEngine produit le texte final (corps + préambule du profil actif).
7. Le Picker se ferme, le focus revient sur X, Injector colle le texte.
8. UsageStats enregistre l'usage (id, horodatage) — jamais le contenu résolu (§18).
Étape critique : 2 → 7, la capture et la restitution du focus. Si le focus ne revient pas exactement dans le champ d'origine, l'injection part dans le vide. Le module Injector (§11) est donc isolé, testé à part, et toutes les surfaces passent par lui — aucun Send dispersé dans les GUI.
6.3 Démarrage et cycle de vie
- Lancement (manuel ou démarrage Windows) → chargement des paramètres → scan de la bibliothèque → construction/vérification du cache d'index → enregistrement des raccourcis globaux et hotstrings → icône tray → attente.
- Un surveillant de dossier (sondage léger toutes les 5 s sur les dates de modification, ou
WM_DEVICECHANGE-like par minuteur) détecte les.mdajoutés/modifiés/supprimés hors de l'application (édition dans VS Code,git pull…) et rafraîchit l'index sans redémarrage. - Arrêt propre par le menu tray : libération des raccourcis, vidage du cache vers le disque, restauration du presse-papiers si une restauration était en attente.
7. Modèle de données : un prompt = un fichier Markdown
7.1 Arborescence de la bibliothèque
Bibliothèque\
├─ _packs\ ← packs importés, non édités directement (optionnel)
├─ Code\
│ ├─ revue-de-code.md
│ └─ expliquer-une-erreur.md
├─ Écriture\
│ ├─ reformuler.md
│ └─ resumer-en-5-points.md
├─ Général\
│ └─ expliquer-simplement.md
└─ Sans catégorie\ ← dossier réel ou implicite (fichiers à la racine)
La catégorie = le dossier de premier niveau. Choix délibéré : la structure est visible et manipulable dans l'Explorateur Windows, aucun champ à maintenir en double. Sous-dossiers au-delà du premier niveau : ignorés en v1 (organisation plate par étiquettes pour le reste). Renommer un dossier = renommer la catégorie, détecté par le surveillant (§6.3).
7.2 L'en-tête du fichier (métadonnées)
---
id: 7f3a2c1e-… # GUID stable, généré à la création, ne change jamais
title: Résumer en 5 points
tags: [résumé, synthèse, court]
targets: [défaut, claude, qwen] # profils de destination conseillés (§12)
favorite: true
pinned: 2 # rang dans les raccourcis directs (0 = non épinglé)
hotkey: ^!r # raccourci propre (syntaxe AHK), optionnel
hotstring: resu; # abréviation ::resu; , optionnelle
profile: défaut # profil appliqué si targets ne tranche pas
send_after: false # surcharge du profil (§12.3)
sensitive: false # si true : presse-papiers vidé après injection (§18, point 6)
created: 2026-10-11
updated: 2026-10-11
variables:
- name: ton
label: Ton de la réponse
type: enum
choices: [neutre, formel, amical, direct]
default: neutre
- name: longueur
label: Longueur max
type: enum
choices: ["5 points", "1 paragraphe", "détaillé"]
default: "5 points"
---
Résume le texte suivant en {{longueur}}, ton {{ton}}.
Réponds en français, sans reformuler la première phrase.
Texte :
{{selection}}
Le corps commence après le second ---. Tout ce qui suit est le prompt, verbatim, y compris ses propres --- éventuels (le parseur ne coupe qu'aux deux premiers délimiteurs).
7.3 Le sous-ensemble d'en-tête accepté (contrat strict)
AHK n'a pas de parseur YAML : PromptKey définit donc un sous-ensemble ligne par ligne, documenté ici comme contrat — tout le reste est une erreur de fichier signalée, jamais devinée :
- Clés scalaires :
clé: valeur(chaîne,true/false, nombre, dateAAAA-MM-JJ). - Listes en ligne :
[a, b, c]— virgules, éléments éventuellement entre guillemets doubles. - Bloc
variables:: liste d'objets indentés de 2 espaces, clés parminame, label, type, choices, default, required, multiline. - Commentaires
#en fin de ligne, lignes vides ignorées. - Interdits (erreur explicite avec n° de ligne) : ancres YAML, listes multi-lignes hors
variables, tableaux imbriqués, valeurs multi-lignes|.
Un fichier en erreur n'est jamais exclu silencieusement : il apparaît dans le Gestionnaire sous « Fichiers en erreur » avec le message et la ligne, et double-cliquer l'ouvre dans l'éditeur de texte par défaut. Un prompt sans en-tête du tout est accepté : titre = nom du fichier, corps = tout le fichier (import de notes existantes sans friction).
7.4 Identité et renommage
L'id (GUID dans l'en-tête) est l'identité ; le nom de fichier est libre (renommer le fichier ne casse ni les statistiques ni les raccourcis). L'historique et les compteurs (§15) sont indexés par id. À la première lecture d'un fichier sans id, PromptKey le génère et réécrit l'en-tête (avec sauvegarde .bak unique).
7.5 Champs calculés (jamais stockés dans le fichier)
usage_count, last_used, score de récence : dérivés de usage.json (§15), pas du fichier prompt — pour que versionner la bibliothèque sous Git ne produise pas un diff à chaque usage.
8. Le Quick Picker : la surface principale
Le Picker est l'écran que l'utilisateur verra 95 % du temps. Ses exigences sont des exigences de vitesse perçue :
| Exigence | Cible |
|---|---|
| Raccourci → fenêtre visible et focus prêt | < 150 ms (fenêtre pré-créée, masquée/montée) |
| Frappe → liste filtrée | < 50 ms par touche (recherche sur index en mémoire) |
| Ouverture → prompt collé (cas sans variable) | ≤ 4 frappes + Entrée, par défaut |
Abandon (Échap) |
Focus rendu à l'application d'origine, zéro effet de bord |
8.1 Composition (voir maquette §20.1)
- Champ de recherche (focus initial, texte sélectionné au retour).
- Liste de résultats : titre, catégorie, étiquettes, marqueurs (★ favori, 📌 épinglé, raccourci propre). Tri par défaut : épinglés → favoris → fréquents récents → pertinence de recherche.
- Panneau d'aperçu : corps du prompt avec les variables surlignées, et — si une sélection a été capturée — son début, tronqué proprement.
- Barre de statut : profil de destination actif, méthode d'injection qui sera utilisée, nombre de résultats.
8.2 Interactions clavier (contrat)
| Touche | Effet |
|---|---|
↑ / ↓, Ctrl+N / Ctrl+P |
Naviguer |
Entrée |
Utiliser le prompt (formulaire de variables si requis, sinon injection directe) |
Ctrl+Entrée |
Utiliser sans formulaire : valeurs par défaut pour toutes les variables |
Ctrl+C (sur un résultat) |
Copier le prompt résolu dans le presse-papiers, sans injecter |
Ctrl+E |
Ouvrir le prompt dans l'Éditeur |
Alt+1…9 |
Basculer le profil de destination pour cette injection seulement |
Échap |
Fermer, rendre le focus, ne rien faire d'autre |
| Frappe directe | Filtrer (la recherche est toujours active, pas de mode séparé) |
8.3 Listes par défaut (recherche vide)
À l'ouverture sans frappe : Épinglés, puis Récents (7 derniers jours, dédupliqués), puis Fréquents. C'est ce qui rend l'outil rapide pour les 5 prompts du quotidien : la plupart des usages ne nécessitent aucune recherche.
9. Le Gestionnaire et l'Éditeur
9.1 Gestionnaire (fenêtre principale, §20.2)
Ouvert par le menu tray, par Ctrl+Alt+M ou depuis le Picker (Ctrl+E sur la bibliothèque). Trois volets :
- Arbre : catégories (dossiers), Favoris, Récents, Épinglés, Fichiers en erreur — avec compteurs.
- Liste : prompts de la sélection, triables (titre, modifié, usage), recherche locale.
- Détail / aperçu : métadonnées et corps, boutons Utiliser / Modifier / Dupliquer / Exporter / Supprimer.
Actions de masse : déplacer vers une catégorie (glisser-déposer ou menu), ajouter/retirer une étiquette, exporter la sélection. Suppression = corbeille Windows (pas de suppression définitive directe) — un prompt est un texte précieux, souvent le fruit d'itérations.
Création express, trois chemins :
- Nouveau (formulaire vide + modèle de corps commenté) ;
- Depuis la sélection : le texte sélectionné dans l'application courante devient le corps (déjà vu en U6) ;
- Depuis le presse-papiers : idem, contenu courant du presse-papiers.
9.2 Éditeur (§20.3)
Éditeur intégré volontairement simple — champ texte multiligne à tabulations conservées, panneau de métadonnées à droite (titre, catégorie, étiquettes, profils, favori/épinglé, raccourci, hotstring), et trois aides qui le distinguent d'un bloc-notes :
- Insertion de variable (
Ctrl+Jou bouton) : insère{{nom}}et, si la variable n'existe pas encore dans l'en-tête, propose de la déclarer (type, libellé, défaut) — la déclaration et l'usage restent synchronisés. - Validation en direct : variables utilisées non déclarées, variables déclarées inutilisées, en-tête en erreur (ligne fautive), raccourci en conflit — affichés sous l'éditeur, sauvegarde bloquée seulement pour les erreurs d'en-tête, jamais pour les avertissements.
- Tester (
Ctrl+T) : ouvre le formulaire de variables puis montre le prompt résolu final (avec profil) dans une fenêtre de prévisualisation, sans rien injecter.
Enregistrer écrit le fichier en UTF-8 explicite (jamais l'encodage ANSI par défaut d'AHK, voir le piège détaillé en §19.4) et rafraîchit l'index immédiatement.
9.3 Ce que l'Éditeur n'essaie pas d'être
Pas de coloration syntaxique avancée, pas de markdown riche : pour l'édition lourde, le bouton « Ouvrir dans l'éditeur externe » (paramétrable : VS Code, Notepad++, Obsidian…) ouvre le .md, et le surveillant de dossier répercute les changements au retour.
10. Le moteur de variables
10.1 Syntaxe
{{nom}} dans le corps. Noms : [a-z0-9_]+, insensibles à la casse à la résolution. Aucune logique (pas de conditions, pas de boucles) en v1 : ce sont des emplacements à remplir, pas un langage de gabarit — la complexité est renvoyée au prompt lui-même, qui est fait pour une IA.
10.2 Types de variables déclarées
| Type | Contrôle du formulaire | Exemple |
|---|---|---|
text |
Champ ligne | {{sujet}} |
multiline |
Champ multiligne | {{contexte}} |
enum |
Liste déroulante (choices obligatoire) |
{{ton}} |
number |
Champ + validation numérique | {{nb_points}} |
date |
Sélecteur de date, rendu AAAA-MM-JJ ou format du default |
{{echeance}} |
bool |
Case à cocher, rend default si coché / texte alternatif choices: [oui, non] |
{{avec_exemples}} |
password |
Champ masqué, jamais persisté ni journalisé | jeton ponctuel |
Variable utilisée mais non déclarée : traitée comme text avec libellé = nom, demandée au formulaire (aucun blocage — un prompt copié-collé depuis le web doit fonctionner tel quel).
10.3 Variables automatiques (jamais demandées)
| Variable | Source | Précision |
|---|---|---|
{{selection}} |
Texte sélectionné dans l'application d'origine, capturé à l'invocation (§11.2) | Chaîne vide si rien n'est sélectionné ; le formulaire le signale |
{{clipboard}} |
Contenu texte du presse-papiers avant toute manipulation | Capturé avant que l'Injector ne touche au presse-papiers |
{{date}} / {{datetime}} / {{time}} |
Horloge locale | Formats AAAA-MM-JJ, AAAA-MM-JJ HH:mm, HH:mm |
{{app}} |
Nom du processus / titre de la fenêtre d'origine | Utile pour « je suis dans {{app}}… » |
{{cursor}} |
Marqueur de position : après injection, le curseur est replacé ici et le marqueur est retiré du texte | Pour les prompts-gabarits à compléter à la main |
Règle de capture : les variables automatiques sont figées au moment de l'invocation (raccourci/hotstring), pas à la validation du formulaire — sinon la sélection d'origine serait perdue dès que le Picker prend le focus.
10.4 Le formulaire de variables (§20.4)
- Un contrôle par variable manuelle, dans l'ordre de déclaration ; valeurs par défaut pré-remplies ;
Tabnavigue,Entrée(hors champ multiligne) valide tout,Échapannule toute l'injection. - Les
requiredvides bloquent la validation avec surlignage, jamais avec une boîte de dialogue. - Les choix faits sont mémorisés par prompt (
usage.json, §15) comme nouveaux défauts proposés — un prompt « revue de code » retient que le langage habituel est Python. Lespasswordsont exclus de cette mémorisation, sans exception.
10.5 Ordre de résolution
corps du fichier
→ substitution des automatiques (capturées à l'invocation)
→ substitution des manuelles (formulaire ou défauts, Ctrl+Entrée)
→ résolution de {{cursor}} (position mémorisée, marqueur retiré)
→ préambule + séparateur + postambule du profil actif (§12.2)
→ texte final remis à l'Injector
Aucune variable inconnue ne subsiste silencieusement : un {{…}} non résolu après ces étapes (ex. faute de frappe dans une automatique) est laissé tel quel et signalé dans la prévisualisation du formulaire ; en injection directe sans formulaire, un bip discret + infobulle tray « variable non résolue : X » après collage. Mieux vaut un défaut visible qu'un texte silencieusement faux.
11. Le moteur d'injection : livrer le prompt à l'IA
C'est le module le plus délicat du système. Il concentre toutes les interactions avec le focus, le presse-papiers et la frappe simulée.
11.1 Interface
Injector.Deliver(texte, options) → résultat {ok, méthode, erreur?}
options : { hwndCible, profil, méthode: auto|clipboard|sendtext,
sendAfter: bool, restaurerPressePapiers: bool }
Aucun autre module n'appelle Send, A_Clipboard ou ControlFocus directement (règle vérifiable par recherche dans le code, §22).
11.2 Capture du contexte d'invocation
À chaque invocation (raccourci global, hotstring exclue) :
hwndet titre de la fenêtre active, nom du processus.- Tentative de capture de la sélection : sauvegarde du presse-papiers →
Ctrl+Csimulé →ClipWaitcourt (250 ms) → lecture → restauration immédiate du presse-papiers. Si le presse-papiers n'a pas changé ou ne contient pas de texte, sélection = vide. Cette capture est best-effort : son échec ne bloque jamais l'ouverture du Picker. - Ces données vivent dans un objet
InvocationContexttransmis au Picker, au formulaire puis à l'Injector.
11.3 Méthode « presse-papiers » (défaut)
1. Sauvegarder le presse-papiers complet (tous formats, via ClipboardAll).
2. Poser le texte final dans le presse-papiers (format texte Unicode).
3. Rendre le focus à hwndCible (WinActivate + attente active ≤ 500 ms).
4. Send "^v" ; attendre le délai de collage (par défaut 150 ms).
5. Planifier la restauration à +1,5 s (paramétrable) :
- si le presse-papiers contient encore EXACTEMENT le texte injecté → restaurer la sauvegarde ;
- sinon (l'utilisateur a copié autre chose) → abandonner la restauration sans rien écraser.
6. Si sendAfter (profil) : attendre 800 ms annulables, puis Send "{Enter}".
L'étape 5 est la différence entre un outil propre et un outil qui « mange » le presse-papiers de l'utilisateur : elle est obligatoire, pas optionnelle.
11.4 Méthode « frappe simulée » (SendText)
Utilisée quand : le profil de l'application la demande, le collage a échoué (détection best-effort), ou l'utilisateur la choisit pour cette fois (Ctrl+Alt+V dans le Picker bascule la méthode). SendText plutôt que Send : pas d'interprétation des caractères spéciaux (+^!#{}), indispensable pour du texte de prompt arbitraire. Vitesse plafonnée et documentée : au-delà de ~4 000 caractères, un avertissement propose de repasser en presse-papiers.
11.5 Échecs et cas limites traités explicitement
| Cas | Comportement |
|---|---|
| Fenêtre d'origine fermée entre-temps | Injection annulée, texte final copié dans le presse-papiers + infobulle « fenêtre disparue — prompt copié » |
| Application cible élevée (admin), PromptKey non élevé | Message clair nommant l'application et l'option (relancer PromptKey en admin, ou copier plutôt qu'injecter) — détecté par comparaison d'intégrité du processus cible quand c'est possible, sinon par échec de WinActivate |
| Le champ cible n'accepte pas le collage (détecté : presse-papiers revenu inchangé n'est pas un signal fiable → pas de détection prétendue) | Aucune fausse promesse : le repli est un choix de profil par application (§12), pas une détection magique |
Échap pendant le compte à rebours d'envoi |
Envoi annulé, texte laissé en place |
| Texte final vide (prompt vide) | Refus avec message, aucune injection |
| PromptKey invoqué alors qu'il est déjà ouvert | Le Picker reprend le focus (instance unique) ; jamais deux fenêtres |
11.6 Journalisation
promptkey.log (rotation, 1 Mo) : horodatage, action, id du prompt, méthode, durée, erreur éventuelle. Jamais le contenu des prompts, des variables ou de la sélection (§18).
12. Profils de destination (les « IA cibles »)
12.1 Principe
Un profil décrit comment adapter la livraison à une destination, pas un autre prompt. La bibliothèque reste unique ; les profils évitent les doublons « Résumer (pour Claude) », « Résumer (pour Qwen) »…
12.2 Contenu d'un profil
; config.ini — section [Profil.claude]
Nom=Claude
Preambule=Réponds en français, en Markdown, sans préambule de politesse.\n---
Postambule=
Methode=clipboard
SendAfter=false
DelaiCollageMs=250
AppMatch=chrome.exe, msedge.exe ; indices d'auto-détection (optionnel)
TitreMatch=Claude ; expression dans le titre de fenêtre
- Préambule / postambule : texte ajouté avant/après le corps résolu (avec
\ninterprétés). C'est l'endroit des consignes transversales : langue, format, concision. - Méthode, délais : surcharge de l'injection pour cette destination.
SendAfter: voir §12.3.- Profils livrés :
défaut(neutre),claude,chatgpt,gemini,qwen,deepseek,hermes-terminal,courriel— tous modifiables, liste ouverte. - Un profil peut aussi être générique par type de champ :
terminal(pas de Markdown, lignes courtes),texte-brut.
12.3 Sélection du profil
Dans l'ordre : (1) choix manuel dans le Picker (Alt+n°, mémorisé pour la session) ; (2) targets/profile du prompt (§7.2) ; (3) auto-détection par AppMatch + TitreMatch de la fenêtre d'origine ; (4) profil défaut. Le profil actif est toujours visible dans la barre de statut du Picker — jamais d'adaptation invisible.
12.4 SendAfter : garde-fous
Désactivé dans tous les profils livrés. Activation = case explicite dans les Paramètres par profil. Quand il est actif : compte à rebours visible dans une mini-fenêtre non bloquante (800 ms par défaut, paramétrable jusqu'à 3 s), Échap annule, et la première activation déclenche un avertissement unique rappelant le risque d'envoi au mauvais fil de discussion.
13. Raccourcis globaux et hotstrings
13.1 Raccourcis par défaut
| Raccourci | Action | Remarque |
|---|---|---|
Ctrl+Alt+Espace |
Ouvrir le Quick Picker | Le raccourci. Espace évite la plupart des conflits applicatifs |
Ctrl+Alt+M |
Ouvrir le Gestionnaire | M = manager |
Ctrl+Alt+N |
Nouveau prompt (depuis la sélection si elle existe) | |
Ctrl+Alt+1…9 |
Injecter l'épinglé n° 1…9 | pinned: de l'en-tête (§7.2) |
Ctrl+Alt+V |
Injecter le dernier prompt utilisé, à nouveau | Rejoue avec un contexte frais (nouvelle sélection capturée) |
| (par prompt) | Raccourci propre (hotkey:) |
Priorité aux conflits signalés (§13.3) |
Tous reassignables dans les Paramètres ; la modification ré-enregistre à chaud, sans redémarrage.
13.2 Hotstrings
Déclarée par hotstring: resu; → l'abréviation ::resu; est active partout. Convention recommandée : terminer par ; (ou un autre signe distinctif) pour éviter les déclenchements en pleine frappe normale — le document de l'utilisateur final le dira, et le modèle de création propose ce suffixe par défaut.
Différences assumées vs raccourcis : pas de capture de contexte riche (la sélection environnante n'est pas récupérable au milieu d'une frappe) — les variables automatiques disponibles sont {{clipboard}}, {{date}}… mais pas {{selection}} ; si le prompt en contient une, elle est résolue comme vide et l'utilisateur est averti une fois par session. Les variables manuelles d'un prompt déclenché par hotstring ouvrent le même formulaire, puis l'injection se fait à l'endroit du curseur.
Attention documentée : une hotstring se déclenche aussi dans les mots de passe et les terminaux ; la liste des hotstrings est visible d'un coup d'œil dans le Gestionnaire (filtre dédié) et chacune peut être désactivée sans supprimer le prompt.
13.3 Conflits
À l'enregistrement (démarrage, modification, création), tout échec de Hotkey()/Hotstring() est consigné et présenté dans Paramètres → Raccourcis en conflit, avec le prompt/raccourci concerné et trois issues : réassigner, désactiver, ignorer (consigné). Aucun conflit silencieux : un raccourci qui ne répond pas sans explication détruit la confiance dans l'outil.
14. Recherche : index en mémoire et classement flou
14.1 Champs indexés
Par prompt : title, tags, catégorie, corps (tronqué aux 2 000 premiers caractères pour l'index), id. Normalisation : minuscules, suppression des accents (é→e) des deux côtés (requête et index) — « resu » doit trouver « Résumer ».
14.2 Construction et cache
Scan des .md → pour chacun : mtime + taille comparés à index-cache.json ; seuls les fichiers changés sont re-parsés. Démarrage cible : < 300 ms pour 1 000 prompts, cache chaud < 80 ms. Le cache est un détail d'optimisation jetable : le supprimer ne perd rien.
14.3 Classement (détail en Annexe B)
Score = pertinence textuelle (sous-séquence floue, bonus préfixe/mots entiers/titre) × pondérations d'usage (épinglé, favori, fréquence, récence). La recherche vide n'utilise que les pondérations (§8.3). L'algorithme tient en une fonction pure, testable unitairement avec des jeux fixes (§22) — le classement ne doit jamais devenir une boîte noire capricieuse entre deux versions.
15. Historique, favoris et statistiques d'usage
usage.json (à côté de la bibliothèque, exclu de la synchro Git recommandée — §17.3) :
{
"7f3a2c1e-…": {
"count": 42, "last_used": "2026-10-11T09:32:11",
"last_values": { "ton": "direct", "langage": "Python" }
}
}
count/last_used: alimentent le classement (§14.3) et le tri du Gestionnaire.last_values: derniers choix du formulaire → nouveaux défauts proposés (§10.4). Jamais depassword, jamais{{selection}}/{{clipboard}}(ce sont des contextes, pas des préférences).- Favoris et épinglés vivent dans l'en-tête du prompt (ils font partie de sa définition partageable), les statistiques dans
usage.json(elles sont personnelles et volatiles). Cette séparation est intentionnelle et cohérente avec D2/§7.5. - « Réinitialiser les statistiques » dans les Paramètres ; historique détaillé (liste des usages horodatés) non conservé : seuls les compteurs servent le classement, le reste serait de la surveillance de soi sans bénéfice.
16. Import, export et packs de prompts
| Opération | Format | Comportement |
|---|---|---|
| Export d'une sélection / catégorie | .zip de .md (+ pack.json de manifeste) |
Les fichiers restent de simples .md : le zip n'est qu'un transport |
| Export « texte brut » | Un .md unique découpé par ## Titre |
Pour partager dans un courriel ou une note ; réimportable |
| Import | .md, dossier de .md, .zip, .json (schéma §16.1) |
Prévisualisation : nouveaux / doublons (même id) / conflits (même titre, autre id) — choix par ligne : importer, remplacer, dupliquer, ignorer |
| Import du presse-papiers | Texte quelconque | Crée un prompt dont le corps est le contenu, titre à saisir |
| Pack de démarrage | Dossier _packs\essentiels\ |
Livré avec l'application (Annexe D), installable/ignoré au premier lancement |
16.1 Schéma JSON d'échange (pour l'interopérabilité)
{ "promptkey_export": 1,
"prompts": [ { "title": "…", "category": "Code", "tags": ["…"],
"body": "… {{selection}} …", "variables": [ { "name": "ton", "type": "enum", "choices": ["…"] } ] } ] }
L'import JSON génère des fichiers .md conformes à §7 (D2 reste la loi : aucun prompt ne vit durablement en JSON).
17. Paramètres, portabilité et synchronisation
17.1 config.ini (à côté de l'exécutable ou de la bibliothèque, mode portable)
Sections : [General] (dossier bibliothèque, langue d'interface du Picker — FR par défaut, thème, démarrage Windows), [Injection] (méthode par défaut, délais, restauration), [Raccourcis], [Editeur] (éditeur externe), [Profil.*] (§12.2). INI plutôt que JSON pour les paramètres : éditable à la main sans casse, natif en AHK (IniRead/IniWrite).
17.2 Mode portable intégral
Si PromptKey.exe trouve un dossier Bibliothèque\ à côté de lui, il l'utilise et écrit tout (config, cache, stats) dans son propre dossier : la totalité de l'outil — programme + prompts + réglages — tient sur une clé USB ou dans un dossier synchronisé. Sinon, défaut : %USERPROFILE%\Documents\PromptKey\.
17.3 Synchronisation (par le dossier, jamais par le code)
- Git/Gitea (recommandé pour Bruno) : la bibliothèque est un dépôt ;
usage.jsonetindex-cache.jsondans.gitignore. Historique, retour arrière, partage entre postes. - OneDrive / dossier partagé : fonctionne tel quel ; le surveillant de dossier (§6.3) absorbe les arrivées de fichiers.
- Conflits : PromptKey ne fusionne rien. Un fichier modifié des deux côtés relève de Git ou de l'Explorateur ; l'application relit ce qui est sur disque, point. Ce non-objectif est écrit ici pour ne jamais être « ajouté vite fait » plus tard.
18. Sécurité et vie privée
- Zéro réseau (D7) : vérifiable — le code ne contient aucun
WinHttp,curlou socket. C'est aussi l'argument antivirus. - Aucun contenu journalisé : ni prompts résolus, ni sélections, ni valeurs de variables dans
promptkey.log(§11.6). - Variables
password: masquées, non persistées (§10.4), exclues delast_values, et le texte final qui les contient n'est jamais mis dans le presse-papiers plus longtemps que le délai d'injection — préférerSendTextpour ces prompts (réglage automatique proposé à la déclaration d'une telle variable). - Secrets dans les prompts eux-mêmes : déconseillés par conception (fichiers en clair, versionnés). La documentation utilisateur le dira en première page ; un avertissement de l'Éditeur signale les motifs évidents (
sk-…,api_key=,Bearer …) — avertissement, pas censure. - Injection ≠ exécution : PromptKey colle du texte. Si le texte collé dans un terminal est une commande, c'est l'affaire de l'utilisateur — d'où D5 (pas d'envoi automatique par défaut), particulièrement sensible pour le profil
terminal. - Presse-papiers restauré (§11.3) : ne pas laisser le dernier prompt — possiblement sensible — traîner dans l'historique du presse-papiers Windows (
Win+V) plus que nécessaire. Limite honnête : Windows peut avoir déjà archivé la valeur ; le paramètre « ne pas restaurer mais vider après injection » est offert pour les prompts marquéssensitive: truedans l'en-tête (champ ajouté au contrat §7.2).
19. Architecture du code AutoHotkey v2
19.1 Arborescence du projet source
PromptKey\
├─ PromptKey.ahk ← point d'entrée, #Include, bootstrap, tray
├─ lib\
│ ├─ Settings.ahk ← config.ini (lecture/écriture, défauts)
│ ├─ PromptStore.ahk ← scan dossier, parse/write des .md (§7)
│ ├─ Frontmatter.ahk ← parseur du sous-ensemble §7.3 (+ tests)
│ ├─ Index.ahk ← index mémoire, cache, recherche floue (§14)
│ ├─ VariableEngine.ahk ← résolution §10.5, captures automatiques
│ ├─ ClipboardGuard.ahk ← sauvegarde/restauration sûre (§11.3)
│ ├─ Injector.ahk ← SEUL module autorisé à Send / coller (§11.1)
│ ├─ HotkeyManager.ahk ← enregistrement, conflits (§13)
│ ├─ UsageStats.ahk ← usage.json (§15)
│ └─ Util.ahk ← dates, normalisation accents, GUID, log
├─ gui\
│ ├─ Picker.ahk ← §8 / §20.1
│ ├─ Manager.ahk ← §9.1 / §20.2
│ ├─ Editor.ahk ← §9.2 / §20.3
│ ├─ VarForm.ahk ← §10.4 / §20.4
│ └─ SettingsGui.ahk ← paramètres, conflits, profils
├─ assets\ (icônes .ico : clair/sombre, épinglé…)
├─ packs\essentiels\ ← Annexe D
├─ tests\ ← §22 (scripts AHK autonomes, sortie console)
├─ build.ahk / build.ps1 ← compilation Ahk2Exe + zip de distribution
└─ README.md
19.2 Principes de code
- Une classe par module, état passé explicitement ; pas de variables globales hors
SettingsetApp(contexte courant). - Les GUI ne touchent ni au disque ni au presse-papiers : elles appellent les services. L'
Injectorne connaît pas les GUI : il reçoit un texte et des options. - Erreurs : les modules lèvent/retournent des résultats typés
{ok, erreur}; les messages utilisateur sont en français, centralisés dansUtil.Msg*pour une éventuelle traduction. - Aucune dépendance externe en v1 (pas de DLL, pas de librairie tierce) : le
.ahkdoit tourner sur une installation AHK v2 propre.
19.3 Concurrence et minuteries
Processus à un fil : tout est événementiel (raccourcis, minuteries AHK). Le scan initial de grosses bibliothèques est le seul travail long : chargement par lots avec SetTimer pour ne pas geler l'icône tray, barre de progression discrète dans le Gestionnaire si > 1 000 fichiers. Aucun travail de fond pendant qu'un Picker est ouvert (le surveillant est suspendu, repris à la fermeture).
19.4 Encodage — le piège n° 1 en AHK
Règle unique : les fichiers prompts sont lus et écrits en UTF-8 explicite (FileEncoding positionné et restauré, ou FileOpen avec encodage nommé), jamais dans l'encodage ANSI par défaut. Les prompts contiennent des accents, des « — », des émojis : un seul aller-retour ANSI les détruit. Tests dédiés (§22) : aller-retour d'un corps contenant é à — ‘’ « » 😀 et {{variables}} doit être bit à bit identique. Les fins de ligne sont normalisées en CRLF à l'écriture sous Windows, tolérées en LF à la lecture.
19.5 Fenêtres et DPI
Gui créés avec prise en charge DPI (-DPIScale évité, dimensions en unités relatives, polices Segoe UI 10/11). Picker : largeur fixe confortable (~720 px à 100 %), centrée sur l'écran de la fenêtre d'origine (pas forcément l'écran principal). Le retour de focus (§6.2) cible le hwnd capturé, jamais « la fenêtre sous la souris ».
20. Maquettes des écrans (ASCII)
20.1 Quick Picker
┌─ PromptKey ──────────────────────────────────────────── [profil: Claude ▾] ─┐
│ Rechercher : résu█ │
├──────────────────────────────────┬──────────────────────────────────────────┤
│ ★ Résumer en 5 points [Général]│ Résume le texte suivant en {{longueur}}, │
│ 📌 Revue de code [Code] │ ton {{ton}}. Réponds en français… │
│ Résumer un courriel [Écrit.]│ │
│ Résumé exécutif (1 page)[Gén.] │ Texte : │
│ │ {{selection}} │
│ │ │
│ │ Sélection capturée : « Le rapport du │
│ │ troisième trimestre montre… » (1 240 c.) │
├──────────────────────────────────┴──────────────────────────────────────────┤
│ Entrée Utiliser · Ctrl+Entrée Défauts · Ctrl+E Modifier · 12 résultats │
│ Méthode : presse-papiers · Envoi auto : non │
└─────────────────────────────────────────────────────────────────────────────┘
20.2 Gestionnaire
┌─ PromptKey — Gestionnaire ──────────────────────────────────────────────────┐
│ Fichier Prompt Outils Rechercher : [____________] │
├───────────────┬──────────────────────────────────┬──────────────────────────┤
│ ▾ Bibliothèque│ Titre Modifié Usage│ Résumer en 5 points │
│ Code (4)│ ★ Résumer 5 points 10-09 42 │ Catégorie : Général │
│ Écriture (6)│ 📌 Revue de code 10-10 31 │ Étiquettes : résumé, … │
│ Général (9)│ Traduire FR→EN 09-28 18 │ Raccourci : — Hotstring │
│ ★ Favoris (5)│ Expliquer erreur 10-11 3 │ : resu; │
│ ◷ Récents │ │ │
│ 📌 Épinglés(3)│ │ [Utiliser] [Modifier] │
│ ⚠ En erreur(1)│ │ [Dupliquer] [Exporter] │
│ │ │ [Supprimer] │
├───────────────┴──────────────────────────────────┴──────────────────────────┤
│ [+ Nouveau] [Depuis sélection] [Importer] 20 prompts · index à jour │
└─────────────────────────────────────────────────────────────────────────────┘
20.3 Éditeur
┌─ Modifier — Revue de code ───────────────────────┬─ Métadonnées ────────────┐
│ Tu es un relecteur de code senior. │ Titre : Revue de code │
│ │ Catégorie : [Code ▾] │
│ Relis le {{langage}} suivant (niveau {{niveau}}) │ Étiquettes : code, revue │
│ et signale : │ ★ Favori 📌 Épinglé n°2 │
│ 1. les bogues probables… │ Raccourci : [Ctrl+Alt+R] │
│ │ Hotstring : [revue; ] │
│ Code : │ Profils : [claude, qwen] │
│ {{selection}} │ │
│ │ Variables déclarées : │
│ │ • langage (enum) │
│ │ • niveau (enum) │
│ [Insérer variable Ctrl+J] │ [+ Déclarer] │
├──────────────────────────────────────────────────┴──────────────────────────┤
│ ⚠ « niveau » utilisé mais non déclaré — [Déclarer] [Tester Ctrl+T] │
│ [Ouvrir externe] [Annuler] [OK] │
└─────────────────────────────────────────────────────────────────────────────┘
20.4 Formulaire de variables
┌─ Revue de code — paramètres ──────────────┐
│ Langage : [Python ▾] │
│ Niveau : (•) Strict ( ) Rapide │
│ Contexte : [___________________________] │
│ [___________________________] │
│ │
│ Sélection incluse : 1 240 caractères ✓ │
│ [Échap Annuler] [Entrée OK] │
└───────────────────────────────────────────┘
21. Packaging, installation et mises à jour
21.1 Formes de distribution
- Source
.ahk(pour qui a AHK v2) — la forme de référence, lisible et auditable. PromptKey.execompilé par Ahk2Exe (base AHK v2 64 bits, icône intégrée) — pour l'usage quotidien.- Archive portable
.zip: exe +packs\+README+ bibliothèque d'exemple ; aucune installation, mode portable (§17.2) actif par la présence du dossierBibliothèque\.
Pas d'installeur en v1 : décompresser, lancer, éventuellement cocher « Démarrer avec Windows » (raccourci dans le dossier Démarrage, créé par l'application sur demande — pas d'écriture registre cachée).
21.2 Premier lancement
Assistant en trois écrans maximum : (1) choisir/créer le dossier de bibliothèque ; (2) proposer le pack de démarrage (Annexe D) — installé seulement sur accord ; (3) montrer LE raccourci, avec bouton « Tester maintenant » qui ouvre le Picker. Toute la valeur de l'outil tient à ce premier test réussi en moins d'une minute.
21.3 Compilation reproductible
build.ps1 : vérifie la version AHK, lance les tests (§22), compile, produit le zip et un SHA256. La recette est dans le README : n'importe qui peut recompiler et comparer — réponse directe au problème des faux positifs antivirus (§4.2).
21.4 Mises à jour
Manuelles en v1 (D7) : remplacer l'exe. Les formats de fichiers (.md, config.ini, usage.json) portent un numéro de version interne ; une migration de format, si un jour nécessaire, se fait à la lecture avec sauvegarde préalable, et est annoncée dans le journal.
22. Tests et critères de qualité
Pas de framework lourd : des scripts AHK autonomes dans tests\, exécutables en ligne de commande, sortie OK/ÉCHEC — lancés par build.ps1 avant toute compilation.
| Suite | Ce qui est vérifié |
|---|---|
Frontmatter |
Le contrat §7.3 : fichiers valides parsés au champ près ; chaque interdit produit l'erreur et la ligne attendues ; fichier sans en-tête accepté |
Encodage |
Aller-retour UTF-8 bit à bit (§19.4), fins de ligne LF/CRLF |
Variables |
Résolution §10.5, automatiques, {{cursor}}, inconnues signalées, password jamais dans last_values |
Recherche |
Jeux fixes titre/requête → ordre attendu (Annexe B), insensibilité aux accents |
Injection (manuel assisté) |
Script ouvrant le Bloc-notes : collage, restauration du presse-papiers, abandon si copie intermédiaire, SendText, retour de focus — à exécuter sur le poste réel, cases cochées dans le rapport de test |
Raccourcis |
Enregistrement des défauts sans conflit sur une machine propre ; rapport de conflit simulé |
Golden tasks (parcours complets, chronométrés à la main avant chaque version) :
- Démarrage froid → Picker → prompt sans variable collé dans le Bloc-notes : < 3 s, presse-papiers d'origine intact après coup.
- Prompt à 3 variables dont une
enum: formulaire → collage correct dans un navigateur (page de test locale). - Hotstring
resu;dans Word : remplacement + variables résolues. - Édition d'un
.mddans un éditeur externe pendant que PromptKey tourne : index à jour sans redémarrage. - Bibliothèque de 2 000 prompts générés : démarrage < 1 s cache chaud, frappe dans le Picker sans latence visible.
23. Plan d'implémentation en phases (tickets)
Convention : chaque ticket est livrable et testable seul ; les critères d'acceptation sont des comportements observables, pas des intentions. Estimation en demi-journées (dj) pour un développeur AHK v2 à l'aise — à titre d'ordre de grandeur.
Phase 0 — Socle et preuve du geste central (≈ 2 dj)
Objectif : prouver le risque n° 1 — capture du focus, collage propre, presse-papiers restauré — avant tout le reste.
| Ticket | Contenu | Acceptation |
|---|---|---|
| P0-1 | Squelette : PromptKey.ahk, tray, instance unique, Settings (INI) |
L'exe démarre, icône tray, quitter fonctionne, aucun résidu |
| P0-2 | ClipboardGuard + Injector (méthode presse-papiers seule) |
Golden task 1 réussie sur Bloc-notes et navigateur |
| P0-3 | Raccourci global + capture du contexte (hwnd, sélection best-effort, §11.2) | La sélection d'un paragraphe est récupérée 9 fois sur 10 dans Word/Chrome ; échec = sélection vide, jamais blocage |
| P0-4 | Picker minimal : liste fixe de 5 prompts codés en dur, recherche naïve, Entrée/Échap |
Le geste §1 complet fonctionne de bout en bout |
Phase 1 — Bibliothèque réelle (≈ 3 dj)
| Ticket | Contenu | Acceptation |
|---|---|---|
| P1-1 | Frontmatter : parseur du contrat §7.3 + écriture (aller-retour) |
Suite Frontmatter verte ; erreurs avec n° de ligne |
| P1-2 | PromptStore : scan, catégories-dossiers, génération d'id, surveillant de dossier |
§6.3 : un .md déposé à la main apparaît sans redémarrage |
| P1-3 | Index + cache + recherche floue (Annexe B) | Suite Recherche verte ; 1 000 prompts, < 50 ms/frappe |
| P1-4 | Picker complet (§8) : aperçu, tris par défaut, barre de statut | Golden tasks 1 et 5 |
| P1-5 | Gestionnaire (§9.1) : arbre, liste, détail, CRUD, corbeille | Créer → utiliser → modifier → supprimer sans quitter l'outil |
Phase 2 — Variables et profils (≈ 3 dj)
| Ticket | Contenu | Acceptation |
|---|---|---|
| P2-1 | VariableEngine : types §10.2, automatiques §10.3, {{cursor}}, ordre §10.5 |
Suite Variables verte |
| P2-2 | Formulaire de variables (§20.4) + mémorisation des derniers choix | Golden task 2 ; password absent de usage.json (vérifié) |
| P2-3 | Profils (§12) : préambule, méthode, sélection auto/manuelle, SendAfter gardé |
Même prompt, deux profils → deux textes finaux conformes en prévisualisation |
| P2-4 | Éditeur (§9.2) : métadonnées, insertion/déclaration de variables, validation, Tester | Un prompt créé de zéro dans l'Éditeur fonctionne au Picker sans retouche du fichier |
| P2-5 | Injection SendText + bascule par profil/par frappe |
Un champ où le collage échoue reçoit le prompt en frappe, texte exact |
Phase 3 — Raccourcis avancés, import/export (≈ 2 dj)
| Ticket | Contenu | Acceptation |
|---|---|---|
| P3-1 | HotkeyManager : raccourcis par prompt, épinglés 1…9, rapport de conflits (§13.3) |
Conflit provoqué → visible et explicable dans Paramètres |
| P3-2 | Hotstrings (§13.2) + filtre de gestion | Golden task 3 ; désactivation unitaire respectée |
| P3-3 | UsageStats complet : tris Fréquents/Récents, réinitialisation |
§8.3 vérifié après usages simulés |
| P3-4 | Import/export (§16) + pack de démarrage (Annexe D) + premier lancement (§21.2) | Export d'une catégorie réimporté sur une bibliothèque vierge = prompts identiques |
| P3-5 | Paramètres complets (§17.1), mode portable, démarrage Windows | Le zip portable fonctionne depuis un dossier neuf, sans trace ailleurs |
Phase 4 — Durcissement et distribution (≈ 2 dj)
| Ticket | Contenu | Acceptation |
|---|---|---|
| P4-1 | Suites de tests complètes (§22) intégrées à build.ps1 |
Build refusé si un test échoue |
| P4-2 | Compilation Ahk2Exe, zip portable, sommes SHA256, README utilisateur (français) | Une machine sans AHK utilise le zip de bout en bout |
| P4-3 | Cas limites §11.5 passés en revue un par un sur poste réel | Tableau §11.5 coché ligne par ligne |
| P4-4 | Prompts marqués sensitive : vidage du presse-papiers après injection (§18, point 6) |
Après injection d'un tel prompt, Win+V ne montre pas le texte injecté comme entrée PromptKey restaurée |
Phase 5 — Extensions optionnelles (hors v1, à décider séparément)
- P5-A — Pont API : profil spécial qui, au lieu d'injecter, envoie le prompt résolu à une API (OpenAI-compatible) et colle la réponse — change la nature de l'outil (réseau, clés, coûts) : décision explicite requise, contraire à D7.
- P5-B — Chaînes de prompts : un prompt dont une variable est la sortie d'un autre (composition), sans langage de gabarit complet.
- P5-C — Bibliothèque SQLite : si la bibliothèque dépasse ~5 000 prompts (D3 à réviser, D2 inchangé).
- P5-D — Snippets système : réponses types courriel/support gérées dans le même outil (mêmes mécanismes, autre bibliothèque).
24. Risques et mitigations
| Risque | Prob. | Mitigation (section) |
|---|---|---|
| Le retour de focus échoue dans certaines applications → texte perdu ou au mauvais endroit | Moyenne | Module isolé et testé (§11), fenêtre disparue = copie de secours, jamais d'envoi auto par défaut (D5) |
| Presse-papiers de l'utilisateur écrasé ou historique pollué | Moyenne | ClipboardGuard + restauration conditionnelle (§11.3), mode sensitive (§18, point 6) |
| Faux positifs antivirus sur l'exe compilé | Élevée | Source distribuée, build reproductible (§21.3), zéro réseau (D7) |
| Le sous-ensemble d'en-tête devient un faux YAML frustrant | Moyenne | Contrat écrit (§7.3), erreurs avec ligne, fichiers sans en-tête acceptés, Éditeur qui génère l'en-tête pour l'utilisateur |
| Conflits de raccourcis avec les applications du quotidien | Élevée | Défaut peu conflictuel (Ctrl+Alt+Espace), détection et rapport (§13.3) |
| L'utilisateur empile 300 prompts et ne retrouve rien | Moyenne | Classement par usage (§14.3), épinglés/favoris, Annexe D comme modèle de nommage |
| Verrouillage format : les prompts deviennent prisonniers de PromptKey | Faible | D2 : des .md lisibles restent exploitables même sans l'application — c'est un argument de conception, pas un risque résiduel |
25. Alternatives écartées
| Alternative | Pourquoi pas (pour ce besoin) |
|---|---|
| Espanso / Beeftext / PhraseExpress (extenseurs de texte) | Excellents pour des snippets figés ; pas de bibliothèque de prompts cherchable avec aperçu, profils par IA, ni formulaire de variables riche au centre du geste |
| PowerToys / lanceurs (Flow Launcher, Raycast-like) | Bons lanceurs, mais l'injection fine (capture de sélection, restauration du presse-papiers, profils) y serait un plugin à écrire quand même — AHK la donne nativement |
| Les bibliothèques intégrées des IA (prompts enregistrés ChatGPT/Claude…) | Enfermées par outil : le besoin est justement une bibliothèque pour toutes les IA (§2.1-4) |
| Gestionnaire de presse-papiers (Ditto…) | Retrouve des textes collés, ne gère ni variables, ni catégories, ni profils |
| Application Electron/web maison | Surdimensionné : installation, empreinte, et l'accès global au clavier/presse-papiers sous Windows y est plus indirect qu'en AHK |
| Simples hotstrings AHK sans application | Le point de départ de beaucoup d'usages réels — mais sans Picker ni gestion, la bibliothèque cesse d'être retrouvable dès ~20 prompts ; PromptKey les conserve comme un mode d'accès parmi d'autres (§13.2) |
26. Décisions ouvertes pour Bruno
Aucune ne bloque la Phase 0 ; Q2 et Q3 influencent la Phase 1.
- Q1 — Nom. « PromptKey » est un nom de travail. Alternatives : PromptDeck (écho à Flowdeck), Prompto, TouchePrompt… Le nom décide du dossier par défaut et de l'icône.
- Q2 — Bibliothèque initiale. Dossier neuf dédié, ou adosser la bibliothèque à un vault/dossier existant (les
.mdy côtoieraient d'autres notes — le parseur tolère les fichiers sans en-tête, mais le Gestionnaire ne montrera que le dossier choisi) ? - Q3 — Synchro entre postes. Git/Gitea dès le départ (recommandé, §17.3) ou dossier local simple en v1 ?
- Q4 — Langue d'interface. Français seulement en v1 (hypothèse de ce document) ou FR/EN dès le départ ? Le code centralise les messages (§19.2) pour garder la porte ouverte.
- Q5 —
SendAfter. Le conserver comme option gardée (§12.4), ou le retirer complètement de la v1 pour ne jamais risquer un envoi involontaire — quitte à le réintroduire plus tard ?
Annexe A — Exemple complet d'un fichier prompt
Fichier : Bibliothèque\Code\expliquer-une-erreur.md
---
id: 9d41b7aa-3c2f-4e01-9a55-1f0c2d77e810
title: Expliquer une erreur
tags: [débogage, erreur, pédagogie]
targets: [défaut, claude, qwen, deepseek]
favorite: false
created: 2026-10-11
updated: 2026-10-11
variables:
- name: niveau
label: Mon niveau sur ce sujet
type: enum
choices: [débutant, intermédiaire, avancé]
default: intermédiaire
---
Explique l'erreur ci-dessous à un niveau {{niveau}} :
1. ce qu'elle signifie, en une phrase simple ;
2. la cause la plus probable dans ce code ;
3. la correction minimale, avec le code corrigé seulement.
Message d'erreur et code :
{{selection}}
Utilisation type : copier un message d'erreur (ou le sélectionner dans l'IDE) → Ctrl+Alt+Espace → « erreur » → choisir le niveau → le prompt complet est collé dans l'IA ouverte.
Annexe B — Algorithme de classement de la recherche
Fonction pure Score(prompt, requêteNormalisée) :
- Correspondance floue : la requête (sans accents, minuscules) est cherchée en sous-séquence dans titre, puis étiquettes, puis catégorie, puis corps. Bonus : correspondance en début de mot (×2), mot entier (×3), dans le titre (×4).
- Requête multi-mots : chaque mot doit correspondre quelque part (ET logique) ; le score est la somme des mots.
- Pondérations multiplicatives : épinglé ×1,5 · favori ×1,3 · fréquence
1 + log10(1+count) × 0,2· récence : ×1,2 si utilisé < 7 jours. - Tri : score décroissant, égalité tranchée par
last_usedpuis titre alphabétique — déterminisme total, testable (§22).
Le but n'est pas la sophistication : c'est que les 5 prompts quotidiens remontent en ≤ 3 frappes, et que le comportement soit prévisible.
Annexe C — Séquence d'injection, pas à pas
Utilisateur Application X PromptKey Presse-papiers
│ │ │ │
│── Ctrl+Alt+Esp ────┼─────────────────▶│ capture hwnd, titre │
│ │ │ capture sélection ──────▶│ (sauvegarde,
│ │ │ │ Ctrl+C, lecture,
│ │ │◀───────────────────────│ restauration)
│ │ Picker ouvert │ │
│── frappe+Entrée ───┼─────────────────▶│ résolution variables │
│ │ │ texte final (profil) │
│ │ │ sauvegarde complète ──▶│
│ │ │ pose le texte ────────▶│
│ │◀─ WinActivate ───│ │
│ │◀─ Ctrl+V ────────│ │
│ │ (texte collé) │ minuterie +1,5 s │
│ │ │ si PP inchangé : ─────▶│ restauration
│ │ │ sinon : abandon propre │
Annexe D — Pack de démarrage proposé (20 prompts)
Livrés dans packs\essentiels\, chacun conforme à §7, avec variables déclarées — ils servent aussi d'exemples du format.
Général : Expliquer simplement · Expliquer une erreur (Annexe A) · Résumer en 5 points · Plan d'action à partir d'un texte · Questions de clarification avant de répondre.
Écriture : Reformuler (ton variable) · Corriger sans changer le style · Raccourcir de moitié · Courriel poli à partir de notes brutes · Traduire FR↔EN en gardant la mise en forme.
Code : Revue de code (niveau variable) · Écrire un test pour cette fonction · Expliquer ce code ligne par ligne · Convertir dans un autre langage · Message de commit à partir du diff ({{clipboard}}).
Analyse : Pour / contre structuré · Extraire les décisions et tâches d'un compte rendu · Comparer deux options selon mes critères ({{contexte}}) · Résumé exécutif d'une page · Transformer en tableau Markdown.
Fin du document — PromptKey, architecture et conception v1.0.