sendra-core 0.1.0

Core request/response model, YAML loading and HTTP execution for Sendra.
Documentation

Sendra

CI

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:

git clone https://github.com/sendra-lab/Sendra.git
cd sendra
cargo build --workspace --release
./target/release/sendra run examples/get-request.yaml
./target/release/sendra tui examples/collection.yaml

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:

cargo run -p sendra-cli -- run examples/get-request.yaml

Smoke test

cargo run -p sendra-cli -- run examples/get-request.yaml

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:

cargo run -p sendra-cli -- run examples/collection.yaml              # all four
cargo run -p sendra-cli -- run examples/collection.yaml "Post JSON"  # just one

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.

cargo run -p sendra-cli -- run examples/scripted-request.yaml

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.

cargo run -p sendra-cli -- run examples/capture-chain.yaml

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.

cargo run -p sendra-cli -- run examples/capture-header-status.yaml

examples/environment-request.yaml uses variables instead of literals, and needs a secret in your shell to run:

API_KEY=live-token cargo run -p sendra-cli -- run examples/environment-request.yaml

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 cargo run -p sendra-cli -- run examples/environment-request.yaml --env staging
API_KEY=live-token cargo run -p sendra-cli -- run examples/environment-request.yaml --env prod

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:

cargo run -p sendra-cli -- run examples/assertions.yaml

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:

cargo run -p sendra-cli -- test examples/test-collection.yaml

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:

cargo run -p sendra-cli -- run examples/repeated-headers.yaml

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:

cargo run -p sendra-cli -- run examples/structured-bodies.yaml               # all four
cargo run -p sendra-cli -- run examples/structured-bodies.yaml "JSON body"   # just one

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, --json output, 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 test ignores 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.