Sendra
Sendra is a terminal-native HTTP client, think Postman, but your requests are
plain YAML files that live in your repo next to the code they exercise, and you
send them from the shell. A request is just a file: method, URL, headers, body.
That makes requests reviewable in a pull request, diffable over time, and
shareable without exporting anything. A file holds either one request or a
named collection of them, sent and printed, against variables from an
environment file so the same request can point at staging or at production, and
a file can declare what it expects the response to look like — which
sendra test then passes or fails your build on. A request can also carry
inline scripts that run just before it is sent and just after it comes back,
with no Node.js or other runtime to install: the interpreter is in the binary.
An interactive terminal UI ships in the same binary, for browsing and running
requests without one shell invocation per request — see
Learn more below.
Layout
sendra/
sendra-core/ library: request/response types, YAML loading, config, environments, scripting, capture, HTTP execution
sendra-cli/ binary `sendra`: argument parsing, output, exit codes, `run`, `test` and `tui`
main.rs `main()`, and the module declarations
cli.rs the clap definitions: subcommands, arguments, `--help` text
run.rs the pipeline `run`/`test` share, and the two handlers
output/ everything printed to the terminal
mod.rs `Reporter`, `Format`, `Detail`: which rendering a run gets
human.rs the terminal rendering: response, assertions, summary
json.rs the `--json` schema: the records the document is built from
errors.rs `error:` and `hint:` lines, and the one clap usage error
exit.rs `Exit`, `Outcome`, `Summary`: exit-code policy, no I/O
test_support.rs fixtures shared by more than one module's tests
tests/ integration tests that run the built binary and read its output
sendra-tui/ the interactive TUI, launched in-process by `sendra tui`/bare `sendra`
examples/ sample request and collection files
.sendra/ this repo's own project config and environments
schema/ generated JSON Schemas for editor tooling — see docs/reference/json-schema.md
xtask/ generates schema/*.schema.json from sendra-core's types; not published
docs/
reference.md full schema and behavior reference, by topic
decisions/ the design rationale behind choices that could have gone another way
sendra-core knows nothing about clap, terminal output, or ratatui. Both
sendra-cli and sendra-tui build on it directly, so core returns typed
errors (SendraError) rather than formatted messages.
Install
No packaged release yet — there is no binary to download. For now, build it from source:
Building the workspace produces one binary, sendra, that carries run,
test and tui alike — there is no separate TUI install.
Or run it straight through Cargo without a separate build step, which is what the rest of this tour does:
Smoke test
That sends a real request to https://httpbin.org/get and prints the status,
headers and body. There is also examples/post-request.yaml, which posts a JSON
body, and examples/collection.yaml, which holds four requests in one file:
examples/scripted-request.yaml carries both hooks: a pre_request script that
adds a header, and a post_request script that checks the response it comes
back in.
examples/capture-chain.yaml is two requests where the second needs something
only the first can tell it: a token and an id captured from one response,
substituted into the next request's header and URL.
examples/capture-header-status.yaml extends that into three requests to show
the two other capture: sources — a response header and the status code —
chained alongside the original JSON-path form.
examples/environment-request.yaml uses variables instead of literals, and
needs a secret in your shell to run:
API_KEY=live-token
It reads base_url and api_key from .sendra/environments/default.yaml in
this repository and sends them to httpbin.org/headers, which echoes back what
it received, so you can see the resolved values on the wire. Leave API_KEY
unset and the run fails before connecting, naming the variable.
--env picks a different environment for the same request file. This
repository ships staging.yaml and prod.yaml beside default.yaml, pointing
at two different echo services:
API_KEY=live-token
API_KEY=live-token
The request file names no host at all — only {{base_url}} — so the two runs
come back from httpbin.org and postman-echo.com respectively, with the
resolved value echoed in the X-Sendra-Base-Url header of each response.
examples/assertions.yaml checks the response it gets back, and prints a
pass/fail line per check under it:
Two of its assertions are meant to fail, so one run shows both halves of the
output. It still exits 0 — see
Assertions.
examples/test-collection.yaml is the same idea under sendra test, which
does not exit 0:
Four requests: two that pass, one whose assertion is wrong on purpose, and one
that asserts nothing and comes back 404. It exits 4 — see
Testing.
examples/repeated-headers.yaml sends a header more than once — a list of
values instead of a scalar, since a YAML mapping cannot repeat a key — beside
an ordinary one, against httpbin.org/headers, which echoes both back:
examples/structured-bodies.yaml is a collection of four requests, one for
each structured way to specify a body — json, body_file, form and
multipart — instead of a hand-escaped body: string. Each posts to
httpbin.org/post, which echoes back exactly what it received:
That's the shortest path from zero to a working request. The rest of what
Sendra can do — the full request/collection/config schema, every CLI flag,
--json's exact shape, scripting, and the reasoning behind the harder design
calls — lives in docs/, not in this file:
Learn more
- docs/reference.md — the full schema and behavior
reference: request/collection shape, config, environments, assertions
(including the operator sub-language), capture, scripting, every CLI flag,
--jsonoutput, exit codes, editor/JSON Schema support, and the interactive TUI (sendra tui). - docs/decisions/ — the design rationale
behind choices that could reasonably have gone another way: why
sendra testignores a status nobody asserted, how the exit codes are split and ranked, the script sandboxing guarantees, and the full precedence chain from a hardcoded default to a CLI override.
Both grew out of the same source material as this file — nothing was shortened or dropped, only moved to where it's easier to find once you already know your way around.