colisdocs

CLI

La commande colis : envoyer, recevoir, suivre et annuler un colis, vérifier une installation, et garder les réglages dans un fichier.

Le paquet npm @mdemb/colis fournit la commande colis :

npm i -g @mdemb/colis
colis --help

Elle se construit aussi depuis le dépôt, voir Installation.

Son analyseur d’arguments est parseArgs de node:util. @colis/core et @colis/protocol sont embarqués dans le build ; sa seule dépendance est le client S3 d’AWS.

Trois façons de travailler

Vers le service public, sans rien configurer. Sans --remote, sans COLIS_REMOTE, sans fichier de configuration et sans bucket, la CLI parle à https://colis-tau.vercel.app/api/transfers : pas de mot de passe, et un compte seulement si vous le voulez (colis connexion). Ce service est ouvert à tous, donc limité : un fichier de 100 Mo au plus, gardé 24 h au plus, et 20 envois par heure depuis une même adresse. Au-delà, le serveur répond TOO_LARGE ou RATE_LIMITED, et la CLI affiche son message et ce qu’il faut faire. Les fichiers sont stockés dans le bucket du service ; colis config indique quand il est utilisé.

colis envoyer ./maquette.pdf
colis statut K7QP2M4X

Vers votre page de livraison, avec --remote (ou remote dans le fichier de configuration). La machine qui envoie n’a besoin d’aucune clé S3 : elle tient le DROP_PASSWORD du déploiement, qui tient les clés. C’est le mode à utiliser pour livrer à un client : le déploiement tient l’accusé de réception et envoie les webhooks.

colis --remote https://votre-livraison.vercel.app/api/transfers --token "$DROP_PASSWORD" envoyer ./maquette.pdf

Directement vers le bucket, dès qu’un bucket est configuré (--bucket, COLIS_BUCKET ou bucket dans le fichier) et sans --remote. La CLI utilise les identifiants S3 de la machine et écrit dans le bucket elle-même. Pratique pour tester un bucket ou échanger un fichier entre vos propres machines, mais sans page de retrait, sans accusé et sans webhook : ce sont des fonctions du déploiement.

Ce n’est pas une seconde implémentation. La CLI n’en a qu’une, le client du protocole, branché soit sur fetch, soit directement sur le gestionnaire de routes dans le même processus.

envoyer

$ colis envoyer ./maquette-v2.pdf
maquette-v2.pdf · 1.8 MB · expires in 1 day
K7QP2M4X

Le code va sur stdout et tout le reste sur stderr, donc la commande se compose :

CODE=$(colis envoyer ./maquette-v2.pdf)

- lit stdin, ce qui permet d’envoyer un dossier :

tar cz ./export | colis envoyer - --name export.tar.gz

--name change le nom sous lequel le fichier est stocké. --expires-in règle la durée de vie (3600, 30m, 24h, 7d ou never). Vers une page de livraison, elle n’est envoyée que si vous la donnez, et le serveur la garde dans les limites de votre formule : au-delà de la formule gratuite, PLAN_LIMIT si la formule Pro l’accepterait ; sans l’option, c’est la durée par défaut du déploiement. never n’y a pas de sens et est refusé.

Vers une page de livraison (le service public compris), un fichier de 4 Mo au plus part en une requête. Au-delà, la CLI passe par les routes d’envoi direct, comme la page : les morceaux vont droit au bucket, et aucune règle CORS n’est nécessaire hors navigateur. Voir Gros fichiers.

Une nouvelle version : --remplace

Le client a demandé des corrections ? Envoyez la version corrigée sous le même code :

$ colis envoyer ./maquette-v3.pdf --remplace K7QP2M4X
maquette-v3.pdf · 1.9 MB · expires in 1 day
Version 2 envoyée sur K7QP2M4X
K7QP2M4X

Le client rouvre le même lien et y trouve la nouvelle version, avec l’historique des précédentes. Seul l’expéditeur peut le faire, et seulement après « corrections demandées » : un livrable validé est clos. La preuve, c’est le jeton d’expéditeur que la page de livraison remet à chaque envoi ; la CLI le garde dans ~/.config/colis/envois.json (ou sous $XDG_CONFIG_HOME), lisible par vous seul, donc --remplace marche depuis la machine qui a fait le premier envoi. Voir Suivi et validation.

recevoir

$ colis recevoir k7qp-2m4x
Wrote /home/vous/maquette-v2.pdf · 1.8 MB

