# Technical Documentation: darrenburns/posting
> ℹ️ **Provenance:** Hybrid Fusion: `darrenburns/posting` (README + 10 In-Tree Chapters) · [CodeWiki Reference](https://codewiki.google/github.com/darrenburns/posting) · Recency: Active (< 180 days)
## 1. Project Overview & Quickstart (darrenburns/posting)
# Posting
**A powerful HTTP client that lives in your terminal.**
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.
Some notable features include:
- "jump mode" navigation
- environments/variables
- autocompletion
- syntax highlighting using tree-sitter
- Vim keys
- customizable keybindings
- user-defined themes
- run Python code before and after requests
- extensive configuration
- open in $EDITOR/$PAGER
- import curl commands by pasting them into the URL bar
- export requests as cURL commands
- import from Postman and OpenAPI specs
- a command palette for quickly accessing functionality
Visit the [website](https://posting.sh) for more information, the roadmap, and the user guide.
## Installation
Posting can be installed via [uv](https://docs.astral.sh/uv/getting-started/installation/) on MacOS, Linux, and Windows.
```bash
# quickly install uv on MacOS/Linux
curl -LsSf https://astral.sh/uv/install.sh | sh
# install Posting (will also quickly install Python 3.13 if needed)
uv tool install --python 3.13 posting
```
Now you can run Posting via the command line:
```bash
posting
```
Homebrew and NixOS are not officially supported at the moment.
### Prefer `pipx`?
If you'd prefer to use `pipx`, that works too: `pipx install posting`.
## Contributing
Contributions are welcome! See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines, information on setting up your development environment, and running tests.
## Learn More
Learn more about Posting at [https://posting.sh](https://posting.sh).
Posting was built with [Textual](https://github.com/textualize/textual).
## 2. In-Tree Documentation Chapters (darrenburns/posting)
## File: README.md
# Posting
**A powerful HTTP client that lives in your terminal.**
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.
Some notable features include:
- "jump mode" navigation
- environments/variables
- autocompletion
- syntax highlighting using tree-sitter
- Vim keys
- customizable keybindings
- user-defined themes
- run Python code before and after requests
- extensive configuration
- open in $EDITOR/$PAGER
- import curl commands by pasting them into the URL bar
- export requests as cURL commands
- import from Postman and OpenAPI specs
- a command palette for quickly accessing functionality
Visit the [website](https://posting.sh) for more information, the roadmap, and the user guide.
## Installation
Posting can be installed via [uv](https://docs.astral.sh/uv/getting-started/installation/) on MacOS, Linux, and Windows.
```bash
# quickly install uv on MacOS/Linux
curl -LsSf https://astral.sh/uv/install.sh | sh
# install Posting (will also quickly install Python 3.13 if needed)
uv tool install --python 3.13 posting
```
Now you can run Posting via the command line:
```bash
posting
```
Homebrew and NixOS are not officially supported at the moment.
### Prefer `pipx`?
If you'd prefer to use `pipx`, that works too: `pipx install posting`.
## Contributing
Contributions are welcome! See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines, information on setting up your development environment, and running tests.
## Learn More
Learn more about Posting at [https://posting.sh](https://posting.sh).
Posting was built with [Textual](https://github.com/textualize/textual).
---
## File: docs/guide/collections.md
## Overview
A *collection* is just a directory on your file system which may or may not contain requests in the `.posting.yaml` format.
There's absolutely nothing special about a collection.
It contains no "special files" or metadata -- it's just a directory.
It could even be empty.
"Collection" is simply the name we give to the directory which we've loaded into Posting.
## The collection browser
Posting displays the currently open collection in the sidebar.
This is called the *collection browser*.
{ height=300px }
The name of the currently open collection is displayed in the bottom right corner of the collection browser.
In the example above, the collection is named "sample-collection".
You can navigate this sidebar using the keyboard or mouse.
Open a request by clicking on it or pressing ++enter++ while it has focus,
and it'll be loaded into the main body of the UI.
A marker will also appear to the left of the request's title, indicating that the request is open.
A save operation will overwrite the currently open request.
!!! example "Keyboard shortcuts"
The collection browser supports various keyboard shortcuts for quick navigation. For example ++shift+j++ and ++shift+k++ can be used to jump through sub-collections.
Press ++f1++ while the browser has focus to view the full list of shortcuts.
The collection browser can be moved to the left or right side of the screen by setting the `collection_browser.position` configuration option
to either `"left"` or `"right"`.
## The default collection
If you launch Posting without a `--collection` argument, it will load the *default collection*, which is stored in Posting's reserved data directory on your file system.
The default collection can be thought of as a *system wide collection*.
It's a place to keep useful requests that you can easily access from anywhere, without having to manually specify a `--collection` argument.
You can check where this is by running `posting locate collection`.
The default collection is named "default", that name will be displayed in the bottom right corner of the collection browser.
This is useful to get started quickly, but you'll probably want to create your own collection directory and load it instead.
This makes it easier to organize your requests and check them into version control.
## Creating a collection
A collection is just a directory, so you can create a collection by simply creating an empty directory anywhere on your file system.
With the directory created, it's time to load it into Posting...
## Loading a collection
If you want to load a collection, you can do so by passing the path to the collection directory to Posting:
```bash
posting --collection path/to/collection
```
### Example
To open a collection (a directory containing requests), use the `--collection` option:
```bash
posting --collection path/to/collection
```
This will recursively find and display requests in the sidebar.
If you don't supply a directory, Posting will use the default collection directory.
You can check where the default collection is by running `posting locate collection`.
---
## File: docs/guide/command_palette.md
## Overview
The *command palette* is a way to search for and execute commands in Posting.
Some functionality in Posting can only be accessed through the command palette.
It can be used to switch themes, show/hide parts of the UI, and more.
### Using the command palette
Press ++ctrl+p++ to open the command palette.
---
## File: docs/guide/configuration.md
## Overview
Posting can be configured using a configuration file, environment variables, and/or `.env` files.
Configuration values are loaded in the following order of precedence (highest to lowest):
1. Configuration file
2. Environment variables
3. `.env` files
## Configuration file
You can write configuration for Posting using YAML.
The location of the config file can be checked using the command `posting locate config`.
Here's an example configuration file:
```yaml
theme: galaxy
layout: horizontal
response:
prettify_json: false
heading:
visible: true
show_host: false
```
## Environment variables
All configuration values can also be set as environment variables.
Simply prefix the name of the config with `POSTING_` and set it as an environment variable.
For nested configuration values, use `__` as the delimiter. So to set `heading.visible` to `false`, you can set the environment variable `POSTING_HEADING__VISIBLE=false`.
For example, to set the theme to `galaxy`, you can set the environment variable `POSTING_THEME=galaxy`.
### dotenv (`.env`) files
Posting also supports `.env` (dotenv) files, which are useful if you want to swap out environment variable values depending on the environment you're working in (for example, "dev" vs "prod").
You can tell Posting to use a `.env` file using the `--env` option.
This option can be supplied multiple times to load multiple `.env` files.
Here's an example `.env` file:
```bash
POSTING_THEME="cobalt"
POSTING_LAYOUT="vertical"
POSTING_HEADING__VISIBLE="false"
```
Dotenv files are separate from collections, although you may wish to include them inside a collection to make it easy to version and share with others.
## Configuring SSL
Posting verifies SSL certificates by default using the CA bundle provided by the `certifi` package.
### SSL certificate configuration
Posting can load custom CA bundles from a `.pem` file.
The easiest way to do this is in your `config.yaml` file:
```yaml
ssl:
ca_bundle: 'absolute/path/to/certificate.pem'
```
### Environment-specific certificates
If the required CA bundle differs per environment, you can again use the principle that all configuration can be set as environment variables which can optionally be set and loaded using `--env` and `.env` files:
```bash
# dev.env
POSTING_SSL__CA_BUNDLE='/path/to/certificate.pem'
```
Now load the `dev.env` file when working in the `dev` environment to ensure the dev environment CA bundle is used:
```bash
posting --env dev.env
```
### Disabling SSL verification
SSL verification can be disabled on a per-request basis in the "Options" tab.
### Client-side certificates
You can specify local certificates to use as a client-side certificate:
```yaml
ssl:
certificate_path: /path/to/certificate.pem
key_file: /path/to/key.key # optional
password: '***********' # optional password for key_file
```
## Full configuration reference
The table below lists all available configuration options and their environment variable equivalents, their default values, and descriptions.
| Config Key (Env Var) | Values (Default) | Description |
|----------------------|------------------|-------------|
| `theme` (`POSTING_THEME`) | See the list of themes in the command palette (Default: `"galaxy"`) | Sets the theme of the application. |
| `load_user_themes` (`POSTING_LOAD_USER_THEMES`) | `true`, `false` (Default: `true`) | If enabled, load user themes from the theme directory, allowing them to be specified in config and selected via the command palette. |
| `load_builtin_themes` (`POSTING_LOAD_BUILTIN_THEMES`) | `true`, `false` (Default: `true`) | If enabled, load builtin themes, allowing them to be specified in config and selected via the command palette. |
| `theme_directory` (`POSTING_THEME_DIRECTORY`) | (Default: `${XDG_DATA_HOME}/posting/themes`) | The directory containing user themes. |
| `layout` (`POSTING_LAYOUT`) | `"vertical"`, `"horizontal"` (Default: `"horizontal"`) | Sets the layout of the application. |
| `use_host_environment` (`POSTING_USE_HOST_ENVIRONMENT`) | `true`, `false` (Default: `false`) | Allow/deny using environment variables from the host machine as variables in requests (using the standard `$` syntax). When disabled, only variables defined explicitly in `.env` files will be available for use. |
| `watch_env_files` (`POSTING_WATCH_ENV_FILES`) | `true`, `false` (Default: `true`) | If enabled, automatically reload environment files when they change. |
| `watch_themes` (`POSTING_WATCH_THEMES`) | `true`, `false` (Default: `true`) | If enabled, automatically reload themes in the theme directory when they change on disk. |
| `watch_collection_files` (`POSTING_WATCH_COLLECTION_FILES`) | `true`, `false` (Default: `true`) | If enabled, automatically reload collection files when they change on disk. Right now, this is limited to reloading Python scripts in the collection. |
| `animation` (`POSTING_ANIMATION`) | `"none"`, `"basic"`, `"full"` (Default: `"none"`) | Controls the animation level. |
| `response.prettify_json` (`POSTING_RESPONSE__PRETTIFY_JSON`) | `true`, `false` (Default: `true`) | If enabled, JSON responses will be pretty-formatted. |
| `response.show_size_and_time` (`POSTING_RESPONSE__SHOW_SIZE_AND_TIME`) | `true`, `false` (Default: `true`) | If enabled, the size and time taken for the response will be displayed in the response area border subtitle. |
| `heading.visible` (`POSTING_HEADING__VISIBLE`) | `true`, `false` (Default: `true`) | Show/hide the app header. |
| `heading.show_host` (`POSTING_HEADING__SHOW_HOST`) | `true`, `false` (Default: `true`) | Show/hide the hostname in the app header. |
| `heading.show_version` (`POSTING_HEADING__SHOW_VERSION`) | `true`, `false` (Default: `true`) | Show/hide the version in the app header. |
| `heading.hostname` (`POSTING_HEADING__HOSTNAME`) | (Default: `unset`) | The hostname to display in the app header. You may use Rich markup here. If unset, the hostname provided via `socket.gethostname()` will be used. |
| `url_bar.show_value_preview` (`POSTING_URL_BAR__SHOW_VALUE_PREVIEW`) | `true`, `false` (Default: `true`) | Show/hide the variable value preview below the URL bar. |
| `url_bar.hide_secrets_in_value_preview` (`POSTING_URL_BAR__HIDE_SECRETS_IN_VALUE_PREVIEW`) | `true`, `false` (Default: `true`) | If enabled, values will be redacted in the value preview when the variable name contains the word `secret` or `key` or `password` or `token`. |
| `collection_browser.position` (`POSTING_COLLECTION_BROWSER__POSITION`) | `"left"`, `"right"` (Default: `"left"`) | The position of the collection browser on screen. |
| `collection_browser.show_on_startup` (`POSTING_COLLECTION_BROWSER__SHOW_ON_STARTUP`) | `true`, `false` (Default: `true`) | Show/hide the collection browser on startup. Can always be toggled using the command palette. |
| `pager` (`POSTING_PAGER`) | (Default: `$PAGER`) | Command to use for paging text. |
| `pager_json` (`POSTING_PAGER_JSON`) | (Default: `$PAGER`) | Command to use for paging JSON. |
| `editor` (`POSTING_EDITOR`) | (Default: `$EDITOR`) | Command to use for opening files in an external editor. |
| `ssl.ca_bundle` (`POSTING_SSL__CA_BUNDLE`) | Absolute path (Default: `unset`) | Absolute path to a CA bundle file/dir. If not set, the [Certifi](https://pypi.org/project/certifi/) CA bundle will be used. |
| `ssl.certificate_path` (`POSTING_SSL__CERTIFICATE_PATH`) | Absolute path (Default: `unset`) | Absolute path to a client SSL certificate file or directory. |
| `ssl.key_file` (`POSTING_SSL__KEY_FILE`) | Absolute path (Default: `unset`) | Absolute path to a client SSL key file. |
| `ssl.password` (`POSTING_SSL__PASSWORD`) | Password for the key file. (Default: `unset`) | Password to decrypt the key file if it's encrypted. |
| `focus.on_startup` (`POSTING_FOCUS__ON_STARTUP`) | `"url"`, `"method", "collection"` (Default: `"url"`) | Automatically focus the URL bar, method, or collection browser when the app starts. |
| `focus.on_response` (`POSTING_FOCUS__ON_RESPONSE`) | `"body"`, `"tabs"` (Default: `unset`)| Automatically focus the response tabs or response body text area when a response is received. |
| `focus.on_request_open` (`POSTING_FOCUS__ON_REQUEST_OPEN`) | `"headers"`, `"body"`, `"query"`, `"info"`, `"url"`, `"method"` (Default: `unset`) | Automatically focus the specified target when a request is opened from the collection browser. |
| `text_input.blinking_cursor` (`POSTING_TEXT_INPUT__BLINKING_CURSOR`) | `true`, `false` (Default: `true`) | If enabled, the cursor will blink in input widgets and text area widgets. |
| `command_palette.theme_preview` (`POSTING_COMMAND_PALETTE__THEME_PREVIEW`) | `true`, `false` (Default: `false`) | If enabled, the command palette will display a preview of the selected theme when the cursor is over it. This will slow down cursor movement and so is disabled by default. |
| `use_xresources` (`POSTING_USE_XRESOURCES`) | `true`, `false` (Default: `false`) | Try to create themes called `xresources-dark` and `xresources-light` (see the section below) |
| `curl_export_extra_args` (`POSTING_CURL_EXPORT_EXTRA_ARGS`) | (Default: `""`) | Extra arguments to pass to curl when exporting a request as a curl command. This string will be inserted directly into the command that gets copied to your clipboard, immediately after `curl `. |
---
## File: docs/guide/environments.md
## Overview
You can use *variables* in input fields and text areas using the `${VARIABLE_NAME}` or `$VARIABLE_NAME` syntax.
These variables will be substituted into outgoing requests.
## Loading variables
Variables are stored in `.env` files, and loaded using the `--env` option.
Here's what a `.env` file might look like:
```bash
# file: dev.env
API_KEY="dev-api-key"
ENV_NAME="dev"
BASE_URL="https://${ENV_NAME}.example.com"
```
To make these variables available in the UI, you can load them using the `--env` option:
```bash
posting --env dev.env
```
You can load multiple `.env` files by specifying the `--env` option multiple times:
```bash
posting --env dev.env --env shared.env
```
This allows you to build up a set of variables which are common to all environments, and then override them for specific environments.
## Autoloading `.env` files
If no `--env` options are provided, Posting will automatically load a `posting.env` file in the current working directory if it exists.
## Using environment variables
By default, Posting will only use variables defined in `.env` files that have been explicitly loaded using the `--env` option.
If you want to permit using environment variables that exist on the host machine (i.e. those which are not defined in any `.env` files), you must set the `use_host_environment` config option to `true` (or set the environment variable `POSTING_USE_HOST_ENVIRONMENT=true`).
## Practical example
Imagine you're testing an API which exists in both `dev` and `prod` environments.
The `dev` and `prod` environments share some common variables, but differ in many ways too.
We can model this by having a single `shared.env` file which contains variables which are shared between environments, and then a `dev.env` and `prod.env` file which contain environment specific variables.
```bash
# file: shared.env
API_PATH="/api/v1"
ENV_NAME="shared"
# file: dev.env
API_KEY="dev-api-key"
ENV_NAME="dev"
BASE_URL="https://${ENV_NAME}.example.com"
# file: prod.env
API_KEY="prod-api-key"
ENV_NAME="prod"
BASE_URL="https://${ENV_NAME}.example.com"
```
When working in the `dev` environment, you can then load all of the shared variables and all of the development environment specific variables using the `--env` option:
```bash
posting --env shared.env --env dev.env
```
This will load all of the shared variables from `shared.env`, and then load the variables from `dev.env`. Since `ENV_NAME` appears in both files, the value from the `dev.env` file will be used since that was the last one specified.
Note that you do *not* need to restart to load changes made to these files,
so you can open and edit your env files in an editor of your choice alongside Posting.
### Environment specific config
Since all Posting configuration options can also be specified as environment variables, we can also put environment specific config inside `.env` files. There's a dedicated "Configuration" section in this document which covers this in more detail.
For example, if you wanted to use a light theme in the prod environment (as a subtle reminder that you're in production!), you could set the environment variable `POSTING_THEME=solarized-light` inside the `prod.env` file.
Note that configuration files take precedence over environment variables, so if you set a value in both a `.env` file and a `config.yaml`, the value from the `config.yaml` file will be used.
---
## File: docs/guide/external_tools.md
## Overview
You can quickly switch between Posting and external editors and pagers.
For example, you could edit request bodies in `vim`, and then browse the JSON response body in `less` or `fx`.
You can even configure a custom pager specifically for browsing JSON.
## External Editors
With a multi-line text area focused, press ++f4++ to open the file in your
configured external editor.
The configured external editor can be set as `editor` in your `config.yaml`
file.
For example:
```yaml title="config.yaml"
editor: vim
```
Alternatively, you can set the `POSTING_EDITOR` environment variable.
```bash
export POSTING_EDITOR=vim
```
If neither is set, Posting will try to use the `EDITOR` environment variable.
!!! tip "Using VSCode or Cursor"
If you want to use VSCode or Cursor, you can set the `POSTING_EDITOR` environment variable to `code -w` or `cursor -w` respectively.
## External Pagers
With a multi-line text area focused, press ++f3++ to open the file in your
configured external pager.
The configured external pager can be set as `pager` in your `config.yaml`
file.
For example:
```yaml title="config.yaml"
pager: less
```
Alternatively, you can set the `POSTING_PAGER` environment variable.
```bash
export POSTING_PAGER=less
```
### JSON Pager
You can use a custom pager for viewing JSON using the `pager_json` setting in
your `config.yaml` file.
For example:
```yaml title="config.yaml"
pager_json: fx
```
Alternatively, you can set the `POSTING_PAGER_JSON` environment variable.
```bash
export POSTING_PAGER_JSON=fx
```
If neither is set, Posting will try to use the default pager lookup rules discussed earlier.
## Exporting to curl
> *Added in Posting 2.4.0*
Open the command palette and select `export: copy as curl`.
This will transform the open request into a cURL command, and copy it to your clipboard.
You can optionally supply extra arguments to pass to curl by setting the `curl_export_extra_args` setting in your `config.yaml` file.
```yaml title="config.yaml"
curl_export_extra_args: "--verbose -w %{time_total} %{http_code}"
```
This will be inserted directly into the command that gets copied to your clipboard, immediately after `curl `,
producing a command like the following:
```bash
curl --verbose -w %{time_total} %{http_code} -X POST ...
```
---
## File: docs/guide/help_system.md
## Overview
Posting has a *built-in help system*, which can be used to get information about the currently focused widget.
### Getting help for the focused widget
With a widget focused, press `f1` to open a help window for that widget.
Most widgets offer more keybindings and functionality than meets the eye, and more than what is shown in the application footer.
The help window explains how to use the focused widget, and lists all of the keybindings offered by it.
---
## File: docs/guide/importing.md
## Overview
Posting supports importing from external sources.
## Importing from curl
!!! example "This feature is experimental."
You can import a curl command by pasting it into the URL bar.
This will fill out the request details in the UI based on the curl command you pasted, overwriting any existing values.
## Importing from OpenAPI
!!! example "This feature is experimental."
Posting can convert OpenAPI 3.x specs into collections.
To import an OpenAPI Specification, use the `posting import path/to/openapi.yaml` command.
You can optionally supply an output directory.
If no output directory is supplied, the default collection directory will be used.
Posting will attempt to build a file structure in the collection that aligns with the URL structure of the imported API.
## Importing from Postman
!!! example "This feature is experimental."
Collections can be imported from Postman.
To import a Postman collection, use the `posting import --type postman path/to/postman_collection.json` command.
You can optionally supply an output directory with the `-o` option.
If no output directory is supplied, the default collection directory will be used (check where this is using `posting locate collection`).
Variables will also be imported from the Postman collection and placed in a `.env` file inside the collection directory.
---
## File: docs/guide/index.md
Posting can be installed in a matter of seconds on MacOS, Linux, and Windows.
## Installation
The recommended method is to use [uv](https://docs.astral.sh/uv/getting-started/installation/), which is a single Rust binary that you can use to install Python apps.
It's significantly faster than alternative tools, and will get you up and running with Posting in seconds.
You don't even need to worry about installing Python yourself - `uv` will manage everything for you.
### uv
Here's how to install Posting using `uv`:
```bash
# quick install on MacOS/Linux
curl -LsSf https://astral.sh/uv/install.sh | sh
# install Posting (will also quickly install Python 3.12 if needed)
uv tool install --python 3.12 posting
# Run posting
posting
```
`uv` can also be installed via Homebrew, Cargo, Winget, pipx, and more. See the [installation guide](https://docs.astral.sh/uv/getting-started/installation/) for more information.
`uv` also makes it easy to install additional Python packages into your Posting environment, which you can then use in your pre-request/post-response scripts.
### pipx
If you prefer, you can install Posting via [`pipx`](https://pipx.pypa.io/stable/).
```bash
pipx install posting
```
---
The methods above will both install Posting globally, in an isolated environment. Do *not* attempt to install Posting with `pip`.
??? failure "Homebrew is not supported"
Installing via Homebrew is not supported, as some of Posting's Rust and C dependencies can take over 10 minutes to compile. When using uv, installation time is measured in milliseconds, and with pipx it's just a few seconds.
## Choose your preferred UI style
Posting comes with two different "spacing" modes: `compact` and `standard`.
The default is `standard` which includes extra padding and borders around content.
`compact` mode removes the padding and borders, and uses a more compact layout.
You can toggle the spacing mode using the `spacing` command from the command palette (++ctrl+p++ then type `spacing`, then press ++enter++).
From this command palette, you can also try out different themes.
To permanently change the spacing mode and/or theme, open the config file (`posting locate config` will tell you where it is) and add the following line(s):
```yaml
spacing: compact
theme:
```
## A quick introduction
This introduction will show you how to create a simple POST request to the [JSONPlaceholder](https://jsonplaceholder.typicode.com/) mock API to create a new user. It focuses on an efficient keyboard-driven workflow, but you can also use the mouse if you prefer.
### Collections and requests
A *collection* is simply a directory which may contain requests saved by Posting.
If you launch Posting without specifying a collection, any requests you create will be saved to the `"default"` collection.
The default collection is a directory reserved by Posting on your filesystem. It's a "global" collection and is not related to the directory you launched Posting from.
This is fine for quick throwaway requests, but you'll probably want to create a new collection for each project you work on so that you can check it into version control.
To create a new collection, simply create a new directory and pass it into Posting.
```bash
mkdir my-collection
posting --collection my-collection
```
Now, any requests you create will be saved in the `my-collection` directory as simple YAML files with the `.posting.yaml` extension.
When Posting opens, you'll see the collection browser on the left side of the screen with `my-collection` displayed at the bottom right corner.
### Setting the request method to POST
When you launch Posting, no request is open, so the UI will look rather empty.
Let's create a simple POST request to the [JSONPlaceholder](https://jsonplaceholder.typicode.com/) mock API to create a new user.
Press ++ctrl+t++ to open the request method dropdown:
The underlined character in each method indicates the key you can press to quickly select that method. We want to send a POST request, so press ++p++ to quickly select the POST method.
### Setting the request URL
You can move focus forward and backward through widgets using ++tab++ and ++shift+tab++ respectively.
So, you can move focus from the method selector to the URL bar by pressing ++tab++ once.
Alternatively, you can immediately move the focus to the URL bar from anywhere in Posting using ++ctrl+l++.
Type `https://jsonplaceholder.typicode.com/users` into the URL bar.
Posting's URL bar highlights parts of the URL as you type, which can be helpful for spotting typos.
It can also autocomplete domains you've previously used, to save you from having to retype them.
For example, if you later want to make a request to `https://jsonplaceholder.typicode.com/posts`, you can simply type "json" into the URL bar and select the URL from the autocomplete menu that appears.
### Adding a JSON body
Press ++ctrl+o++ to enter "jump mode", then press ++w++ to quickly jump to the "Body" tab.
Jump mode is great for quickly moving through the UI without having to press ++tab++ multiple times.
At this point focus is currently on the tab bar itself.
Press ++j++ (or ++down++) to move the cursor down to the dropdown.
Press ++enter++ to open it, then select the option `Raw (json, text, etc.)`.
Move down to the text area below using ++j++ (or ++down++), and type (or paste) the JSON below.
```json
{
"name": "John Doe",
"username": "johndoe",
"email": "john.doe@example.com"
}
```
Note at the bottom right of the text area, JSON is pre-selected as the content type.
This means Posting will automatically use JSON syntax highlighting and it will insert the `Content-Type: application/json` header for you when the request is sent.
### Viewing keyboard shortcuts
Now is probably a good time to note that you can see the full list of keyboard shortcuts for the focused widget by pressing ++f1++. The text area widget in particular has a lot of useful shortcuts and supports things like undo/redo.
!!! tip "Changing keyboard shortcuts"
You can remap keybindings in Posting using [Keymaps](../guide/keymap.md).
### Sending the request
Press ++ctrl+j++ to send the request.
This shortcut works globally.
!!! tip "Keyboard shortcuts"
You may also be able to send the request using ++alt+enter++.
This only works on terminals that support the Kitty keyboard protocol.
### Working with the response
The response will be displayed in the main body of the UI.
Press ++ctrl+o++ to enter "jump mode", and the ++a++ to move to the response `Body` tab.
Press ++j++ or ++down++ to move the cursor down into the response body.
This text area supports a bunch of different keyboard shortcuts for quickly navigating the response body.
Text can be selected by holding ++shift++ and moving the cursor using the arrow keys (or `hjkl` keys for Vim fans).
You can also select text by clicking and dragging with the mouse.
Press ++y++ or ++c++ to copy the selected text to your clipboard.
If no text is selected, the entire response body will be copied.
!!! tip "Vim keys"
The response text area supports some Vim-inspired keyboard shortcuts.
- To select text without holding ++shift++, you can press ++v++ to enter visual mode, and use `hjkl` to navigate.
- If your cursor is at a bracket, you can press ++%++ to jump to the matching bracket.
- Press ++w++ to move the cursor to the next word, and ++b++ to move the cursor to the previous word.
Try experimenting to find out what's supported, and if you're desperately missing something, please start a discussion on [GitHub Discussions](https://github.com/darrenburns/posting/discussions).
You can open the response using the command defined in your `$EDITOR`, `$POSTING_EDITOR`, `$POSTING_PAGER`, or `$POSTING_PAGER_JSON` environment variables.
For example, if you set `$POSTING_PAGER_JSON` to `fx`, then press the corresponding keybind to open the pager when the response text area has focus, the response will be opened in the `fx` JSON viewer.
### Saving the request
Finally, press ++ctrl+s++ to save the request to disk.
Fill out the form on the modal that appears, and press ++enter++ or ++ctrl+n++ to write the request to disk.
!!! tip "Folders"
Requests can be saved to folders - simply include a `/` in the `Path in collection` field when you save the request,
and Posting will create the required directory structure for you.
---
## File: docs/guide/keymap.md
## Overview
As explained in the [Help System](./help_system.md) section, you can view the keybindings for any widget by pressing ++f1++ or ++ctrl+question-mark++ when that widget has focus.
If you wish to use different keybindings, you can do so by editing the `keymap` section of your `config.yaml` file.
Check the location of that file on your system by running `posting locate config` on the command line.
### Changing the keymap
Actions in Posting have unique IDs which map to a keybinding (listed at the bottom of this page).
For any of these IDs, you can change the keybinding by adding an entry to the `keymap` section of your `config.yaml` file:
```yaml
keymap:
:
```
Here's an example of changing the keybinding for the "Send Request" action:
```yaml
keymap:
send-request: ctrl+r
```
After adding the above entry to `config.yaml` and restarting Posting, you'll notice that that the footer of the app now shows `^r` to send a request rather than the default `^j`.
Now you can press `^r` to send a request *instead of* `^j`.
You can also have multiple keys map to the same action by separating them with commas:
```yaml
keymap:
send-request: ctrl+r,ctrl+i
```
Note that by adding an entry to the `keymap` you are overriding the default keybinding for that action, so if you wish to keep the default keybinding, you'll need to specify it again:
```yaml
keymap:
send-request: ctrl+r,ctrl+i,ctrl+j
```
### Key format
Support for keys in the terminal varies between terminals, multiplexers and operating systems.
It's a complex topic, and one that may involve some trial and error.
Some keys might be intercepted before reaching Posting, and your emulator might not support certain keys.
- To specify ++ctrl+x++, use `ctrl+x`.
- To specify ++ctrl+shift+x++, use `ctrl+X` (control plus uppercase "X").
- To specify multiple keys, separate them with commas: `ctrl+shift+left,ctrl+y`.
- To specify a function key, use `f`. For example, ++f1++ would be `f1`.
- To specify `@` (at) use `at` (*not* e.g. ++shift+2++ as this only applies to some keyboard layouts).
- Arrow keys can be specified as `left`, `right`, `up` and `down`.
- `shift` works as a modifier non-printable keys e.g. `shift+backspace`, `shift+enter`, `shift+right` are all acceptable. Support may vary depending on your emulator.
- `alt` also works as a modifier e.g. `alt+enter`.
- `ctrl+enter`, `alt+enter`,`ctrl+backspace`, `ctrl+shift+enter`, `ctrl+shift+space` etc. are supported if your terminal supports the Kitty keyboard protocol.
- Other keys include (but are not limited to) `comma`, `full_stop`, `colon`, `semicolon`, `quotation_mark`, `apostrophe`, `left_bracket`, `right_square_bracket`, `left_square_bracket`, `backslash`, `vertical_line` (pipe |), `plus`, `minus`, `equals_sign`, `slash`, `asterisk`,`tilde`, `percent_sign`.
The only way to know for sure which keys are supported in your particular terminal emulator is to install Textual, run `textual keys`, press the key you want to use, and look at the `key` field of the printed output.
!!! example "Work in progress"
In the future, I hope to make it easier to discover which keys are supported and when key presses they correspond to for a particular environment directly within Posting. This will likely take the form of a CLI command that outputs key names and their corresponding key presses. For now, if you need assistance, please open a discussion on [GitHub](https://github.com/darrenburns/posting/discussions).
### Binding IDs
These are the IDs of the actions that you can change the keybinding for:
- `send-request` - Send the current request. Default: `ctrl+j,alt+enter`.
- `focus-method` - Focus the method selector. Default: `ctrl+t`.
- `focus-url` - Focus the URL input. Default: `ctrl+l`.
- `save-request` - Save the current request. Default: `ctrl+s`.
- `expand-section` - Expand or shrink the section which has focus. Default: `ctrl+m`.
- `toggle-collection` - Toggle the collection browser. Default: `ctrl+h`.
- `new-request` - Create a new request. Default: `ctrl+n`.
- `commands` - Open the command palette. Default: `ctrl+p`.
- `help` - Open the help dialog for the currently focused widget. Default: `f1,ctrl+question_mark`.
- `quit` - Quit the application. Default: `ctrl+c`.
- `jump` - Enter jump mode. Default: `ctrl+o`.
- `open-in-pager` - Open the content of the focused text area in your $PAGER/$POSTING_PAGER/$POSTING_PAGER_JSON. Default: `f3`.
- `open-in-editor` - Open the content of the focused text area in your $EDITOR/$POSTING_EDITOR. Default: `f4`.
- `search-requests` - Go to a request by name. Default: `ctrl+shift+p`.
--- METRICS ---
- Files Extracted: 11
- Estimated Token Budget: ~9436 tokens
- Recency Window: Active (< 180 days)
- Canonical Reference: https://codewiki.google/github.com/darrenburns/posting