Benchtop

Transformez une idée vague de projet électronique ou d'impression 3D en un dossier complet et prêt à construire : concept, liste de pièces et prix en direct, circuit vérifié, PCB carrier, guide de soudure illustré à l'échelle, boîtier imprimable, firmware et page de présentation.

Qu'est-ce que Benchtop ?

Benchtop est un outil conçu pour les développeurs et les makers qui souhaitent concrétiser rapidement un projet d'électronique physique (ESP32, Arduino, Raspberry Pi Pico, capteurs, etc.) sans se noyer dans la documentation ou les erreurs manuelles. Il génère automatiquement l'ensemble des livrables depuis un unique fichier `project.json` : schémas de câblage, listes de pièces (BOM) avec prix actualisés, règles de vérification électrique, fichiers CAO pour boîtier 3D et PCB, échafaudage de firmware, et même une page de présentation web. Le système est conçu pour garantir la cohérence et la fiabilité : toute information (brochage, dimensions, connexions) provient d'une source unique, éliminant les erreurs de duplication. Benchtop s'exécute via des scripts TypeScript sous Bun et peut être utilisé de manière progressive (du concept à la mise en production) ou en démarrant à n'importe quelle phase du projet.

Compatible avec~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/filipjaj/benchtop/tree/HEAD/skills/benchtop

Installed? Explore more Développement et programmation skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

Demander à votre IA préférée

Ouvre une nouvelle conversation avec cette compétence d'agent déjà préchargée.

Documentation

Que fait Benchtop ?

Transforme « Je veux un truc qui… » en un dossier qu'une personne peut construire : un guide, une liste de pièces, un boîtier à imprimer, une carte à commander, un firmware à flasher et une page qui le présente.

L'idée unique

Tout est généré à partir d'un seul fichier, project.json, ainsi que des définitions de pièces dans assets/parts/. Vous écrivez et modifiez ce fichier ; les scripts en dérivent les dessins, les vérifications, le boîtier, la carte, les numéros de broches et la page.

C'est ce qui rend la sortie fiable. Un schéma de câblage que vous dessinez à la main et un tableau de brochage que vous tapez à la main finiront par se contredire tôt ou tard, et un débutant ne peut pas dire lequel est faux. Donc : ne dessinez jamais une illustration de câblage à la main, ne tapez jamais un numéro GPIO dans un firmware, ne citez jamais une dimension qui ne se trouve pas dans un fichier de pièce. Modifiez project.json (ou un fichier de pièce) et régénérez.

scripts/lib/types.ts est le schéma, avec un commentaire sur chaque champ. examples/luft/project.json est un fichier projet complet (pièces, connexions, boîtier, firmware et blocs de présentation) ; lisez-le avant d'écrire votre premier fichier. Il est livré avec son firmware dans examples/luft/firmware/ (la seule partie écrite à la main, et un modèle de ce à quoi main.cpp devrait ressembler) mais sans les autres sorties générées : exécutez les scripts sur une copie pour voir ce que chacun produit.

Configuration

Les scripts sont du TypeScript exécuté avec bun depuis le répertoire de cette compétence. Le cœur (vérifications, BOM, approvisionnement, guide, fiche concept, page de présentation, échafaudage du firmware) n'a pas de dépendances.

ÉtapeNécessiteSi manquant
Boîtier, PCBbun install --cwd scripts une fois (JSCAD, tscircuit, épinglés)Le script affiche la commande et quitte avec le code 3. Dites à l'utilisateur ce qui sera installé, puis exécutez-la.
Guide PDF, captures d'écranChrome, Chromium ou EdgeLe HTML fonctionne toujours ; l'utilisateur imprime au format PDF depuis un navigateur.
Compilation du firmwarePlatformIO (pio)L'échafaudage est toujours écrit ; indiquez qu'il n'est pas compilé.
Rendu 3DBlender dans le PATHrender.ts quitte avec le code 3 avec une ligne ; la page utilise le dessin au trait et la visionneuse 3D.

Travaillez dans un dossier de projet choisi par l'utilisateur (demandez une fois ; par défaut ./<slug>/). Toutes les commandes prennent ce dossier : bun <skill>/scripts/<name>.ts <projectDir>.

Le flux

Six phases. Chacune se termine par quelque chose que l'utilisateur peut regarder et une décision qui lui appartient. N'avancez pas à travers une décision : une mauvaise hypothèse à la phase 1 gaspille tout ce qui suit. Si l'utilisateur arrive à mi-parcours (« J'ai les pièces, il me faut un boîtier »), commencez à cette phase et construisez le project.json minimum dont elle a besoin.

