mirror of
https://github.com/darrenburns/posting.git
synced 2026-10-16 15:34:25 +08:00
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:
@@ -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
|
||||
@@ -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":
|
||||
|
||||
@@ -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 |
Reference in New Issue
Block a user