One YAML file per request
Collections, folders and requests each live in their own small file, so diffs stay readable and merge conflicts stay rare.
Yamlet is a local-first API client for Git-friendly collections. Start one container,
open localhost:7878, and every request, folder and environment you touch is
saved as a readable YAML file in your own workspace folder.
Yamlet ships as a single container image. Mount the folder you want to keep your collections in, and the app reads and writes YAML there directly.
Run this from the directory that holds (or will hold) your collections. It is mounted at /workspace and bound to your machine only. The yamlet-data volume keeps private app state, such as the Chrome extension pairing, across updates.
$ docker run -d --name yamlet -p 127.0.0.1:7878:7878 -v "$PWD:/workspace" -v yamlet-data:/data ghcr.io/piyushdoorwar/yamlet:latest
Go to http://localhost:7878. Create a collection or import one you already have, then start sending requests. Use your browser's Install app option to give Yamlet its own window.
Everything lands in collections/, environments/ and globals/ as plain YAML. Review it, diff it, branch it and merge it like the rest of your code.
Pull the newest image, then remove and recreate the container with the same command. Your YAML lives in your folder, and keeping the same yamlet-data volume keeps the Chrome extension paired.
$ docker pull ghcr.io/piyushdoorwar/yamlet:latest
$ docker rm -f yamlet
$ docker run -d --name yamlet -p 127.0.0.1:7878:7878 -v "$PWD:/workspace" -v yamlet-data:/data ghcr.io/piyushdoorwar/yamlet:latest
Inside the container, localhost is the container itself. Use
http://host.docker.internal:<port> instead (on Linux add
--add-host=host.docker.internal:host-gateway), or run with
--network host -e HOST=127.0.0.1 (keep the HOST setting so Yamlet is not exposed to your network).
A full request workflow in the browser, with nothing hidden in a database or a hosted account.
Collections, folders and requests each live in their own small file, so diffs stay readable and merge conflicts stay rare.
Request, collection, environment and global scopes. {{variables}} are highlighted inline; hover to peek a value, click to edit it.
Fresh test data on every send with {{$guid}}, {{$timestamp}}, {{$randomEmail}} and many more, with autocomplete as you type.
Pre-request and post-response JavaScript at request and collection level, with a pm API for variables, requests and pm.test assertions.
Bearer, Basic, API key and cookie auth, plus OAuth 2.0 client credentials, password and authorization code with PKCE. Inherit it from the collection.
Every method including the new QUERY, or any custom verb. JSON, XML and text, multipart form-data with file fields, URL-encoded forms, GraphQL and binary uploads.
Run a collection or folder in order, repeat it for several iterations and feed it rows from a CSV or JSON data file.
Import cURL commands, OpenAPI and Swagger specs, and v2.1 collection JSON exports. They are converted to Yamlet YAML on save.
Turn any request into ready-to-paste code for cURL, JavaScript, Python, Go, C#, Java and other languages.
See, edit and clear the cookies your requests collect, per domain, without leaving the app. The optional Yamlet Interceptor Chrome extension syncs cookies from sites you approve.
Save responses as examples next to the request, and revisit what you sent earlier from the request history.
Work across many requests in tabs that come back when you return, and keep your hands on the keyboard with shortcuts, including Ctrl+K to jump to any request.
No export step and no sync service. The files Yamlet writes are the source of truth, so code review works on API changes the same way it works on code.
collections/
jsonplaceholder/
collection.yaml
posts/
folder.yaml
list-posts.yaml
create-post.yaml
users/
environments/
dev.yaml
globals/
globals.yaml
name: Create Post order: 2 method: POST url: '{{baseUrl}}/posts' headers: - key: Content-Type value: application/json body: type: json raw: | { "title": "Hello from Yamlet", "email": "{{$randomEmail}}" } scripts: - type: afterResponse code: | pm.test('created', () => pm.response.to.have.status(201));
The yamlet CLI (@piyushdoorwar/yamlet on npm) runs a workspace headlessly: every request, every
script, every pm.test. It prints a results table and exits with code
1 if anything fails.
$ npm install -g @piyushdoorwar/yamlet
$ yamlet run ./my-workspace --env dev
# or without installing
$ npx @piyushdoorwar/yamlet run ./my-workspace --reporter junit
--env dev--bail--iterations 5--data users.csv--reporter junit
Yamlet workspace ./my-workspace env dev ┌──────┬────────┬─────────────────────┬────────┬───────┐ │ │ Status │ Request │ Time │ Tests │ ├──────┼────────┼─────────────────────┼────────┼───────┤ │ PASS │ 200 │ GET /posts │ 84 ms │ 2/2 │ │ PASS │ 200 │ GET /posts/1 │ 61 ms │ 2/2 │ │ PASS │ 201 │ POST /posts │ 142 ms │ 2/2 │ │ FAIL │ 404 │ GET /users/99 │ 57 ms │ 0/1 │ └──────┴────────┴─────────────────────┴────────┴───────┘ 1 failed, 3 passed · 7 of 8 tests · 344 ms exit code 1
Free and open source. Runs on any machine with Docker.