Le fichier est écrit sous son nom d’origine, ou sous -o <chemin> ; -o - l’écrit sur stdout. Le code se tape comme on veut : casse et tirets sont ignorés. Pour un colis protégé par un mot de passe, passez-le avec --token.

statut

L’accusé de réception d’un colis : envoyé, ouvert, validé ou à corriger.

$ colis statut K7QP2M4X
à corriger
envoyé      2026-09-22 10:00
ouvert      2026-09-22 11:00
à corriger  2026-09-22 12:00
comment     Le logo en SVG, et le fond plus clair.

La première ligne est l’état seul, pour colis statut K7QP2M4X | head -1 dans un script ; --json donne l’objet complet (code, status, sentAt, openedAt, decidedAt, comment, isSender, version, versions). Après un --remplace, l’état est celui de la version en cours ; la sortie ajoute version 2 of 2 et une ligne par version précédente, avec la réponse du client. Depuis la machine qui a envoyé le colis, statut joint le jeton d’expéditeur, et isSender vaut true.

statut interroge une page de livraison : l’accusé est tenu par elle, pas par le bucket. Sans rien configurer, c’est le service public. Avec un bucket et sans --remote, la commande le dit, indique seulement si le colis est encore là, et sort en erreur. Voir Suivi et validation.

annuler

$ colis annuler K7QP2M4X
Burned K7QP2M4X

Détruit le colis tout de suite ; sinon il expire seul. Annuler un code déjà disparu n’est pas une erreur. Vers une page de livraison, cela envoie parcel.deleted.

connexion, compte et deconnexion

Un compte est facultatif. Connecté, vos envois vers ce serveur sont rattachés à votre compte, et la limite d’envois par heure se compte par compte plutôt que par adresse.

$ colis connexion
Ouvrez https://colis-tau.vercel.app/connexion?code=BCDF-GHJK
et confirmez le code BCDF-GHJK (valable 10 min).
En attente de la confirmation…
Connecté en tant que vous@exemple.fr.

La page s’ouvre dans le navigateur quand c’est possible ; connectez-vous-y par lien e-mail si ce n’est pas déjà fait, vérifiez que le code est bien celui du terminal, puis confirmez. La CLI attend la confirmation et garde la session un an dans ~/.config/colis/compte.json, lisible par vous seul, comme envois.json. Ensuite, colis envoyer l’envoie en Authorization: Bearer à ce serveur.

$ colis compte
vous@exemple.fr
formule         Pro
taille          jusqu’à 2 Go par fichier
durée           jusqu’à 30 jours par lien
envois          200 par heure
renouvellement  27 octobre 2026 (mensuel)
serveur         https://colis-tau.vercel.app/api

$ colis deconnexion
Déconnecté de vous@exemple.fr.

Sur un serveur qui propose la formule Pro :

colis compte pro            # ouvre le paiement Stripe, abonnement mensuel
colis compte pro --annuel   # abonnement annuel
colis compte gerer          # carte, factures, résiliation

La page de paiement s’ouvre dans le navigateur quand c’est possible, et son adresse est toujours affichée. Un envoi qui dépasse les limites de la formule gratuite, mais pas celles de Pro, échoue en PLAN_LIMIT : la CLI affiche le message du serveur et rappelle colis compte pro.

deconnexion révoque la session sur le serveur, puis l’oublie sur la machine. Une session expirée ou révoquée fait échouer l’envoi en INVALID_SESSION plutôt que de l’envoyer anonymement : reconnectez-vous, ou déconnectez-vous pour envoyer sans compte. Avec --token (le DROP_PASSWORD d’un serveur privé), c’est lui qui occupe l’en-tête et la session n’est pas envoyée.

verifier

La commande à lancer en premier. Contre un bucket, elle effectue les opérations dont colis a besoin et rapporte ce qui s’est passé :

$ colis verifier
Using /home/vous/livraisons/colis.config.json
✓ Configuration: bucket "livraisons", region "auto", https://….r2.cloudflarestorage.com
✓ Credentials: resolved, key ends in 1a2b
✓ Bucket reachable: HeadBucket succeeded
✓ Write, read, delete: round-tripped a probe object
! Expiry cleanup: no enabled expiration rule
  → Add an S3 lifecycle rule that expires objects under …
! Browser uploads (CORS): no CORS configuration
  → For large files in the colis drop, add a CORS rule allowing PUT from your site and exposing ETag. …

