Showcase Posting workflows in the README

Center the introduction, retain the theme slideshow, and add jump, mouse, response, and protocol demos with matching navigation links.

Amp-Thread-ID: https://ampcode.com/threads/T-01a13691-8157-7318-9b6e-4ae947bf79c4
Co-authored-by: Darren Burns <darrenb900@gmail.com>
This commit is contained in:
Amp
2026-10-13 23:20:56 +00:00
co-authored by Darren Burns
parent 52153ef6aa
commit 4843c2579c
9 changed files with 148 additions and 13 deletions
+43 -13
View File
@@ -1,31 +1,63 @@
# Posting
<h1 align="center">Posting</h1>
**A powerful HTTP client that lives in your terminal.**
<p align="center"><strong>A powerful HTTP client that lives in your terminal.</strong></p>
Posting is an HTTP client, not unlike Postman and Insomnia. As a TUI application, it can be used over SSH and enables efficient keyboard-centric workflows. Your requests are stored locally in simple YAML files, so they're easy to read and version control.
<p align="center">Posting is an HTTP client, not unlike Postman and Insomnia. As a TUI application, it can be used over SSH and enables efficient keyboard-centric workflows. Your requests are stored locally in simple YAML files, so they're easy to read and version control.</p>
<img width="968" alt="Posting cycling through six dark themes, with request tabs, a populated collection, header autocomplete, and a JSON response" src="docs/assets/themes/themes.gif" />
Full-size screenshots: [Galaxy](docs/assets/themes/galaxy.png) · [Aurora](docs/assets/themes/aurora.png) · [Lantern](docs/assets/themes/lantern.png) · [Midnight Ember](docs/assets/themes/midnight-ember.png) · [Neon Reef](docs/assets/themes/neon-reef.png) · [Cyberdeck](docs/assets/themes/cyberdeck.png).
<p align="center"><a href="https://posting.sh">Website</a> · <a href="#installation">Installation</a> · <a href="https://posting.sh/guide/">User guide</a></p>
Some notable features include:
- request tabs, so you can work on several requests at once
- "jump mode" navigation
- layered environments and variables, with a variables screen and autocompletion
- header autocompletion and collection search
- syntax highlighting
- response search, a collapsible JSON tree, and JSONPath filtering
- HTTP, GraphQL, and gRPC, including streaming
- request timing, and a persistent history of responses
- customizable keybindings
- customizable keybindings and extensive configuration
- 37 built-in themes, plus user-defined themes
- extensive configuration
- open in $EDITOR/$PAGER
- import curl commands by pasting them into the URL bar
- export requests as curl commands
- import curl commands by pasting them into the URL bar, and export requests as curl commands
- import from OpenAPI, Postman and Bruno
- a command palette for quickly accessing functionality
- `posting remote`, so coding agents like Claude Code and Codex can send requests through the Posting you have open while you watch
Visit the [website](https://posting.sh) for more information, the roadmap, and the user guide.
## Jump mode
Press a shortcut, type a label, and jump straight to any part of the interface.
<img width="968" alt="Filtering the collection, opening a request, jumping to a header field and accepting an autocompletion, then jumping into the response" src="docs/assets/features/jump-mode.gif" />
## Mouse support
Click, scroll, select text, and drag to resize panels.
<img width="968" alt="Using the mouse to switch request tabs, resize the response panel, scroll through a response, and select text" src="docs/assets/features/mouse.gif" />
## Explore your responses
Search response text, explore JSON as a collapsible tree, and filter it with JSONPath.
<img width="968" alt="Finding text in a JSON response, expanding and collapsing its tree, and filtering the same response with JSONPath" src="docs/assets/features/responses.gif" />
## gRPC and GraphQL
Send GraphQL queries and work with gRPC services, including interactive streaming.
<table>
<tr>
<th>gRPC streaming</th>
<th>GraphQL</th>
</tr>
<tr>
<td width="50%"><img width="460" alt="An open bidirectional gRPC stream with sent and received messages and Streaming status" src="docs/assets/features/grpc.png" /></td>
<td width="50%"><img width="460" alt="A GraphQL query with variables and a successful JSON response" src="docs/assets/features/graphql.png" /></td>
</tr>
</table>
## Installation
@@ -57,8 +89,6 @@ Contributions are welcome! See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines
Try gRPC locally with the [example server and collection](examples/grpc/README.md), including an interactive bidirectional streaming walkthrough.
## Learn More
Learn more about Posting at [https://posting.sh](https://posting.sh).
Posting 3 is built with [Terma](https://github.com/darrenburns/terma). Posting 2 was built with [Textual](https://github.com/textualize/textual).
<p align="center"><a href="https://posting.sh">Website</a> · <a href="#installation">Installation</a> · <a href="https://posting.sh/guide/">User guide</a></p>
@@ -0,0 +1,16 @@
name: Get user
description: A GraphQL query with variables. Uses the demo server's canned GetUser response.
kind: graphql
url: ${BASE_URL}/graphql
graphql:
query: |-
query GetUser($id: ID!) {
user(id: $id) {
id
name
email
role
}
}
variables: '{"id": "1"}'
operation_name: GetUser
+7
View File
@@ -68,6 +68,13 @@ class Handler(BaseHTTPRequestHandler):
if path == "/users":
user = {"id": 4, **self.read_json(), "created_at": "2026-10-10T09:41:00Z"}
self.respond(201, user, {"Location": "/users/4", "Set-Cookie": "session=8c1f; Path=/; HttpOnly"})
elif path == "/graphql":
# Canned response for the collection's GetUser operation, not a
# general-purpose GraphQL server.
request = self.read_json()
user_id = str(request.get("variables", {}).get("id", "1"))
user = next((user for user in USERS if str(user["id"]) == user_id), None)
self.respond(200, {"data": {"user": user}})
elif path == "/auth/login":
self.respond(200, {"token": "dev-token-123", "expires_in": 3600})
elif path == "/orders":
+82
View File
@@ -0,0 +1,82 @@
# Feature demos
These are recordings and screenshots of Posting's real UI, using the Galaxy
theme and local demo servers. They contain no live credentials or external API
data. The theme slideshow in `../themes/` is unchanged.
## Capture setup
Build Posting from the repository root:
```sh
GOWORK=off go build -o /tmp/posting-readme-bin ./cmd/posting
```
Run `python3 demo/server.py` and `go run ./examples/grpc` in separate terminals.
Use a disposable copy of `demo/sample-api` for the HTTP demos, with the `local`
environment selected. The GraphQL endpoint returns a canned `GetUser` response;
it is not a general-purpose GraphQL server. The gRPC demos use the real service
and collection in `examples/grpc`.
The captures use Terma v0.26.0's `cmd/terma-browser` launcher, which runs Posting
in a PTY inside an xterm.js terminal:
```sh
GOWORK=off go install github.com/darrenburns/terma/cmd/terma-browser@v0.26.0
POSTING_THEME=galaxy POSTING_HEADING__HOSTNAME=you@devbox \
TERMA_DISABLE_PIXEL_MOUSE=1 terma-browser -port 8750 -- \
/tmp/posting-readme-bin --collection /path/to/sample-api-copy -e local
```
Open the URL printed by the launcher. Set `cols` and `rows` query parameters
before its authentication fragment. Use **100 × 32 cells** for the recordings
and **64 × 36 cells**, with the sidebar hidden (`Ctrl+H`), for both stills.
For gRPC, launch a second instance with `--collection examples/grpc/collection`
and no environment flag.
Load JetBrains Mono 2.304 regular, bold, italic and bold italic explicitly into
the browser, disable ligatures, and set the terminal font to 16px. Wait for all
four font faces with `document.fonts.load` and `document.fonts.ready`; verify
that `iiii`, `WWWW` and `0000` each measure 38.4px. Hide the launcher's web
header and terminal padding, and capture just the terminal at **2× scale**.
The resulting recordings are 1920 × 1344px; the stills are 1228 × 1512px.
## Scenes
- **Jump mode:** start with List users and Get order open and sent. Search for
`post users` with `Ctrl+G`, open Create user, clear the search and send it.
Use `Ctrl+O` and the displayed label to focus a new header name. Type `Acce`,
accept `Accept`, then enter `application/json`. Jump to the response body,
pausing after the first character of its two-character label.
- **Mouse:** switch between Get order and List users, drag the horizontal
divider upwards, scroll the response, then drag to select Katherine Johnson's
name. Record the real moving pointer, not an added animation.
- **Responses:** expand List users' response with `Alt+Z`, find `role` with
`Ctrl+F` and advance a match. Press `Escape`, then `t` for the JSON tree.
Collapse the root with `Home`, `Left`, then expand with `Right`. Focus
JSONPath with `Ctrl+F`, paste `$.users[?@.role=="admin"]`, and press `Enter`.
The result contains Ada's complete object and shows **1 match**.
- **gRPC:** open Bidi chat, focus Method to discover the schema, then open the
stream with `Alt+J`. Send `Hello from Posting!`, `Still streaming`, and
`One more message`, editing the message between sends. Capture the three
replies while the status is still **Streaming**.
- **GraphQL:** open Get user in `graphql/`, send it, and keep both the query
and successful JSON response visible.
## GIF encoding
Record at 2× scale, then encode at 12 fps without resizing. Use two passes to
avoid buffering every full-resolution frame in memory:
```sh
ffmpeg -i scene.mp4 -vf 'fps=12,palettegen=stats_mode=diff' \
-frames:v 1 palette.png
ffmpeg -i scene.mp4 -i palette.png \
-lavfi 'fps=12[x];[x][1:v]paletteuse=dither=none:diff_mode=rectangle' \
-loop 0 scene.gif
gifsicle -O3 --lossy=30 scene.gif -o scene-optimized.gif
```
Inspect the encoded animations, including intermediate jump labels and tree
states, before replacing the README assets. Check the Markdown at desktop and
narrow widths; GitHub makes each image a link to its full-resolution version.
Binary file not shown.

After

Width:  |  Height:  |  Size: 145 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 185 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 MiB