
resterm v1.5.6
Client API pour terminal pour HTTP, GraphQL et gRPC. De simples fichiers .http que vous pouvez diff et versionner, avec workflows, mocks, profilage, tracing, import OpenAPI, tunnels SSH, redirections de ports Kubernetes, WebSocket, SSE et un exécuteur CLI.
Resterm
Un client API et atelier de travail natif au terminal pour REST, GraphQL, gRPC, WebSocket et SSE.
Resterm est un atelier API-as-code — ou, en termes plus familiers, un client API — construit autour de fichiers .http et .rest simples que vous pouvez différencier, relire et versionner. Il combine l'édition interactive de requêtes avec des workflows déclaratifs, des assertions, des serveurs simulés, du tracing, du profilage et de l'automatisation sans interface. Tout reste sur votre machine. Pas de comptes, pas de synchronisation cloud, pas de télémétrie.
Si vous cherchez un client de style Postman centré sur des collections GUI, Resterm n'est probablement pas fait pour vous, mais essayez-le quand même !
[!NOTE] Resterm est maintenant en v1 ! Consultez les notes de version v1.0.0 pour les nouvelles fonctionnalités et les changements cassants.
Liens rapides : Captures d'écran, Démarrage rapide, Fichiers de requêtes, Installation, Documentation.
Visite guidée des captures d'écran
Voir l'interface en action (cliquer pour déplier)
Workflows
Trace et chronologie
Profileur
Expliquer
RestermScript
Thème clair
Démo navigateur OAuth (ancienne conception d'interface)
Pourquoi Resterm
- HTTP, GraphQL, gRPC, WebSocket et SSE prêts à l'emploi.
- L'automatisation vit dans les fichiers de requêtes : conditions (
@when,@if/@elif/@else,@for-each), workflows multi-étapes (@workflow/@step), captures, variables et assertions (@capture,@var,@assert). - RestermScript, un petit langage d'expressions conçu pour Resterm, avec des hooks JavaScript quand vous en avez besoin.
- Contrôles de style Vim avec indices contextuels en barre inférieure, aide hors ligne consultable, aide
Ksous le curseur, recherche/et commandes comme:w,:q,:helpet:docs. - Authentification et tunneling intégrés : OAuth 2.0 (identifiants client, mot de passe, code d'autorisation avec PKCE), authentification adossée à vos CLI existants, tunnels SSH et redirections de ports Kubernetes. Aucun outil supplémentaire nécessaire.
- Exécuteur CLI :
resterm runpour les exécutions scriptées et l'intégration continue, avec sortie JSON et JUnit. - Serveurs simulés déclarés à côté des requêtes qu'ils imitent, avec règles de correspondance, séquences, vérification d'appels et rechargement à chaud.
- Tracing de chronologie, profilage et comparaison d'exécutions entre environnements.
- Transcriptions en streaming et console interactive pour WebSocket et SSE.
- Aucune intégration IA, jamais.
Démarrage rapide
- Installez Resterm (voir Installation pour les scripts, Windows et les installations manuelles). ```bash
brew install resterm
- Initialiser un espace de travail. ```bash
mkdir my-api && cd my-api
resterm init
resterm init vous donne un petit projet qui fonctionne sans connexion internet. Le fichier requests.http généré inclut des scénarios de simulation locaux et quelques requêtes qui s’appuient les unes sur les autres. Ils couvrent les assertions, l’authentification bearer, la correspondance JSON, json-rules, et @for-each.
- Démarrez-le et envoyez votre première requête. ```bash
resterm
Appuyez sur Ctrl+Entrée dans l’éditeur pour envoyer la requête mise en surbrillance.
Pas encore de fichiers ? Exécutez simplement resterm, saisissez une URL et appuyez sur Ctrl+Entrée. Une commande curl collée fonctionne également.
Fichiers de requête
Les fichiers de requête Resterm utilisent la syntaxe HTTP standard, complétée par des directives # @ pour la configuration et l’automatisation :```http
@setting base-url https://api.example.com/v1/
Create users
// Send this request once for each name in the list.
@for-each ["david", "tom"] as name
@when env.mode == "development"
@assert response.statusCode == 201
POST users Content-Type: application/json
{"name":"{{= name }}"}
Les paramètres définis avant la première requête s’appliquent à l’ensemble du fichier, `###` sépare les requêtes, et les directives peuvent répéter, limiter ou valider une requête. Plus d’exemples ici : [`_examples/`](https://github.com/unkn0wn-root/resterm/blob/main/_examples).
## CLI
`resterm run` exécute les fichiers `.http` / `.rest` sans ouvrir la TUI, ce qui correspond à ce que la CI exécute.```bash
resterm run --request CreateUser requests.http
Le projet généré communique avec un serveur mock local. Démarrez-le d'abord dans un autre terminal :```bash resterm mock requests.http
Dans la TUI, appuyez plutôt sur `g Shift+M` pour démarrer le même serveur mock depuis l’espace de travail.
La [documentation CLI](https://github.com/unkn0wn-root/resterm/blob/main/docs/cli.md) couvre les sélecteurs, les formats de sortie et d’autres exemples.
## Aide-mémoire clavier
- Focus et disposition des volets
- `Tab` / `Shift+Tab` : se déplacer entre la barre latérale, l’éditeur et la réponse.
- `g+r`, `g+i`, `g+p` : accéder aux requêtes, à l’éditeur ou à la réponse.
- `g+h` / `g+l` : redimensionner horizontalement. Modifie la largeur de la barre latérale lorsqu’elle est focalisée, sinon la séparation éditeur/réponse.
- `g+j` / `g+k` : redimensionner la hauteur éditeur/réponse lorsqu’ils sont empilés, réduire ou développer les branches dans le navigateur.
- `g+v` / `g+s` : basculer le volet de réponse entre les dispositions intégrée et empilée.
- `g+1`, `g+2`, `g+3` : réduire ou restaurer la barre latérale, l’éditeur, la réponse.
- `g+z` / `g+Z` : zoomer sur le volet focalisé, effacer le zoom.
- Environnements et variables globales
- `Ctrl+E` : changer d’environnement.
- `Ctrl+G` : inspecter les variables globales capturées.
- Aide et commandes
- `?` : ouvrir l’index d’aide hors ligne consultable.
- `K` (mode normal de l’éditeur) : ouvrir l’aide pour la directive, le modèle ou le mot-clé sous le curseur.
- `:help <sujet>` / `:man <sujet>` : ouvrir un sujet intégré ; `:docs <sujet>` ouvre le manuel complet correspondant à la version.
- `Ctrl+O` : ouvrir la fenêtre contextuelle fichier/espace de travail. Tapez pour filtrer, faites défiler avec `Up` / `Down`, et utilisez `Tab` pour descendre dans les répertoires.
- `:` : ouvrir la ligne de commande. Utilisez `Up` / `Down` pour sélectionner les suggestions, `Tab` pour en compléter une, ou `Enter` pour accepter et exécuter une sélection. Les arguments de chemin tels que `:mock start --source` et `:edit` parcourent le système de fichiers dans la même fenêtre contextuelle.
- Réponses
- `Ctrl+V` / `Ctrl+U` : diviser le volet de réponse pour une comparaison côte à côte.
- `Ctrl+Shift+C` ou `g y` (volet de réponse focalisé) : copier tout l’onglet Pretty, Raw ou Headers.
- `g x` : afficher l’aperçu Explain pour la requête active sans l’envoyer.
- `g e` : ouvrir le fichier actuel dans votre éditeur externe.
> [!TIP]
> Si vous ne retenez que trois raccourcis :
> - `Ctrl+Enter` envoie la requête
> - `Tab` / `Shift+Tab` change de volet
> - `g+p` accède à la réponse
## Installation
**Linux / macOS (Homebrew)**```bash
brew install resterm
[!NOTE] Les installations via Homebrew doivent être mises à jour avec Homebrew (
brew upgrade resterm). La commande intégréeresterm --updateest destinée aux binaires installés à partir des versions GitHub ou des scripts d'installation.
Linux / macOS (script Shell)
[!IMPORTANT] Les binaires Linux précompilés dépendent de glibc 2.32 ou plus récent. Sur une distribution plus ancienne, compilez à partir des sources avec une chaîne d'outils glibc plus récente ou mettez à niveau glibc avant d'utiliser les archives de version.```bash curl -fsSL https://raw.githubusercontent.com/unkn0wn-root/resterm/main/install.sh | bash
or with `wget` :```bash
wget -qO- https://raw.githubusercontent.com/unkn0wn-root/resterm/main/install.sh | bash
Windows (PowerShell)```powershell iwr -useb https://raw.githubusercontent.com/unkn0wn-root/resterm/main/install.ps1 | iex
Les scripts détectent votre architecture, téléchargent la dernière version et installent le binaire.
### Installation manuelle
> [!NOTE]
> L'assistant d'installation manuelle utilise `curl` et `jq`. Installez `jq` avec votre gestionnaire de paquets (`brew install jq`, `sudo apt install jq`, etc.).
**Linux / macOS**```bash
# Detect latest tag
LATEST_TAG=$(curl -fsSL https://api.github.com/repos/unkn0wn-root/resterm/releases/latest | jq -r .tag_name)
# Download the matching binary (Darwin/Linux + amd64/arm64)
curl -fL -o resterm "https://github.com/unkn0wn-root/resterm/releases/download/${LATEST_TAG}/resterm_$(uname -s)_$(uname -m)"
# Make it executable and move it onto your PATH
chmod +x resterm
sudo install -m 0755 resterm /usr/local/bin/resterm
Windows (PowerShell)```powershell $latest = Invoke-RestMethod https://api.github.com/repos/unkn0wn-root/resterm/releases/latest $asset = $latest.assets | Where-Object { $.name -like 'resterm_Windows*' } | Select-Object -First 1 Invoke-WebRequest -Uri $asset.browser_download_url -OutFile resterm.exe
Optionally relocate to a directory on PATH, e.g.:
Move-Item resterm.exe "$env:USERPROFILE\bin\resterm.exe"
### Depuis la source```bash
go install github.com/unkn0wn-root/resterm/cmd/resterm@latest
Mise à jour```bash
resterm --check-update resterm --update
La première commande indique si une version plus récente est disponible. La seconde la télécharge, la vérifie et l'installe en place. Sous Windows, l'ancien binaire reste à côté du nouveau sous le nom `resterm.exe.old` et est supprimé lors de la prochaine mise à jour.
## Configuration
- Les environnements sont des fichiers JSON (`resterm.env.json`) découverts dans le répertoire de la requête, la racine de l'espace de travail ou le répertoire courant. Un fichier peut définir des environnements nommés ou des groupes indépendants, par exemple api, app et credentials, qui se combinent en un seul environnement. Les fichiers Dotenv (`.env`, `.env.*`) sont activés via `--env-file` et sont mono-espace de travail. Voir [environnements groupés](https://github.com/unkn0wn-root/resterm/blob/main/docs/resterm.md#grouped-environments) et l'exemple exécutable dans `_examples/grouped/`.
- La configuration est stockée par système d'exploitation et peut être remplacée avec `RESTERM_CONFIG_DIR` :
- macOS : `~/Library/Application Support/resterm`
- Windows : `%APPDATA%\resterm`
- Linux/Unix : `~/.config/resterm`
## Serveurs simulés (Mock Servers)
Vous pouvez définir des réponses simulées dans les mêmes fichiers `.http` que vos requêtes.
- Faites correspondre les requêtes entrantes par requête, en-têtes ou corps JSON, puis choisissez une réponse nommée ou par défaut.
- Renvoyez une séquence de réponses pour les tests d'interrogation (polling) et de nouvelle tentative. Utilisez un chemin, une requête, un en-tête ou une valeur de cookie pour suivre chaque séquence séparément.
- Retardez les réponses d'une durée fixe, ou donnez à chaque requête un délai différent avec `random`, `normal` ou `jitter`.
- Construisez des réponses à partir des valeurs de chemin, de requête, d'en-tête et de corps, avec des générateurs pour les données dynamiques.
- Vérifiez les compteurs d'appels avec `@expect` ou inspectez le trafic reçu depuis RestermScript.
- Rechargez à chaud les fichiers sources et les fixtures, avec TLS optionnel.
Deux scénarios sur une même route :```http
### Payment accepted
# @mock method=POST path=/payments name=accepted default=true latency=150ms
HTTP/1.1 202 Accepted
Content-Type: application/json
{"id":"pay_123","status":"pending"}
### Payment declined
# @mock method=POST path=/payments name=declined
# @match query={"mode":"decline"} headers={"X-Tenant":"demo"} json={"amount":0}
HTTP/1.1 422 Unprocessable Entity
Content-Type: application/json
{"error":"amount must be positive"}
Servez un fichier ou un répertoire entier :```bash resterm mock ./requests.http resterm mock --recursive --addr 127.0.0.1:9090 ./requests
Plus d’informations dans la [référence Mock Servers](https://github.com/unkn0wn-root/resterm/blob/main/docs/resterm.md#mock-servers), le [guide CLI `resterm mock`](https://github.com/unkn0wn-root/resterm/blob/main/docs/cli.md#resterm-mock) et l’[exemple fonctionnel](https://github.com/unkn0wn-root/resterm/blob/main/_examples/mocks.http).
## Headless
Le package [`headless`](https://github.com/unkn0wn-root/resterm/blob/main/headless) est l’API Go publique du même moteur qui alimente la TUI et la CLI. Utilisez-le pour exécuter des requêtes, des workflows, des assertions, comparer des exécutions et des profils depuis votre propre code Go ou votre CI.
Si vous préférez ne pas construire votre propre exécuteur, il existe [resterm-runner](https://github.com/unkn0wn-root/resterm-runner).
## Collections
Exportez un espace de travail sous forme de bundle compatible Git et importez-le dans un autre. Les bundles contiennent un `manifest.json` avec des sommes de contrôle, afin que les imports vérifient d’abord l’intégrité des fichiers. Les valeurs d’environnement sont exportées sous forme de placeholders `REPLACE_ME`, de sorte que les secrets ne quittent jamais votre machine.```bash
resterm collection export --workspace ./my-api --out ./shared/my-api-bundle
resterm collection import --in ./shared/my-api-bundle --workspace ./my-local-api
Ajoutez --dry-run pour prévisualiser une importation et --force pour écraser les fichiers existants. Documentation : partage de collections.
Importation curl
Collez une commande curl dans l'éditeur et appuyez sur Ctrl+Entrée pour la transformer en requête structurée. Resterm comprend les indicateurs courants, fusionne les segments de données répétés et préserve les téléversements multipart. Les préfixes de shell comme sudo ou $ sont ignorés. La CLI effectue la même conversion avec --from-curl.
Ceci :```bash
curl -X POST https://api.example.com/login
-H "Content-Type: application/json"
--user demo:secret
-d '{"user":"demo"}'
devient ceci :```http
### POST https://api.example.com/login
# @auth basic demo secret
POST https://api.example.com/login
Content-Type: application/json
{"user":"demo"}
Docs : requêtes inline et exemples d'import.
RestermScript
RestermScript (RTS) est un petit langage d'expressions conçu pour Resterm. Il cible directement le format des requêtes, les workflows et les directives, ce qui rend les scripts courts et prévisibles. Les hooks JavaScript restent disponibles lorsque vous avez besoin de plus.
Exemple rapide (module RTS + requête) :```rts // rts/helpers.rts module helpers export fn authHeader(token) { return token ? "Bearer " + token : "" }
📦 Installation
Option 1: Install via pip
pip install kitploit
Option 2: Install from source
git clone https://github.com/kitploit/kitploit.git
cd kitploit
pip install -r requirements.txt
python setup.py install
Option 3: Use Docker
docker pull kitploit/kitploit
docker run -it --rm kitploit/kitploit
🚀 Quick Start
After installation, you can start using Kitploit immediately:
kitploit --help
This will display all available commands and options. For a more detailed guide, check the documentation.
🛠️ Usage Examples
Search for a tool
kitploit search nmap
Get details about a specific tool
kitploit info metasploit
Update the local database
kitploit update
List all available tools
kitploit list
📚 Documentation
Full documentation is available at docs.kitploit.com. It includes detailed guides, API references, and tutorials to help you get the most out of Kitploit.
# @use ./rts/helpers.rts
# @when env.has("feature")
# @assert response.statusCode == 200
GET https://api.example.com/users/{{= vars.get("user") }}
Authorization: {{= helpers.authHeader(vars.get("auth.token")) }}
```
Full reference: [`docs/restermscript.md`](https://github.com/unkn0wn-root/resterm/blob/main/docs/restermscript.md).
## Analyse approfondie
### OAuth 2.0
Utilisez `@auth oauth2` pour acquérir et injecter des jetons. Les jetons sont mis en cache par environnement et actualisés lorsque c'est possible. L'attribution des identifiants client est la valeur par défaut. L'attribution par mot de passe et le code d'autorisation avec PKCE sont également pris en charge :```http
### Service status
# @auth oauth2 token_url={{oauth.tokenUrl}} client_id={{oauth.clientId}} client_secret={{oauth.clientSecret}} cache_key=my-api
GET {{base.url}}/anything/projects
```
Exemple : [`_examples/oauth2.http`](https://github.com/unkn0wn-root/resterm/blob/main/_examples/oauth2.http). Consultez la [documentation OAuth 2.0](https://github.com/unkn0wn-root/resterm/blob/main/docs/resterm.md#oauth-20-directive).
### Workflows et scripts
Les workflows enchaînent des requêtes nommées et peuvent choisir l’étape suivante à partir d’une réponse :```http
### Sign in
# @workflow sign-in
# @step Login using=Login
// GetProfile and RefreshToken are request names.
// The first true condition runs the named request.
# @if last.statusCode == 200 run=GetProfile
# @elif last.statusCode == 401 run=RefreshToken
# @else fail="unexpected login response"
```
Ils peuvent aussi transmettre des données entre les étapes et exécuter des hooks RestermScript ou JavaScript. Exemple : [`_examples/workflows.http`](https://github.com/unkn0wn-root/resterm/blob/main/_examples/workflows.http). Consultez la [documentation sur les workflows](https://github.com/unkn0wn-root/resterm/blob/main/docs/resterm.md#workflows).
### Interrogation et nouvelles tentatives
Utilisez `@poll` pour répéter une requête jusqu'à ce qu'une condition de réponse devienne vraie. Ajoutez `@retry` pour relancer les échecs réseau, les délais d'attente ou certaines réponses sélectionnées avec un backoff exponentiel :```http
### Wait for job
# @retry count=4
# @retry-when response.statusCode in [429, 502, 503]
# @retry-backoff exponential(100ms, 2s) jitter=20%
# @poll every=500ms timeout=30s until=response.json().status == "completed"
GET {{base.url}}/jobs/{{job.id}}
```
Chaque cycle d'interrogation dispose de son propre budget de nouvelles tentatives. Exemple : [`_examples/polling-retries.http`](https://github.com/unkn0wn-root/resterm/blob/main/_examples/polling-retries.http). Consultez la [documentation sur l'interrogation et les nouvelles tentatives](https://github.com/unkn0wn-root/resterm/blob/main/docs/resterm.md#polling-and-retries).
### Comparer des exécutions
`@compare` exécute une requête contre au moins deux environnements et utilise un résultat comme référence :```http
### Compare health
# @compare dev stage prod base=prod
GET {{services.api.base}}/status
```
Appuyez sur `g+c` pour l’exécuter dans la TUI, ou fournissez `--compare` en ligne de commande. Exemple : [`_examples/compare.http`](https://github.com/unkn0wn-root/resterm/blob/main/_examples/compare.http). Consultez la [documentation sur la comparaison](https://github.com/unkn0wn-root/resterm/blob/main/docs/resterm.md#compare-runs).
### Traçage et chronologie
`@trace` enregistre les phases HTTP et peut signaler les requêtes qui dépassent les budgets de latence :```http
### Trace API
# @trace dns<=50ms connect<=120ms total<=400ms tolerance=25ms
GET https://api.example.com/health
```
Les résultats apparaissent dans l'onglet Timeline et peuvent être exportés vers OpenTelemetry. Exemple : [`_examples/trace.http`](https://github.com/unkn0wn-root/resterm/blob/main/_examples/trace.http). Consultez la [documentation sur le tracing](https://github.com/unkn0wn-root/resterm/blob/main/docs/resterm.md#timeline--tracing).
### Streaming (WebSocket et SSE)
`@sse` enregistre les événements serveur, tandis que `@websocket` et `@ws` scriptent les trames WebSocket. Les deux produisent des transcriptions dans l'onglet Stream :```http
### Events
# @sse duration=30s idle=10s max-events=5
GET https://api.example.com/events
### Chat
# @websocket idle=3s
# @ws send Hello
# @ws close 1000 done
GET wss://api.example.com/chat
```
Exemple : [`_examples/streaming.http`](https://github.com/unkn0wn-root/resterm/blob/main/_examples/streaming.http). Consultez la [documentation sur le streaming](https://github.com/unkn0wn-root/resterm/blob/main/docs/resterm.md#streaming-sse--websocket).
### gRPC
Utilisez une ligne de requête `GRPC` pour le serveur et `@grpc` pour la méthode entièrement qualifiée. Le corps est en protobuf JSON :```http
### Get user
# @grpc users.UserService/GetUser
# @grpc-plaintext true
GRPC {{grpc.host}}
{"tenantId":"{{tenant.id}}"}
```
La réflexion serveur est activée par défaut. Les ensembles de descripteurs et les appels de streaming sont également pris en charge. Exemple : [`_examples/grpc.http`](https://github.com/unkn0wn-root/resterm/blob/main/_examples/grpc.http). Consultez la [documentation gRPC](https://github.com/unkn0wn-root/resterm/blob/main/docs/resterm.md#grpc).
### Import OpenAPI
Générez des requêtes, des mocks ou les deux à partir d'un document OpenAPI local ou d'une URL `http(s)` :```bash
resterm --from-openapi _examples/openapi-spec.yml --http-out api.http --openapi-mode both
```
Remote fetches respectent `--insecure` et `--proxy`. Exemple d'entrée : [`_examples/openapi-spec.yml`](https://github.com/unkn0wn-root/resterm/blob/main/_examples/openapi-spec.yml). Consultez la [documentation d'importation](https://github.com/unkn0wn-root/resterm/blob/main/docs/cli.md#import-examples).
### Tunnels SSH
Définissez un profil SSH avant les requêtes qui l'utilisent, puis sélectionnez-le avec `use=` :```http
// Set key to choose a key file. Leave it out to use your SSH agent or a default key.
# @ssh file edge host=jump.example.com user=ops key=~/.ssh/id_ed25519
### Internal API
# @ssh use=edge
GET http://10.0.0.10/v1/health
```
Profils peuvent être à l'échelle du fichier ou de l'espace de travail, et des tunnels inline ponctuels sont également pris en charge. Exemple : [`_examples/ssh.http`](https://github.com/unkn0wn-root/resterm/blob/main/_examples/ssh.http). Consultez la [documentation SSH](https://github.com/unkn0wn-root/resterm/blob/main/docs/resterm.md#ssh-tunnels).
### Redirections de ports Kubernetes
`@k8s` ouvre une redirection de port gérée vers un pod, un service, un déploiement ou un statefulset :```http
### Service health
# @k8s namespace=default service=api port=http
GET http://api.default.svc.cluster.local/health
```
Les cibles peuvent utiliser des ports numériques ou nommés et peuvent être enregistrées sous forme de profils réutilisables. Exemple : [`_examples/k8s.http`](https://github.com/unkn0wn-root/resterm/blob/main/_examples/k8s.http). Voir la [documentation Kubernetes](https://github.com/unkn0wn-root/resterm/blob/main/docs/resterm.md#kubernetes-port-forwards).
### Thèmes et raccourcis clavier
Personnalisez les couleurs et les raccourcis clavier avec `themes/*.toml` et `bindings.toml` ou `bindings.json` dans le répertoire de configuration. Documentation : [`docs/resterm.md#theming`](https://github.com/unkn0wn-root/resterm/blob/main/docs/resterm.md#theming) et [`docs/resterm.md#custom-bindings`](https://github.com/unkn0wn-root/resterm/blob/main/docs/resterm.md#custom-bindings).
## Documentation
- [`docs/resterm.md`](https://github.com/unkn0wn-root/resterm/blob/main/docs/resterm.md) couvre la syntaxe des requêtes, les directives, les scripts et les transports.
- [`docs/cli.md`](https://github.com/unkn0wn-root/resterm/blob/main/docs/cli.md) couvre `resterm run`, les importateurs, les collections et l'historique.
- [Compatibilité](https://github.com/unkn0wn-root/resterm/blob/main/docs/resterm.md#compatibility) explique les garanties de compatibilité de Resterm pour la v1.
Dans la TUI, appuyez sur `?` ou exécutez `:help`. Utilisez `:docs` lorsque vous souhaitez consulter le manuel web complet de la version installée.
## Licence
[Licence Apache 2.0](https://github.com/unkn0wn-root/resterm/blob/main/LICENSE).