Ferry est un canal privé entre des machines que votre équipe reconnaît déjà — appairées une fois, vérifiées par une phrase lue à voix haute, disponibles ensuite en permanence. Envoyez un fichier, un secret ou un message directement d'une machine à une autre : pas de cloud, pas de compte, pas de serveur au milieu, et rien qui traîne pour toujours dans un historique de chat cherchable. Les secrets portent un TTL et se détruisent à la première ouverture ; chaque échange atterrit dans un journal d'audit sans contenu à la place.
Ce n'est ni une messagerie ni AirDrop. C'est le canal pour ce qui ne devrait être ni dans l'un ni dans l'autre — identifiants, clés, tout ce qui a une date d'expiration.
Gratuit et open source, Apache-2.0. Un démon, trois portes d'entrée : la ligne de commande ferry, une extension VS Code, et une application de bureau.
# machine A ferry send laptop-b ./build/app.tar.gz ferry send laptop-b ./.env --burn # disparaît dès qu'ils l'ouvrent
Logiciel en pré-version
Le format de transport et le format sur disque changent encore, et rien n'a fait l'objet d'un audit de sécurité externe. Jouez avec, n'en dépendez pas — et n'y faites pas passer quoi que ce soit que vous seriez fâché de perdre ou de divulguer. La compatibilité entre versions n'est pas promise avant la 1.0.
Pourquoi
Un drive cloud, un pastebin, Slack, un e-mail — le secret atterrit sur le disque d'un tiers, se fait indexer, se fait sauvegarder, et n'est plus qu'à une fuite, un export ou une recherche un peu trop poussée d'être trouvé par quelqu'un qui n'aurait jamais dû le voir. Ferry ne fait rien de tout ça. La donnée quitte votre machine et arrive sur la leur, et c'est tout le trajet. Il n'y a aucun serveur à pirater, aucun historique de canal à purger, rien à réquisitionner.
Le compromis est réel
Ferry ne fonctionne que si les deux machines peuvent réellement se joindre — le même réseau de bureau, un partage de connexion, un VPN. Il n'y a pas de relais et il n'y en aura jamais, donc il ne traversera pas Internet pour vous. Si c'est ce qu'il vous faut, Ferry n'est pas l'outil.
Réponses franches
Comment ça marche
Créée au premier lancement du démon, jamais écrite sur disque en clair. Gardée dans le trousseau de l'OS, ou dans un fichier chiffré avec age sur une machine sans interface.
Quelqu'un lit un code court à voix haute ; puis les deux personnes confirment que la même phrase de vérification s'affiche sur les deux écrans. Jamais sauté, jamais « oui » par défaut, jamais contourné par « faire confiance à ce réseau ».
Chaque connexion démarre par un handshake Noise qui rejette toute clé absente de votre roster — avant de lire une seule commande. Appliqué dans le transport, jamais seulement dans l'interface.
Les fichiers sont scellés avec age. Les secrets reçoivent en plus leur propre clé jetable, et « détruire à la lecture » broie la clé enveloppée, puis le chiffré, puis la ligne — une destruction interrompue laisse un chiffré inouvrable, jamais un orphelin ouvrable.
Le TTL et la destruction à la lecture sont mesurés sur l'horloge monotone du destinataire à partir de la livraison — jamais sur un horodatage fourni par l'expéditeur. Si les horloges divergent après un redémarrage, l'élément expire.
Il consigne qu'il s'est passé quelque chose, qui, quel élément, quand, et le résultat — et rien sur ce qu'il contenait.
Trois surfaces
Le démon est la seule chose qui parle le protocole pair-à-pair. Tout ce que vous touchez lui parle par un socket local et jamais directement à une autre machine.
Les binaires ferry et ferry-daemon. ferry send, ferry receive, ferry pair, ferry activity — n'importe quelle commande démarre elle-même le démon au premier usage, sauf ferry status, qui ne fait jamais que dire la vérité.
Apporte son propre démon — rien d'autre à installer. Une barre latérale et un panneau complet, la même appli : appairage, boîte de réception, panneau d'envoi et compositeur de secrets, le tout dans l'éditeur.
Une coque Tauri autour de la même interface, pour les machines sans éditeur dans la boucle. Le démon est embarqué dans l'installeur comme son propre sidecar — rien à lancer séparément.
L'appairage vit dans la CLI, pas dans le démon sans tête — il faut un humain pour lire une phrase de vérification à voix haute, et une étape qui exige structurellement une personne ne peut pas vivre dans un processus qui structurellement ne peut en joindre aucune.
L'interface
Une seule app React, trois hôtes. Montrée ici avec des données fictives.
Opt-in
Par défaut, Ferry ne fait aucun appel réseau à part un transfert direct vers un pair. Deux fonctions peuvent parler à l'API de GitHub — et seulement après que vous ayez mis remote_features_enabled = true et connecté un compte. Rien ne part vers GitHub avant ça, Ferry ne bascule jamais vers GitHub de lui-même, et le laisser éteint ne vous coûte que ces deux fonctions.
Vous choisissez, élément par élément, de déposer une copie déjà scellée sur GitHub en gist privé et de donner le lien à quelqu'un — pour quand vous ne pouvez pas être sur le même réseau. Le compromis est réel : le chiffré quitte votre machine, la destruction à la lecture ne peut plus être honorée, et GitHub apprend la clé publique du destinataire et la taille du fichier.
Pointez Ferry vers un fichier de dépôt — n'importe quelle URL que vous contrôlez. Il récupère le roster signé, vous montre qui l'a signé et le diff exact des ajouts/retraits, et n'importe que sur une seconde confirmation.
Chaque échange avec GitHub est un choix que vous faites pour cette action précise. Aucune synchro en arrière-plan, aucune télémétrie, aucun envoi automatique.
Architecture
Huit crates Rust dans un seul workspace Cargo. Les dépendances ne pointent jamais que dans un sens, donc une violation est une erreur de build, pas une habitude de revue de code.
direction des dépendances
daemon / cli → core → net / store / crypto → proto
crates/proto Types, enums et codes d'erreur. Zéro logique. Les bindings TypeScript en sont générés ; la CI échoue sur tout diff.
crates/core Chaque décision de domaine. Pilotable depuis le démon, la CLI, ou un harnais de test à faux réseau sans changement — ne mentionne jamais un socket, une base de données, ni React.
crates/net · store · crypto La mécanique : framing et transport, SQLite, les primitives auditées.
crates/daemon · cli Câblent le tout et rien d'autre.
crates/remote La seule crate qui sait que HTTP existe — derrière les fonctions GitHub désactivées par défaut.
Comment se mesure « terminé »
Ferry tient un registre de vérification : une ligne par flux visible par l'utilisateur, et une ligne n'est verte qu'une fois le flux exécuté de bout en bout sur deux vraies machines sur un vrai réseau, y compris une déconnexion et une reconnexion quand ça compte. Le code qui compile, les tests unitaires qui passent, et le harnais à deux nœuds qui passe méritent tous une note inférieure — ils renseignent sur la machine à états, pas sur un partage de connexion avec un portable en veille dessus.
Un vrai cycle appairer → envoyer → détruire → ouvrir fonctionne aujourd'hui entre deux démons sur un même hôte, et entre deux conteneurs sur un réseau multicast en CI. Le passage sur deux machines physiques et un audit de sécurité externe restent à faire. C'est pour ça que c'est une pré-version, et c'est dit ici plutôt que découvert plus tard.
350+ tests Rust · harnais à deux nœuds en mémoire · run CI à deux conteneurs · builds Windows + macOS
Se le procurer
Chaque canal ci-dessous sort de la même release taguée. Choisissez celui qui vous convient — téléchargez une archive, tirez une image, ou compilez vous-même.
.tar.gz (Linux/macOS) ou .zip (Windows) avec ferry + ferry-daemon dedans, bit exécutable intact. Extrayez, posez sur votre PATH.
docker pull ghcr.io/firaslamouchi21/ferry, miroir sur Docker Hub. CLI et interface dans une seule image, aucune toolchain Rust ou Node.
.deb / .AppImage / .rpm sur Linux, .dmg sur macOS, .msi / un .exe d'installation sur Windows — le démon est embarqué dedans. Non signé pour l'instant ; voyez ce que ça implique.
Pas encore sur le Marketplace — prenez le .vsix de votre plateforme dans la release et code --install-extension ferry-. Apporte son propre démon.
compiler depuis les sources
git clone https://github.com/firaslamouchi21/Ferry cd Ferry cargo build --release -p ferry-daemon -p ferry cargo test --workspace bash testing/local-two-peer.sh
ou la commande unique : ./dev.sh compile le démon + la CLI et ouvre l'interface contre eux, sans Docker ni jonglage de terminaux.
Un premier lancement
ferry daemon start ferry pair listen --name laptop-a ferry pair connect 192.168.1.20:53124 482913 --name laptop-b ferry send laptop-b ./.env --burn ferry receive list ferry receive open <item-id> --out ./.env
ferry send écrit juste l'élément dans une file locale ; le démon le livre la prochaine fois que l'autre machine est là. Une machine sans tête — un runner CI, un NAS — garde son identité dans un fichier chiffré et se fait appairer depuis un portable avant d'être déployée.
Contribuer
Il y a une courte liste de choses sur lesquelles Ferry ne cédera pas — jamais de serveur, roster appliqué au handshake, appairage toujours un code plus une phrase confirmée, un état réel sur chaque élément, journal d'audit sans contenu, crypto uniquement à partir de primitives revues. Un changement qui en casse une discrètement est renvoyé, aussi utile soit-il ; tout le reste est bienvenu.
Apache-2.0, et aussi vendu en builds packagés — les contributions entrent aux mêmes conditions, avec une attestation DCO (git commit -s).
Contact
Un bug, une idée, une inquiétude de sécurité, ou l'envie d'aider à faire avancer Ferry vers la v2 — ça arrive directement dans la boîte de Firas et vous recevrez un accusé automatique. Pour les vulnérabilités, utilisez l'adresse du fichier SECURITY.md plutôt que ce formulaire.