# La CLI

> La ligne de commande s3nd : déplacer un fichier entre machines avec un code, vérifier qu’un bucket est réellement prêt à recevoir des transferts, et garder les réglages dans un fichier versionnable plutôt que dans l’historique du shell. Directement vers S3 ou via votre propre serveur.

Canonical: https://s3nd.sh/fr/cli · Markdown: https://s3nd.sh/fr/cli.md · English: https://s3nd.sh/cli

Déplacez un fichier avec put et get, vérifiez qu’un bucket est réellement prêt à recevoir des transferts avec doctor, et gardez les réglages dans un fichier que vous pouvez versionner. Directement vers S3 sans rien déployer, ou via votre propre serveur avec un jeton.

```sh
npm install -g @s3nd/cli
```
```sh
$ s3nd put ./report.pdf
report.pdf · 284 kB · expires in 1 day
K7QP2M4X

$ CODE=$(s3nd put ./report.pdf)          # the code is stdout, the rest is stderr
$ tar cz ./project | s3nd put - --name project.tar.gz

# on the other machine
$ s3nd get K7QP2M4X
Wrote /home/you/report.pdf · 284 kB

$ s3nd get K7QP2M4X -o -  | less        # or to stdout
$ s3nd rm K7QP2M4X
Burned K7QP2M4X
```

## La commande à lancer en premier.
Une mauvaise configuration S3 échoue tard et vaguement. doctor effectue les opérations dont s3nd a réellement besoin et rapporte ce qui s’est passé, plutôt que de lire votre policy et de raisonner dessus. L’objet sonde est supprimé avant de rendre la main.

**un point de départ par fournisseur**
```sh
$ s3nd init --provider r2 --bucket transfers
Wrote /home/you/transfers/s3nd.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=…
The R2 API token needs Object Read & Write on this bucket, and nothing else.
Give the bucket a lifecycle rule that deletes objects under "transfers/" after a day or two.
Run `s3nd doctor` — it performs the operations s3nd needs and reports what happened.
```
**et la vérification qui justifie la commande**
```sh
$ s3nd doctor
Using /home/you/transfers/s3nd.config.json
✓ Configuration: bucket "transfers", region "auto"
✓ 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 this bucket after a day or
    two. Without it, expired transfers stay stored and billed.

1 check(s) failed.
```

Cette dernière vérification est celle que personne ne découvre avant l’arrivée d’une facture. `expiresIn` empêche un transfert d’être remis ; seule une règle de cycle de vie supprime l’objet. Pointé sur un serveur, `doctor` vérifie la seule chose qui compte là-bas, un vrai aller-retour, et sort avec un code non nul en cas d’échec, donc il sert de smoke test de déploiement.

## Des réglages versionnables, des clés qui ne le sont pas.
${VAR} est lu depuis l’environnement, et envFile nomme un fichier à charger d’abord sans écraser ce que le shell a déjà défini. Les profils tiennent plusieurs configurations dans un seul fichier. Un flag bat une variable, qui bat le fichier.

**s3nd.config.json**
```json
{
  "envFile": ".env",
  "profiles": {
    "r2": {
      "bucket": "transfers",
      "region": "auto",
      "endpoint": "https://${R2_ACCOUNT_ID}.r2.cloudflarestorage.com",
      "expiresIn": "24h",
      "credentials": { "accessKeyId": "${R2_ACCESS_KEY_ID}", "secretAccessKey": "${R2_SECRET_ACCESS_KEY}" }
    },
    "local": { "bucket": "transfers", "endpoint": "http://localhost:9000" },
    "prod":  { "remote": "https://drop.example.com/api/transfers", "token": "${S3ND_TOKEN}" }
  }
}
```
```sh
$ s3nd -p local doctor          # against a MinIO container, offline
$ s3nd -p r2 put ./report.pdf
$ s3nd -p prod put ./report.pdf # through your server, with a token

$ s3nd config                   # which value won, and where it came from
file         /home/you/transfers/s3nd.config.json (profile "r2")
mode         straight to S3
bucket       transfers                                 $S3ND_BUCKET
endpoint     https://8c4….r2.cloudflarestorage.com     s3nd.config.json (r2)
credentials  …1a2b                                     s3nd.config.json (r2)
expires in   1 day                                     s3nd.config.json (r2)
```

Le fichier est cherché depuis le répertoire courant vers le haut, puis dans `~/.config/s3nd/config.json`. `s3nd config` masque l’identifiant de clé et n’affiche jamais le secret ni le jeton. L’environnement seul fonctionne aussi, ce qui est la forme que veut la CI.

## Une implémentation, deux câblages.
Chaque commande accepte --remote, qui la pointe sur un déploiement du protocole de transfert au lieu de S3. La CLI a exactement une implémentation, le client du protocole, branchée soit sur fetch, soit directement sur le handler dans le même processus. Les deux modes ne peuvent pas diverger.

```sh
$ s3nd --remote https://drop.example.com/api/transfers --token "$TOKEN" put ./report.pdf
K7QP2M4X

$ s3nd doctor --remote https://drop.example.com/api/transfers --token "$TOKEN"
✓ Server: https://drop.example.com/api/transfers answered
✓ Create, read, delete: round-tripped code 8WTXQC8R
```

Conséquence pratique : la machine d’où vous lancez ça a besoin d’un jeton pour votre propre déploiement plutôt que d’identifiants S3. C’est la forme qui convient à une équipe, où donner les clés du bucket à chaque laptop ne convient pas.

`s3nd init --provider remote` écrit le point de départ correspondant, et `doctor --remote` prouve que le serveur répond avant que quiconque n’en dépende.

[Mettre en place un serveur](https://doc.s3nd.sh/docs/server)

## Six commandes, une douzaine d’options.
### Commandes
- `put <file>`: Stocke un fichier et affiche le code à transmettre. "-" lit stdin
- `get <code>`: Récupère ce qu’un code désigne, vers le nom de fichier stocké, -o, ou stdout
- `rm <code>`: Brûle un code
- `doctor`: Vérifie que cette configuration peut réellement stocker des transferts. Code de sortie non nul quand une vérification échoue
- `init`: Écrit un s3nd.config.json de départ pour aws, r2, minio, scaleway, wasabi ou remote
- `config`: Affiche la configuration résolue, et d’où vient chaque valeur

### Options
- `-c, --config`: Fichier de configuration à lire
- `-p, --profile`: Profil à utiliser dedans
- `--env-file`: Lit d’abord des paires KEY=value depuis ce fichier
- `--bucket, --prefix, --region, --endpoint`: Réglages du bucket, prioritaires sur le fichier et l’environnement
- `--expires-in`: 3600, 30m, 24h, 7d, ou never
- `--remote, --token`: Parle à un serveur s3nd plutôt qu’à S3 directement
- `--name`: Nom de fichier sous lequel stocker le transfert
- `--json`: Sortie lisible par une machine, pour les scripts et pour doctor en CI

Sinon, la configuration vient des mêmes variables d’environnement que la bibliothèque : `S3ND_BUCKET`, `S3ND_ENDPOINT`, `S3ND_REMOTE`, `S3ND_TOKEN` et les identifiants AWS habituels. Node 20 ou plus ; l’analyse des arguments est le `parseArgs` de `node:util`, donc il n’y a rien d’autre à installer.
