https://github.com/beyondlex/poste
https://github.com/beyondlex/poste
Last synced: about 1 month ago
JSON representation
- Host: GitHub
- URL: https://github.com/beyondlex/poste
- Owner: beyondlex
- Created: 2026-05-29T01:44:11.000Z (about 2 months ago)
- Default Branch: main
- Last Pushed: 2026-06-12T08:18:19.000Z (about 1 month ago)
- Last Synced: 2026-06-12T09:22:49.483Z (about 1 month ago)
- Language: Lua
- Size: 1.21 MB
- Stars: 1
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Agents: AGENTS.md
Awesome Lists containing this project
README
# Poste
**Send requests from files. Keyboard-first. Multi-protocol.**
A Neovim plugin and Rust CLI for executing HTTP, Redis, SQL (PostgreSQL / MySQL / SQLite) requests from plain text files. Inspired by JetBrains HTTP Client, with focus on keyboard-driven workflows and dataset manipulation.
## Features
- **File-based requests** — Define requests in `.http`/`.rest`, `.sql`, `.sqlite`, `.redis`, `.mongo` files
- **Environment variables** — JetBrains-style `env.json` with `{{var}}` substitution
- **Named connections** — `connections.json` for database credentials; supports env var references
- **Keyboard-first** — Execute at cursor, navigate results with Vim keys, never leave home row
- **Multi-protocol** — HTTP, Redis, PostgreSQL, MySQL, SQLite (MongoDB/AMQP stubs)
- **SQL dataset buffer** — Paginated results, cell navigation (hjkl), vim-style search/filter, sorting, inline editing
- **Dataset manipulation** — Edit cells inline, generate DML (INSERT/UPDATE/DELETE) from changes, commit with transaction support
- **Data import/export** — CSV, JSON, SQL INSERT statements
- **DB browser** — Tree-view of schemas, tables, columns; generate SELECT/DESCRIBE queries; DDL table operations
- **Completion** — HTTP methods/headers/values (nvim-cmp or blink.cmp); SQL keywords/identifiers/columns (blink.cmp)
- **Assertions & scripts** — Inline `> {% ... %}` assertions, pre/post-request scripts
- **Request chaining** — `{{RequestName.res.body.X}}` to extract values from prior responses
## Quick Start
### Install
```lua
-- lazy.nvim
{
"beyondlex/poste",
dependencies = {
"saghen/blink.cmp",
"stevearc/dressing.nvim",
"beyondlex/finder",
},
config = function()
require("poste").setup()
end,
}
```
```bash
# Rust CLI (optional — for standalone execution or to enable context-aware features)
cargo install --path crates/poste-cli
```
### Create a request file
`requests/api.http`:
```http
### List users
GET {{api_base}}/users
Authorization: Bearer {{api_token}}
### Create user
POST {{api_base}}/users
Content-Type: application/json
{"name": "John", "email": "john@test.com"}
```
`requests/queries.sql`:
```sql
-- @connection pg-dev
SELECT * FROM users WHERE active = true;
```
`requests/cache.redis`:
```redis
# @connection redis://localhost:6379
### Get user session
GET session:user:42
### Set cache
SET post:latest "active"
EXPIRE post:latest 3600
```
### Define environments
`env.json` (walk-up discovery from file directory):
```json
{
"dev": {
"api_base": "http://localhost:8080",
"api_token": "dev-token-xxx",
"db_host": "127.0.0.1",
"db_port": "5432",
"db_user": "app_user",
"db_pass": "local-pass"
},
"prod": {
"api_base": "https://api.example.com",
"api_token": "prod-token-xxx"
}
}
```
### Define connections
`connections.json` (walk-up discovery; supports `{{var}}`):
```json
{
"pg-dev": {
"dialect": "postgres",
"host": "{{db_host}}",
"port": "{{db_port}}",
"database": "myapp",
"user": "{{db_user}}",
"password": "{{db_pass}}"
},
"my-blog": {
"dialect": "mysql",
"host": "localhost",
"port": 3306,
"database": "blog",
"user": "root",
"password": ""
}
}
```
### Execute
In Neovim, open any supported file. With cursor on a request block, press `` to execute. Results open in a side panel.
Default keymaps →
### Source buffer (`.http`, `.sql`, `.redis`)
| Key | Action |
|-----|--------|
| `` | Execute request at cursor |
| `]]` / `[[` | Jump next/previous block |
| `gd` | Go to definition |
| `grr` | Go to references |
| `gs` | Symbol outline (Telescope fallback to `vim.ui.select`) |
| `rp` | Paste curl from clipboard |
| `rc` | Copy request as curl |
### HTTP response buffer
| Key | Action |
|-----|--------|
| `q` | Close |
| `B` / `I` | View Body / Verbose |
| `A` / `S` | View Assertions / Script logs |
| `` / `` | Next/previous tab |
### SQL source buffer (additional)
| Key | Action |
|-----|--------|
| `K` | Show DDL for table under cursor |
| `db` | Toggle DB browser |
| `cr` | Clear filter/search in dataset |
| `` | Trigger completion (i mode) |
### SQL dataset buffer
| Key | Action |
|-----|--------|
| `q` | Close |
| `h`/`j`/`k`/`l` | Move cell left/down/up/right |
| `0`/`$` | First/last column |
| `gg`/`G` | First/last row |
| `H`/`L` | Previous/next page |
| `K` | Preview cell content in float |
| `yy` / `yc` | Yank cell / yank column |
| `s` | Sort by current column (toggle asc/desc) |
| `zh` | Toggle cell highlight |
| `zH` | Toggle header float |
| `zN` | Toggle row numbers |
| `R` | Re-run query |
| ``/`` | Next/previous result tab |
| `n`/`N` | Next/previous search match |
| `/` | Search |
| `cr` | Clear search/filter |
| `fc` | Find column |
| `ce` | Filter by current cell |
| `hh`/`ll` | First/last page |
| `pa` | Toggle pagination |
| `gp` | Toggle raw mode |
| `i` / `a` | Enter edit mode (insert/append) |
| `dd` | Delete row |
| `o` / `O` | Insert row below/above |
| `u` | Undo edit |
| `w` / `:W` | Commit changes (generate & execute DML) |
| `ec` | Export as CSV |
| `ej` | Export as JSON |
| `es` | Export as SQL INSERT |
### DB browser
| Key | Action |
|-----|--------|
| `` | Toggle node expand/collapse |
| `x` | Open context menu (node-specific actions) |
| `r` | Refresh node |
| `/` | Search filter |
| `s` | Generate SELECT * query |
| `d` | Generate DESCRIBE query |
| `q` | Close |
| `ma`/`mr`/`md`/`mt` | Table ops: add/rename/drop/alter column |
### Commands
| Command | Description |
|---------|-------------|
| `:PosteRun` | Execute request at cursor |
| `:PosteEnv [name]` | Switch or show current environment |
| `:PostePasteCurl` | Paste curl from clipboard |
| `:PosteCopyAsCurl` | Copy request as curl |
| `:PosteCmpStatus` | Show HTTP completion status |
| `:PosteSQLCmpStatus` | Show SQL completion status |
| `:PosteImport ` | Import data from CSV/JSON file into dataset |
| `:PosteExport {csv\|json\|sql}` | Export current dataset |
## Configuration
```lua
require("poste").setup({
-- Binary path (default: stdpath("data")/poste/bin/poste)
poste_binary = vim.fn.stdpath("data") .. "/poste/bin/poste",
-- Default environment
default_env = "dev",
-- Response window
split_direction = "vertical", -- "vertical" | "horizontal"
split_size = 80, -- columns (vertical) or rows (horizontal)
-- Log file (set to "" to disable)
log_file = vim.fn.stdpath("cache") .. "/poste.log",
-- Customize keymaps — set to false to disable
keymaps = {
source_buffer = {
run = "",
jump_next = "]]",
jump_prev = "[[",
goto_definition = "gd",
goto_references = "grr",
quickfix_next = "]q",
quickfix_prev = "[q",
paste_curl = "rp",
copy_as_curl = "rc",
show_symbols = "gs",
},
http_response = {
close = "q",
view_body = "B",
view_verbose = "I",
view_assertions = "A",
view_script_logs = "S",
next_tab = "",
prev_tab = "",
},
sql_source = {
run = "",
show_ddl = "K",
clear_filter = "cr",
toggle_db_browser = "db",
trigger_completion = "",
},
sql_dataset = {
close = "q",
move_left = "h", move_down = "j", move_up = "k", move_right = "l",
prev_page = "H", next_page = "L",
first_col = "0", last_col = "$",
first_row = "gg", last_row = "G",
preview_cell = "K",
yank_cell = "yy", yank_column = "yc",
sort_column = "s",
toggle_cell_highlight = "zh",
toggle_header_float = "zH",
toggle_row_numbers = "zN",
toggle_raw_mode = "gp",
next_tab = "", prev_tab = "",
rerun = "R",
goto_first_page = "hh", goto_last_page = "ll",
toggle_pagination = "pa",
find_column = "fc", filter_by_cell = "ce",
show_search = "/", clear_filter_search = "cr",
next_search = "n", prev_search = "N",
-- Editing
edit_insert = "i",
edit_append = "a",
edit_delete_row = "dd",
edit_insert_row_above = "O",
edit_insert_row_below = "o",
edit_undo = "u",
edit_commit = "w",
-- Export
export_csv = "ec",
export_json = "ej",
export_sql = "es",
},
sql_table_ops = {
select_all = "ma",
refresh_all = "mr",
describe_all = "md",
toggle_menu = "mt",
},
db_browser = {
toggle_node = "",
context_menu = "x",
refresh_node = "r",
search_filter = "/",
select_query = "s",
describe_query = "d",
close = "q",
},
introspect_float = {
close = "q",
close_alt = "",
},
},
-- Override highlight group colors
highlights = {
-- Example: change HTTP method colors
-- PosteMethodGET = { fg = "#00ff00", bold = true },
-- PosteMethodPOST = { fg = "#ffff00", bold = true },
-- PosteMethodDELETE = { fg = "#ff0000", bold = true },
--
-- Example: customize SQL dataset look
-- PosteSqlHeader = { fg = "#ff8800", bold = true },
-- PosteSqlCellSelected = { bg = "#334455", fg = "#ffffff", bold = true },
},
})
```
Full list of highlight groups you can override: `PosteLatency`, `PosteSpinner`, `PosteSuccess`, `PosteError`, `PosteSeparator`, `PosteRequestName`, `PosteVarRef`, `PosteMagicVar`, `PosteMethodGET[...]`
## Completion
Poste provides context-aware completions.
### HTTP (`.http`/`.rest`)
- **HTTP methods** — `GET`, `POST`, `PUT`, `DELETE`, etc.
- **Header names** — `Content-Type`, `Authorization`, `Accept-Encoding`, etc.
- **Header values** — `application/json`, `Bearer `, `gzip`, etc.
- **Variables / env vars** — `{{...}}` references from env.json
Works with both **nvim-cmp** and **blink.cmp**. Registration is automatic.
### SQL (`.sql`/`.sqlite`)
- **SQL keywords** — `SELECT`, `FROM`, `WHERE`, `JOIN`, etc.
- **Tables, columns, schemas** — introspected from your database
- **Functions** — aggregate and scalar functions per dialect
- **Connection-aware** — completions reflect the actual schema
Requires **blink.cmp**. Auto-registers as `poste_sql` source provider.
```vim
:PosteCmpStatus " HTTP completion status
:PosteSQLCmpStatus " SQL completion status
```
## SQL Features
### Connection management
Connections are defined in `connections.json` (walked up from the SQL file). Reference them in your `.sql` files:
```sql
-- @connection pg-dev
-- @connection my-blog
```
The `USE database;` statement switches the active database for parsing/completion context.
### Dataset buffer
Query results render in a rich dataset buffer with:
- **Cell navigation** — hjkl to move between cells
- **Sorting** — press `s` on any column
- **Search & filter** — `/` for search, `ce` to filter by cell value
- **Pagination** — configurable page size, `pa` to toggle
- **Multi-result tabs** — each statement gets its own tab, ``/`` to switch
- **Raw mode** — `gp` to toggle compact view
### Dataset editing
Inline editing directly in the dataset buffer:
- **Enter edit mode** — `i` to insert before cursor, `a` to append after
- **Edit cells** — Type to modify, `` to exit edit, `` to confirm
- **Manage rows** — `dd` to delete, `o`/`O` to insert below/above
- **Undo changes** — `u` to undo edits (before commit)
- **Generate & commit DML** — `w` or `:W` to auto-generate UPDATE/INSERT/DELETE statements and execute with transaction
### DB Browser
Press `db` in a SQL file to open the database tree browser. Navigate schemas, tables, and columns. Press `s` to generate a `SELECT *` query or `d` for `DESCRIBE`.
### Data import/export
**Export current dataset:**
- `ec` — CSV (RFC 4180 compliant)
- `ej` — JSON (array of objects)
- `es` — SQL INSERT statements (dialect-aware)
**Import data:**
- `:PosteImport ` — Load CSV/JSON data into a new result tab
### SQL Integration Tests
```bash
# Start test databases (PG 16 on 15432, MySQL 8.0 on 13306)
cd tests/sql && docker compose up -d
# Run queries
cargo run -- run tests/sql/queries/postgres.sql --line 4 --env dev
# Run Lua tests
tests/run.sh
```
## CLI
```bash
# Execute a specific request by line number
poste run requests/api.http --line 4 --env dev
# Introspect database schema
poste introspect --connection pg-dev --env dev
# List available connections
poste connection list --env dev
```
## Architecture
```
poste/
├── crates/
│ ├── poste-core/ # Request parsing, SQL parsing, env management (no I/O)
│ ├── poste-exec/ # Protocol execution, SQL connection/dialect, response
│ └── poste-cli/ # CLI binary (poste run / connection / introspect)
├── lua/
│ └── poste/
│ ├── http/ # HTTP protocol handling
│ └── sql/ # SQL protocol handling (buffer, editor, export, import, etc.)
└── tests/
├── run.sh # Lua tests
└── sql/ # Docker Compose + SQL integration tests
```
## Development Status
**Progress: 34/38 steps completed** (~90%)
| Phase | Description | Status |
|-------|-------------|--------|
| **1A** | Rust infrastructure | ✅ Complete |
| **1B** | Lua dataset panel | ✅ Complete |
| **1C** | MySQL/SQLite executors | ✅ Complete |
| **2** | Connection & context management | ✅ Complete |
| **3** | DB structure browser | ✅ Complete |
| **4** | Table operations + DDL + completion | ✅ Complete |
| **5** | Import/export + pagination | ✅ Complete |
| **6** | Advanced features (editor, transactions) | ✅ Complete |
**Tests:** 300+ passing (230 Rust + 70 Lua)
## License
MIT