Les deux derniers contrôles sont des avertissements : la règle de cycle de vie, sans laquelle les colis expirés restent stockés et facturés, et la règle CORS dont les gros fichiers ont besoin. L’objet de test est supprimé avant la fin.

Contre une page de livraison, elle vérifie la seule chose qui compte, un vrai aller-retour :

$ colis verifier --remote https://votre-livraison.vercel.app/api/transfers --token "$DROP_PASSWORD"
✓ Server: https://votre-livraison.vercel.app/api/transfers answered
✓ Create, read, delete: round-tripped code 8WTXQC8R

Elle sort en erreur si un contrôle échoue, donc colis verifier --json sert de test après un déploiement.

init

Écrit un colis.config.json de départ pour un fournisseur, puis dit ce qu’il reste à faire :

$ colis init --provider r2 --bucket livraisons
Wrote /home/vous/livraisons/colis.config.json

Put the three values in .env, and keep it out of git:
  R2_ACCOUNT_ID=…
  R2_ACCESS_KEY_ID=…
  R2_SECRET_ACCESS_KEY=…
…

--provider accepte aws, r2, minio, scaleway, wasabi ou remote. remote écrit une configuration qui parle à une page de livraison, avec le jeton lu dans COLIS_TOKEN. La commande refuse d’écraser un fichier existant sans --force, et écrit ailleurs avec --config <chemin>.

config

Ce que la CLI a retenu, et d’où vient chaque valeur :

$ colis config
file         /home/vous/livraisons/colis.config.json (profile "prod")
profiles     prod, local
mode         https://votre-livraison.vercel.app/api/transfers (over HTTP)

Elle n’affiche jamais un secret (l’identifiant de clé est masqué à ses quatre derniers caractères, le jeton est seulement signalé comme présent) et ne contacte rien : elle fonctionne avant tout le reste.

Le fichier de configuration

Tout ce que prennent les options, dans un fichier que la CLI trouve seule :

colis.config.json
{
  "remote": "https://votre-livraison.vercel.app/api/transfers",
  "token": "${COLIS_TOKEN}",
  "envFile": ".env"
}

La CLI cherche --config <chemin> ou $COLIS_CONFIG, puis colis.config.json, .colisrc.json ou .colisrc en remontant depuis le dossier courant, puis ~/.config/colis/config.json. Le premier trouvé l’emporte. ${VAR} est lu dans l’environnement, et envFile charge un fichier KEY=value d’abord : le fichier peut être versionné, pas les secrets.

Plusieurs réglages dans un seul fichier, choisis avec -p ou $COLIS_PROFILE :

colis.config.json
{
  "envFile": ".env",
  "profiles": {
    "prod": { "remote": "https://votre-livraison.vercel.app/api/transfers", "token": "${COLIS_TOKEN}" },
    "local": { "remote": "http://localhost:3400/api/transfers" }
  }
}
colis -p local verifier
colis -p prod envoyer ./maquette.pdf

Chaque clé et chaque variable d’environnement sont dans Configuration.

Options

OptionEffet
-c, --config <path>Le fichier de configuration à lire
-p, --profile <name>Le profil à utiliser dans ce fichier
--env-file <path>Lire d’abord les paires KEY=value de ce fichier
--bucket <name>Nom du bucket
--prefix <prefix>Préfixe des clés dans le bucket
--region <name>Région
--endpoint <url>Point d’accès compatible S3 : R2, MinIO, Scaleway, Wasabi…
--expires-in <d>Durée de vie : 3600, 30m, 24h, 7d ou never, envoyée aussi à une page de livraison
--annuelAvec compte pro : l’abonnement annuel plutôt que mensuel
--remote <url>Parler à une page de livraison plutôt qu’au bucket
--token <token>Jeton Bearer envoyé avec --remote : le DROP_PASSWORD, ou le mot de passe d’un colis protégé
--name <filename>Nom sous lequel stocker le fichier
-o, --output <path>Où recevoir écrit. - pour stdout
--jsonSortie lisible par une machine
--provider <name>Le modèle qu’écrit init
--forceAutoriser init à écraser un fichier existant
-h, --helpL’aide
-v, --versionLa version

Les anciens noms de s3nd restent des alias : put pour envoyer, get pour recevoir, rm pour annuler, doctor pour verifier.

Chaque commande sort avec un code non nul quand elle échoue. La couleur disparaît quand la sortie n’est pas un terminal, et quand NO_COLOR est défini.

Sur cette page