1. Imaginer

Lisez references/imagine.md. Découvrez ce que la chose fait, pour qui, où elle vit, comment elle est alimentée et quelles sont les compétences et les outils de l'utilisateur. Proposez deux ou trois directions vraiment différentes, pas trois tailles du même boîtier. Une fois une direction choisie, écrivez un premier project.json (blocs pièces et boîtier, pas encore de connexions) et exécutez :

bun scripts/concept.ts <projectDir>      # out/concept.html : vue fermée, vue intérieure, taille, coût

Montrez à l'utilisateur la fiche concept (ouvrez-la, ou faites une capture d'écran avec shoot.ts). Décision : est-ce la bonne chose ? Itérez ici ; c'est l'endroit le moins coûteux pour changer d'avis.

2. Pièces et circuit

Lisez references/circuit.md. Choisissez des pièces dans assets/parts/ (listez le dossier ; chaque fichier a un blurb). Une pièce qui n'y est pas va dans <projectDir>/parts/. Le fait que ses positions de pastilles proviennent de quelque part décide si le guide et le boîtier peuvent être fiables, donc avant de taper une carte ou un module à la main, consultez le catalogue de pièces. Un instantané est livré avec la compétence ; il n'y a rien à configurer :

bun scripts/catalog.ts find "<modèle exact>"     # cette carte ou ce module est-il dans le catalogue ?
bun scripts/catalog.ts pads <part_id>           # contient-il les positions des pastilles du fichier CAO du fabricant ?
bun scripts/catalog.ts import-part <part_id> --id <id> --out <projectDir>/parts/<id>.json

