restman-0.7.5.1: README.md
[](https://gitlab.com/krakrjak/restman/-/commits/master)
[](https://gitlab.com/krakrjak/restman/-/releases)
[](LICENSE)
# RESTMan
**RESTMan** is a keyboard-driven TUI HTTP client for the terminal. Compose and
send HTTP(S) requests interactively — or script one-shot requests from the
command line — without leaving your shell.
[[_TOC_]]
---
## Features
- **All HTTP methods** — GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS, CONNECT,
PATCH, or any custom verb
- **Interactive TUI** — full-screen [Brick](https://hackage.haskell.org/package/brick)-based
terminal UI
- **Oneshot mode** — `--oneshot URI` prints the response body to stdout and
exits (scriptable like `curl`)
- **Quick Request mode** — pass a URI on the command line to pre-populate the
TUI and fire the request immediately
- **Syntax-highlighted responses** — MIME-type-aware, pygments colour theme via
[Skylighting](https://hackage.haskell.org/package/skylighting)
- **Bi-directional scroll** — arrow keys, Vi/Vim keys (`hjkl`), Page Up/Down,
and mouse wheel
- **Custom headers** — add, edit, enable, or disable individual headers in a
table with horizontal scroll
- **Default headers toggle** — view and toggle the wreq default headers
(`Accept-Encoding`, `User-Agent`, …)
- **Request payloads** — provide a body inline (`--payload`) or from a file
(`--payload-file`)
- **TLS / HTTPS** — via `http-client-tls`; 30-second timeout guards against
captive portals and slow proxies
- **Shell completions** — HTTP method names auto-complete via
`optparse-applicative`
---
## TUI Preview
```
Header(s) Payload Session Help
================================================================================
╭── Verb ──╮ ╭─────────────────── URL to Query? ──────────────────────────╮
│ GET ▼│ │ https://api.example.com/v1/items │
╰──────────╯ ╰────────────────────────────────────────────────────────────╯
╭──────────────────────────────────────────────────────────────────────────╮
│ [X] Use Default Headers │
│ ┌──────────────────────────────────────────────────────────────────┐ │
│ │ Accept-Encoding: gzip, deflate, br │ │
│ │ User-Agent: Haskell wreq-0.5.4.1/0.0.0.0 │ │
│ └──────────────────────────────────────────────────────────────────┘ │
╰──────────────────────────────────────────────────────────────────────────╯
╭─ Active ──╮╭────────────── Name ─────────────╮╭──────── Value ───────────╮
│ [X] ││ Authorization ││ Bearer my-token │
│ [ ] ││ X-Request-ID ││ deadbeef-cafe │
╰───────────╯╰─────────────────────────────────╯╰───────────────────────────╯
[+ Add Custom Header]
╭────────────────────────── Response Body ──────────────────────────────╮▲
│ { │ │
│ "items": [ │▓│
│ { "id": 1, "name": "widget" } │ │
│ ] │▼│
╰───────────────────────────────────────────────────────────────────────╯◄▓►
```
---
## Platform Support
| Platform | Status |
|---|---|
| Linux | ✓ Fully supported |
| macOS — Intel | ✓ Supported |
| macOS — Apple Silicon (M1 / M2 / M3) | ✓ Supported (requires `llvm`, see below) |
| Windows via WSL2 + Debian | ✓ Supported — recommended Windows path |
| Windows native | ⚠ Experimental — supported since [Brick 2.0](https://hackage.haskell.org/package/brick) / [vty 6.0](https://hackage.haskell.org/package/vty) via [`vty-windows`](https://hackage.haskell.org/package/vty-windows), but builds have been unreliable; see [Known Limitations](#known-limitations) |
---
## Prerequisites
| Tool | Version | Notes |
|---|---|---|
| [GHC](https://www.haskell.org/ghc/) | 9.10.x | Managed automatically by Stack |
| [Stack](https://docs.haskellstack.org/) | any recent | Primary build tool |
| [llvm](https://llvm.org/) | — | **macOS Apple Silicon only** — `brew install llvm` |
Stack will download and configure the correct GHC version (via Stackage
**LTS 24.38**) on first run.
---
## Quick Start
```sh
# 1. Clone the repository
git clone https://gitlab.com/krakrjak/restman.git
cd restman
# 2. Set up the compiler (once — downloads GHC 9.10.x if needed)
stack setup
# 3. Build RESTMan and all dependencies
stack build
# 4. Launch the TUI
stack exec restman
```
> **First build** resolves and compiles all Haskell dependencies, which can
> take several minutes.
---
## Installation
To install the `restman` binary to `~/.local/bin`:
```sh
stack install
```
Add `~/.local/bin` to your `PATH` so you can run `restman` directly:
```sh
# Add to ~/.bashrc, ~/.zshrc, etc.
export PATH="$HOME/.local/bin:$PATH"
```
RESTMan is also listed on [Hackage](https://hackage.haskell.org/package/restman)
as a package reference.
---
## Usage
### Modes of Operation
| Mode | How to invoke | Description |
|---|---|---|
| **Interactive TUI** | `restman` | Full-screen TUI — compose and send requests interactively |
| **Quick Request** | `restman URI` | TUI launches with URI pre-filled; request fires immediately |
| **Oneshot** | `restman --oneshot URI` | Prints response body to stdout and exits — no TUI |
### Command-line Reference
```
Usage: restman [--help] [-m|--method METHOD]
[--no-default-headers | --default-headers]
[-h|--custom-header NAME_VALUE]
[--payload PAYLOAD | --payload-file PATHNAME]
[--oneshot] [URI]
```
| Flag | Short | Default | Description |
|---|---|---|---|
| `--help` | | | Show help and exit |
| `--method METHOD` | `-m` | `GET` | HTTP method / verb |
| `--no-default-headers` | | off | Send **only** custom headers (suppress wreq defaults) |
| `--default-headers` | | on | Append custom headers after wreq defaults |
| `--custom-header NAME_VALUE` | `-h` | — | Add a `Name:Value` header (repeatable) |
| `--payload PAYLOAD` | | — | Inline request body (UTF-8) |
| `--payload-file PATHNAME` | | — | Load request body from a file |
| `URI` | | — | Target URL (positional, optional) |
| `--oneshot` | | off | Non-interactive one-shot mode (requires `URI`) |
`--custom-header` format: `Name:Value` — the first colon separates the header
name from its value. The flag may be repeated to supply multiple headers.
### Examples
```sh
# Open the TUI (no arguments)
restman
# Open the TUI pre-loaded with a URL (request fires immediately)
restman https://httpbin.org/get
# One-shot GET — print the response body to stdout
restman --oneshot https://httpbin.org/get
# One-shot POST with a JSON payload
restman --oneshot -m POST \
-h 'Content-Type:application/json' \
--payload '{"key":"value"}' \
https://httpbin.org/post
# PUT with a binary payload file, suppressing default headers
restman -m PUT \
--no-default-headers \
-h 'Content-Type:application/octet-stream' \
--payload-file ./data.bin \
https://example.com/upload
```
---
## TUI Keybindings
### Global
| Key | Action |
|---|---|
| `Esc` / `Ctrl+Q` | Quit RESTMan |
| `Tab` | Move focus to the next widget |
| `Shift+Tab` | Move focus to the previous widget |
| `Enter` (URL editor focused) | Send the HTTP request |
### Method Selector Popup
| Key | Action |
|---|---|
| `↓` (on Method field) | Open the method selector popup |
| `↑` / `↓` | Navigate the method list |
| `Enter` | Confirm selection and close the popup |
| `Esc` | Close the popup without changing the method |
### Custom Headers
| Key | Action |
|---|---|
| `Space` on `[+ Add Custom Header]` | Add a new empty header row |
| `Space` on a header checkbox | Enable / disable that header |
| `Tab` into a Name or Value cell | Begin editing the cell |
| `←` / `→` | Scroll cell content horizontally |
### Default Headers Toggle
| Key | Action |
|---|---|
| `Tab` to `[X] Use Default Headers` | Move focus to the toggle |
| `Space` | Toggle default headers on / off |
### Response Viewport
| Key | Action |
|---|---|
| `↓` / `j` | Scroll down one line |
| `↑` / `k` | Scroll up one line |
| `→` / `l` | Scroll right one column |
| `←` / `h` | Scroll left one column |
| `Page Down` | Scroll down one page |
| `Page Up` | Scroll up one page |
| Mouse scroll | Scroll three lines up / down |
---
## Building from Source
### Linux / Debian (and Windows WSL2)
Install the required system packages:
```sh
apt install haskell-stack libtinfo-dev libz1g-dev
```
Upgrade to the latest Stack release, then set up the compiler and build:
```sh
stack upgrade # may prompt for sudo
stack setup # downloads GHC 9.10.x
stack build
```
### macOS — Intel
```sh
stack setup
stack build
```
### macOS — Apple Silicon (M1 / M2 / M3)
Install [ghcup](https://www.haskell.org/ghcup/) and LLVM:
```sh
brew install llvm
```
Export the LLVM paths (add these to your shell profile):
```sh
export PATH="/opt/homebrew/opt/llvm/bin:$PATH"
export LDFLAGS="-L/opt/homebrew/opt/llvm/lib"
export CPPFLAGS="-I/opt/homebrew/opt/llvm/include"
```
Then build with the `aarch64` target:
```sh
stack --arch aarch64 --system-ghc build
```
### Windows
**WSL2 (recommended):** Use WSL2 with a Debian distribution and follow the
Linux / Debian steps above.
**Windows native (experimental):** Native Windows support was introduced in
vty 6.0 / Brick 2.0 via
[`vty-windows`](https://hackage.haskell.org/package/vty-windows), which
RESTMan picks up transitively through Brick. However, `vty-windows` has a
tightly pinned `Win32` dependency and build failures have been reported.
If you want to attempt a native build, install
[GHCup](https://www.haskell.org/ghcup/) for Windows, then:
```sh
stack setup
stack build
```
Please report any success or failure in the
[issue tracker](https://gitlab.com/krakrjak/restman/-/issues).
---
## Running Tests
```sh
stack test
```
The test suite uses [Tasty](https://hackage.haskell.org/package/tasty) with
HUnit unit tests, Hedgehog property tests, and an in-process HTTP echo server
for integration tests.
---
## Known Limitations
- **Windows native (experimental)** — native Windows support was added in
[vty 6.0](https://hackage.haskell.org/package/vty) and
[Brick 2.0](https://hackage.haskell.org/package/brick) via the
[`vty-windows`](https://hackage.haskell.org/package/vty-windows) backend.
However, `vty-windows` has a tightly pinned `Win32` dependency and has had
reported build failures. WSL2 + Debian remains the most reliable Windows
path until `vty-windows` stabilises.
- **8 KB header line limit** — `http-client` enforces a hard 8 KB limit per
response header line. Sites with very large headers (e.g. `slashdot.org`'s
`Content-Security-Policy`) will produce an `OverlongHeaders` exception.
- **Captive portals** — the 30-second response timeout guards against infinite
hangs, but portal authentication pages are not navigable from the TUI.
---
## Contributing
Bug reports and feature requests:
[gitlab.com/krakrjak/restman/issues](https://gitlab.com/krakrjak/restman/-/issues)
Before submitting a merge request, please ensure:
- `stack build` passes with no warnings
- `stack test` is green
- Code passes `hlint` and is formatted with `stylish-haskell`
- [pre-commit](https://pre-commit.com/) hooks are installed
(`pre-commit install`)
---
## License
[BSD 2-Clause](LICENSE) — © Zac Slade, Boyd Stephen Smith Jr.