Quand pads liste un jeu de données, import-part écrit le fichier de pièce provisoire : pastilles et contour du fichier du fabricant, broches de masse, et là où le catalogue les a, les numéros GPIO, le niveau logique, la hauteur et les ouvertures des connecteurs. Il imprime ce qu'il n'a pas pu déduire (broches d'alimentation, prix, souvent la hauteur) ; complétez ces informations à partir de la fiche technique. N'importez que la carte exacte que vous achèterez, même fabricant et même révision : les pastilles d'une carte de marque ne disent rien d'un clone avec la même puce. Lorsque le catalogue n'a pas de données de pastilles pour la pièce, écrivez le fichier à partir de la fiche technique ou du dessin du fabricant, en suivant references/circuit.md (« Ajouter une pièce »). Ensuite, écrivez les connections et vérifiez-les :

bun scripts/validate.ts <projectDir>     # vérification des règles électriques, sortie 1 en cas d'erreurs

Les erreurs bloquent. Chaque constat indique ce qui ne va pas, pourquoi c'est important et quoi changer ; corrigez project.json et relancez jusqu'à ce que ce soit propre. Les avertissements sont des jugements : résolvez-les ou informez l'utilisateur en termes simples. Ne supprimez jamais un constat en modifiant un fichier de pièce pour le faire passer, sauf si le fichier de pièce est réellement erroné, et dites-le si vous le faites. Lorsque la consommation réelle d'une pièce dépasse l'alimentation et que le firmware la limitera, déclarez cela avec peakMa et peakMaWhy dans l'entrée de la pièce (voir la référence) plutôt que de le cacher.

3. Approvisionnement et chemin de construction

Décision, demandée explicitement : voulez-vous un PCB fini, ou voulez-vous le souder vous-même ? Expliquez les trois chemins en une phrase chacun et recommandez-en un pour ce projet et cette personne :

build.pathCe que l'utilisateur faitBon quand
wireSoude (ou pousse sur, joint: "dupont") des fils entre les modules, en suivant le guideUnique, peu de connexions, le veut cette semaine
pcb-diyCommande une carte bare carrier, soude les modules dessusPlusieurs unités, nombreuses connexions, veut soigné et robuste
pcb-assembledCommande la carte avec les supports soudés, insère les modulesPas de fer à souder, ou un cadeau pour quelqu'un qui n'en a pas

Ensuite, obtenez les prix en direct. Lisez d'abord references/sourcing-stores.md ; il couvre quels magasins ont une API, lesquels chercher sur le web, et la TVA et les douanes pour le pays de l'utilisateur.

bun scripts/shopping.ts <projectDir> --region NO   # out/shopping/index.html : la liste qu'une personne achète
bun scripts/source.ts <projectDir>       # candidats prix et stock par pièce, depuis les magasins avec API
bun scripts/bom.ts <projectDir>          # out/bom.csv, out/bom.md, total estimé

Commencez par shopping.ts. Il n'a besoin d'aucune API : pour chaque pièce, il montre le dessin, ce à quoi une annonce doit correspondre (taille, ordre des broches, plage d'alimentation, hauteur), et des boutons qui ouvrent la bonne recherche chez les détaillants pour la région de l'utilisateur (code pays à deux lettres ; la liste des magasins est assets/stores.json). Cette page seule suffit à un utilisateur pour acheter, et c'est la bonne transition lorsque vous ne pouvez pas chercher les prix vous-même. Il ne commande jamais rien. Allez ensuite plus loin et trouvez des annonces et prix réels là où vous le pouvez :

Le catalogue de pièces fourni (references/catalog.md) contient des faits du fabricant, pas des prix : find et show renvoient des dimensions et broches liées aux sources pour écrire un fichier de pièce. Un catalogue complet (localisé par --db ou BENCHTOP_CATALOG) a également des annonces de magasins : bun scripts/catalog.ts listings "<part>" --norway. Ses chiffres sont des affirmations du vendeur et du fabricant, jamais des mesures.

Attendez-vous à ce que les magasins avec API manquent les modules clones génériques (les cartes de capteurs et d'affichage bon marché que la plupart des constructions utilisent) et proposent à la place une carte de marque avec une taille ou un ordre de broches différent. Ce n'est pas une correspondance : recherchez sur les magasins en ligne nommés dans la référence la variante exacte que le fichier de pièce décrit.

source.ts rassemble les candidats ; vous choisissez. Préférez un ou deux magasins plutôt que cinq (l'expédition domine les petites commandes), vérifiez que chaque annonce est la même variante que le fichier de pièce (l'ordre des broches et la taille diffèrent entre les clones), et écrivez vos choix dans project.sourcing : une ligne par pièce avec la variante à choisir dans sa note, et une entrée shipping par magasin (laissez son price de côté si le magasin ne le montre qu'à la caisse). Lorsqu'une annonce fournit plusieurs pièces, un assortiment de résistances pour trois résistances, donnez-lui une ligne et nommez les autres références dans covers. Une pièce que l'utilisateur dit déjà posséder obtient "owned": true sur son entrée dans parts au lieu d'une ligne : elle reste dans le guide et les vérifications, ne coûte rien, et la page d'achat indique à l'utilisateur quoi vérifier sur celle qui est dans son tiroir. Relancez bom.ts ; il affiche alors le total réel, frais d'expédition compris. Montrez ce chiffre à l'utilisateur avant qu'il ne commande quoi que ce soit. Un magasin signalé comme « indisponible » est une panne de son côté, pas une raison d'arrêter : continuez avec les autres.

4. Fichiers de construction

Générez ce dont le chemin choisi a besoin, puis regardez chaque sortie avant de la montrer. Pendant l'itération, exécutez le script sur lequel vous travaillez. Avant de remettre quoi que ce soit, exécutez l'ensemble du pipeline une fois pour qu'aucun fichier ne soit obsolète ou manquant :

bun scripts/build.ts <projectDir> --region NO   # chaque étape dans l'ordre ; s'arrête si la vérification électrique échoue

Il imprime une ligne par étape, répète tout ce qu'un générateur a signalé dans une liste, et écrit out/build-report.md. Une étape qu'il saute indique pourquoi (Blender manquant, pas encore de copie de présentation). Il compile le firmware : une erreur de compilation fait échouer la construction, et la première compilation pour une famille de puces télécharge sa chaîne d'outils (environ 1 Go, quelques minutes), ce qui est prévu. Un rapport qui indique PAS COMPILÉ signifie que le firmware n'est pas vérifié ; dites-le lors de la remise. Les scripts individuels :

bun scripts/guide.ts <projectDir> --pdf  # out/guide/index.html + guide.pdf
bun scripts/enclosure.ts <projectDir>    # out/enclosure/ : body.stl, lid.stl, .3mf, assembly.glb, print.md
bun scripts/pcb.ts <projectDir>          # chemins pcb uniquement. pcb/board.tsx + out/pcb/ : gerbers.zip, schematic.svg, pcb.png, order.md
bun scripts/firmware.ts <projectDir>     # firmware/ : platformio.ini, include/pins.h, test de démarrage, squelette main.cpp
bun scripts/compile.ts <projectDir>      # compile le test de démarrage et main avec PlatformIO ; erreurs en fichier:ligne
bun scripts/render.ts <projectDir>       # out/renders/ : hero.png, hero-alpha.png, exploded.png, top.png (nécessite Blender)
bun scripts/drawing.ts <projectDir>      # out/drawings/ : plan de câblage, dessin du boîtier dimensionné, carte des broches, feuille de vérification d'ajustement 1:1
bun scripts/shoot.ts <projectDir>/out/guide/index.html <projectDir>/out/shots --pages 1,3,4 --width 900

Lisez la référence pour chaque étape que vous exécutez : references/guide.md, references/enclosure.md, references/pcb.md, references/firmware.md, references/renders.md, references/drawings.md. Chacune explique quoi vérifier et quoi changer dans project.json lorsque le résultat n'est pas correct. Écrivez ensuite le comportement réel du firmware dans firmware/src/main.cpp, en utilisant uniquement les constantes de pins.h.

Les scripts de boîtier et de PCB impriment des avertissements (un évent recouvert par une autre pièce, un port qui n'atteint pas une paroi, une pièce montée sur fil laissée de côté sur la carte). Ce sont des problèmes de conception, pas du bruit. Corrigez la disposition ou dites à l'utilisateur quelle est la conséquence.

guide.ts et drawing.ts vérifient leurs propres dessins à chaque construction et impriment une ligne par problème : un fil qui se termine sur une pastille cachée derrière un composant plus grand, un nom de broche sans endroit clair pour se poser, des pièces qui se chevauchent dans une vue éclatée, un fil traversant une pièce dans le plan de câblage. Chaque ligne nomme la page, l'étape et la pièce. Les constats de disposition peuvent être corrigés avec bench ; les constats du moteur de rendu appartiennent au générateur, et la géométrie non résolue nécessite des données sources. Ne modifiez pas la géométrie correcte d'une pièce pour faire taire un constat du moteur de rendu. Une pièce marquée geometryEvidence.status: "unresolved" (la disposition de son fichier est contredite par des preuves ; aujourd'hui, c'est le microphone INMP441) se construit toujours : le boîtier, les dessins, le guide et le package sont fabriqués à partir des chiffres du fichier, un avertissement : le dit une fois par construction, et chaque sortie affectée porte « LAYOUT NON VÉRIFIÉ ». Répétez cet avertissement en premier lors de la remise, dites à l'utilisateur de mesurer la pièce et de la corriger dans le dossier parts/ du projet avant d'imprimer, et ne présentez jamais un tel boîtier comme prêt à imprimer. L'impression de test d'ajustement est la porte. --strict-geometry (ou BENCHTOP_STRICT_GEOMETRY=1) retransforme l'avertissement en refus avec un guide logique partiel ; un PCB carrier est refusé dans tous les modes, car une carte coûte de l'argent et n'a pas de test d'ajustement bon marché. --strict se termine avec un code non nul tant qu'un constat de dessin demeure. Une vérification propre signifie que les invariants de dessin testés sont vérifiés, pas que le fichier de pièce est correct.

5. Présentation

Lisez references/showcase.md. Écrivez le bloc showcase (titre, comment ça fonctionne, fonctionnalités, statistiques, FAQ, thème), puis :

bun scripts/package.ts <projectDir>      # dist/<slug>/ (index.html, guide/, files/) + dist/<slug>.zip
bun scripts/shoot.ts <projectDir>/dist/<slug>/index.html <projectDir>/out/shots --width 1320 --height 2400

Regardez la page, en entier : --from 2400 capture la fenêtre à partir de 2400 px vers le bas. La copie est la vôtre et c'est ce qui sépare une page produit d'un modèle avec des noms échangés ; la référence explique comment l'écrire et comment choisir un thème. Les prix sur la page proviennent de project.sourcing une fois que chaque pièce a une ligne dedans. Une ligne achetée dans une devise autre que celle du projet porte sa propre currency ; les totaux sont alors affichés par devise (« 401 NOK + 7.95 USD ») et jamais convertis. Sans approvisionnement, la page indique que le chiffre est une estimation basée sur les prix typiques.

package.ts reconstruit le guide à partir de project.json à chaque fois, donc ne corrigez jamais un fichier généré à la main : la correction est perdue lors de la prochaine exécution et les fichiers sont en désaccord jusqu'à cette date. Si un générateur est erroné, modifiez son entrée, et s'il ne peut pas être corrigé de cette façon, dites à l'utilisateur ce qui ne va pas dans la sortie plutôt que de le corriger silencieusement.

6. Remise

Dites brièvement à l'utilisateur : où se trouve le package, combien il coûtera, quoi faire en premier, et ce qui n'a pas été vérifié. Soyez précis. Voir « Ce que la précision signifie ici ».

Ce que la précision signifie ici

Lisez references/geometry-evidence.md avant d'utiliser une pièce clone pour un boîtier ou un PCB carrier. Vérifiez assets/geometry-evidence.json.

Skills associés