{"id":51020860,"url":"https://github.com/beyondlex/poste","last_synced_at":"2026-06-21T16:01:33.518Z","repository":{"id":361057104,"uuid":"1252905588","full_name":"beyondlex/poste","owner":"beyondlex","description":null,"archived":false,"fork":false,"pushed_at":"2026-06-12T08:18:19.000Z","size":1267,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-12T09:22:49.483Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Lua","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/beyondlex.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-05-29T01:44:11.000Z","updated_at":"2026-06-12T08:18:25.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/beyondlex/poste","commit_stats":null,"previous_names":["beyondlex/poste"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/beyondlex/poste","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/beyondlex%2Fposte","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/beyondlex%2Fposte/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/beyondlex%2Fposte/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/beyondlex%2Fposte/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/beyondlex","download_url":"https://codeload.github.com/beyondlex/poste/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/beyondlex%2Fposte/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34616512,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-21T02:00:05.568Z","response_time":54,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-06-21T16:01:32.797Z","updated_at":"2026-06-21T16:01:33.504Z","avatar_url":"https://github.com/beyondlex.png","language":"Lua","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Poste\n\n**Send requests from files. Keyboard-first. Multi-protocol.**\n\nA 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.\n\n## Features\n\n- **File-based requests** — Define requests in `.http`/`.rest`, `.sql`, `.sqlite`, `.redis`, `.mongo` files\n- **Environment variables** — JetBrains-style `env.json` with `{{var}}` substitution\n- **Named connections** — `connections.json` for database credentials; supports env var references\n- **Keyboard-first** — Execute at cursor, navigate results with Vim keys, never leave home row\n- **Multi-protocol** — HTTP, Redis, PostgreSQL, MySQL, SQLite (MongoDB/AMQP stubs)\n- **SQL dataset buffer** — Paginated results, cell navigation (hjkl), vim-style search/filter, sorting, inline editing\n- **Dataset manipulation** — Edit cells inline, generate DML (INSERT/UPDATE/DELETE) from changes, commit with transaction support\n- **Data import/export** — CSV, JSON, SQL INSERT statements\n- **DB browser** — Tree-view of schemas, tables, columns; generate SELECT/DESCRIBE queries; DDL table operations\n- **Completion** — HTTP methods/headers/values (nvim-cmp or blink.cmp); SQL keywords/identifiers/columns (blink.cmp)\n- **Assertions \u0026 scripts** — Inline `\u003e {% ... %}` assertions, pre/post-request scripts\n- **Request chaining** — `{{RequestName.res.body.X}}` to extract values from prior responses\n\n## Quick Start\n\n### Install\n\n```lua\n-- lazy.nvim\n{\n  \"beyondlex/poste\",\n  dependencies = {\n    \"saghen/blink.cmp\",\n    \"stevearc/dressing.nvim\",\n    \"beyondlex/finder\",\n  },\n  config = function()\n    require(\"poste\").setup()\n  end,\n}\n```\n\n```bash\n# Rust CLI (optional — for standalone execution or to enable context-aware features)\ncargo install --path crates/poste-cli\n```\n\n### Create a request file\n\n`requests/api.http`:\n\n```http\n### List users\nGET {{api_base}}/users\nAuthorization: Bearer {{api_token}}\n\n### Create user\nPOST {{api_base}}/users\nContent-Type: application/json\n\n{\"name\": \"John\", \"email\": \"john@test.com\"}\n```\n\n`requests/queries.sql`:\n\n```sql\n-- @connection pg-dev\n\nSELECT * FROM users WHERE active = true;\n```\n\n`requests/cache.redis`:\n\n```redis\n# @connection redis://localhost:6379\n\n### Get user session\nGET session:user:42\n\n### Set cache\nSET post:latest \"active\"\nEXPIRE post:latest 3600\n```\n\n### Define environments\n\n`env.json` (walk-up discovery from file directory):\n\n```json\n{\n  \"dev\": {\n    \"api_base\": \"http://localhost:8080\",\n    \"api_token\": \"dev-token-xxx\",\n    \"db_host\": \"127.0.0.1\",\n    \"db_port\": \"5432\",\n    \"db_user\": \"app_user\",\n    \"db_pass\": \"local-pass\"\n  },\n  \"prod\": {\n    \"api_base\": \"https://api.example.com\",\n    \"api_token\": \"prod-token-xxx\"\n  }\n}\n```\n\n### Define connections\n\n`connections.json` (walk-up discovery; supports `{{var}}`):\n\n```json\n{\n  \"pg-dev\": {\n    \"dialect\": \"postgres\",\n    \"host\": \"{{db_host}}\",\n    \"port\": \"{{db_port}}\",\n    \"database\": \"myapp\",\n    \"user\": \"{{db_user}}\",\n    \"password\": \"{{db_pass}}\"\n  },\n  \"my-blog\": {\n    \"dialect\": \"mysql\",\n    \"host\": \"localhost\",\n    \"port\": 3306,\n    \"database\": \"blog\",\n    \"user\": \"root\",\n    \"password\": \"\"\n  }\n}\n```\n\n### Execute\n\nIn Neovim, open any supported file. With cursor on a request block, press `\u003cCR\u003e` to execute. Results open in a side panel.\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eDefault keymaps →\u003c/b\u003e\u003c/summary\u003e\n\n### Source buffer (`.http`, `.sql`, `.redis`)\n\n| Key | Action |\n|-----|--------|\n| `\u003cCR\u003e` | Execute request at cursor |\n| `]]` / `[[` | Jump next/previous block |\n| `gd` | Go to definition |\n| `grr` | Go to references |\n| `gs` | Symbol outline (Telescope fallback to `vim.ui.select`) |\n| `\u003cleader\u003erp` | Paste curl from clipboard |\n| `\u003cleader\u003erc` | Copy request as curl |\n\n### HTTP response buffer\n\n| Key | Action |\n|-----|--------|\n| `q` | Close |\n| `B` / `I` | View Body / Verbose |\n| `A` / `S` | View Assertions / Script logs |\n| `\u003cTab\u003e` / `\u003cS-Tab\u003e` | Next/previous tab |\n\n### SQL source buffer (additional)\n\n| Key | Action |\n|-----|--------|\n| `K` | Show DDL for table under cursor |\n| `\u003cleader\u003edb` | Toggle DB browser |\n| `\u003cleader\u003ecr` | Clear filter/search in dataset |\n| `\u003cC-Space\u003e` | Trigger completion (i mode) |\n\n### SQL dataset buffer\n\n| Key | Action |\n|-----|--------|\n| `q` | Close |\n| `h`/`j`/`k`/`l` | Move cell left/down/up/right |\n| `0`/`$` | First/last column |\n| `gg`/`G` | First/last row |\n| `H`/`L` | Previous/next page |\n| `K` | Preview cell content in float |\n| `yy` / `yc` | Yank cell / yank column |\n| `s` | Sort by current column (toggle asc/desc) |\n| `zh` | Toggle cell highlight |\n| `zH` | Toggle header float |\n| `zN` | Toggle row numbers |\n| `R` | Re-run query |\n| `\u003cTab\u003e`/`\u003cS-Tab\u003e` | Next/previous result tab |\n| `n`/`N` | Next/previous search match |\n| `\u003cleader\u003e/` | Search |\n| `\u003cleader\u003ecr` | Clear search/filter |\n| `\u003cleader\u003efc` | Find column |\n| `\u003cleader\u003ece` | Filter by current cell |\n| `\u003cleader\u003ehh`/`\u003cleader\u003ell` | First/last page |\n| `\u003cleader\u003epa` | Toggle pagination |\n| `\u003cleader\u003egp` | Toggle raw mode |\n| `i` / `a` | Enter edit mode (insert/append) |\n| `dd` | Delete row |\n| `o` / `O` | Insert row below/above |\n| `u` | Undo edit |\n| `\u003cleader\u003ew` / `:W` | Commit changes (generate \u0026 execute DML) |\n| `\u003cleader\u003eec` | Export as CSV |\n| `\u003cleader\u003eej` | Export as JSON |\n| `\u003cleader\u003ees` | Export as SQL INSERT |\n\n### DB browser\n\n| Key | Action |\n|-----|--------|\n| `\u003cCR\u003e` | Toggle node expand/collapse |\n| `x` | Open context menu (node-specific actions) |\n| `r` | Refresh node |\n| `/` | Search filter |\n| `s` | Generate SELECT * query |\n| `d` | Generate DESCRIBE query |\n| `q` | Close |\n| `ma`/`mr`/`md`/`mt` | Table ops: add/rename/drop/alter column |\n\n\u003c/details\u003e\n\n### Commands\n\n| Command | Description |\n|---------|-------------|\n| `:PosteRun` | Execute request at cursor |\n| `:PosteEnv [name]` | Switch or show current environment |\n| `:PostePasteCurl` | Paste curl from clipboard |\n| `:PosteCopyAsCurl` | Copy request as curl |\n| `:PosteCmpStatus` | Show HTTP completion status |\n| `:PosteSQLCmpStatus` | Show SQL completion status |\n| `:PosteImport \u003cfile\u003e` | Import data from CSV/JSON file into dataset |\n| `:PosteExport {csv\\|json\\|sql}` | Export current dataset |\n\n## Configuration\n\n```lua\nrequire(\"poste\").setup({\n  -- Binary path (default: stdpath(\"data\")/poste/bin/poste)\n  poste_binary = vim.fn.stdpath(\"data\") .. \"/poste/bin/poste\",\n\n  -- Default environment\n  default_env = \"dev\",\n\n  -- Response window\n  split_direction = \"vertical\",  -- \"vertical\" | \"horizontal\"\n  split_size = 80,               -- columns (vertical) or rows (horizontal)\n\n  -- Log file (set to \"\" to disable)\n  log_file = vim.fn.stdpath(\"cache\") .. \"/poste.log\",\n\n  -- Customize keymaps — set to false to disable\n  keymaps = {\n    source_buffer = {\n      run = \"\u003cCR\u003e\",\n      jump_next = \"]]\",\n      jump_prev = \"[[\",\n      goto_definition = \"gd\",\n      goto_references = \"grr\",\n      quickfix_next = \"]q\",\n      quickfix_prev = \"[q\",\n      paste_curl = \"\u003cleader\u003erp\",\n      copy_as_curl = \"\u003cleader\u003erc\",\n      show_symbols = \"gs\",\n    },\n    http_response = {\n      close = \"q\",\n      view_body = \"B\",\n      view_verbose = \"I\",\n      view_assertions = \"A\",\n      view_script_logs = \"S\",\n      next_tab = \"\u003cTab\u003e\",\n      prev_tab = \"\u003cS-Tab\u003e\",\n    },\n    sql_source = {\n      run = \"\u003cCR\u003e\",\n      show_ddl = \"K\",\n      clear_filter = \"\u003cleader\u003ecr\",\n      toggle_db_browser = \"\u003cleader\u003edb\",\n      trigger_completion = \"\u003cC-Space\u003e\",\n    },\n    sql_dataset = {\n      close = \"q\",\n      move_left = \"h\",  move_down = \"j\",  move_up = \"k\",  move_right = \"l\",\n      prev_page = \"H\",  next_page = \"L\",\n      first_col = \"0\",  last_col = \"$\",\n      first_row = \"gg\", last_row = \"G\",\n      preview_cell = \"K\",\n      yank_cell = \"yy\", yank_column = \"yc\",\n      sort_column = \"s\",\n      toggle_cell_highlight = \"zh\",\n      toggle_header_float = \"zH\",\n      toggle_row_numbers = \"zN\",\n      toggle_raw_mode = \"\u003cleader\u003egp\",\n      next_tab = \"\u003cTab\u003e\", prev_tab = \"\u003cS-Tab\u003e\",\n      rerun = \"R\",\n      goto_first_page = \"\u003cleader\u003ehh\", goto_last_page = \"\u003cleader\u003ell\",\n      toggle_pagination = \"\u003cleader\u003epa\",\n      find_column = \"\u003cleader\u003efc\", filter_by_cell = \"\u003cleader\u003ece\",\n      show_search = \"\u003cleader\u003e/\", clear_filter_search = \"\u003cleader\u003ecr\",\n      next_search = \"n\", prev_search = \"N\",\n      -- Editing\n      edit_insert = \"i\",\n      edit_append = \"a\",\n      edit_delete_row = \"dd\",\n      edit_insert_row_above = \"O\",\n      edit_insert_row_below = \"o\",\n      edit_undo = \"u\",\n      edit_commit = \"\u003cleader\u003ew\",\n      -- Export\n      export_csv = \"\u003cleader\u003eec\",\n      export_json = \"\u003cleader\u003eej\",\n      export_sql = \"\u003cleader\u003ees\",\n    },\n    sql_table_ops = {\n      select_all = \"ma\",\n      refresh_all = \"mr\",\n      describe_all = \"md\",\n      toggle_menu = \"mt\",\n    },\n    db_browser = {\n      toggle_node = \"\u003cCR\u003e\",\n      context_menu = \"x\",\n      refresh_node = \"r\",\n      search_filter = \"/\",\n      select_query = \"s\",\n      describe_query = \"d\",\n      close = \"q\",\n    },\n    introspect_float = {\n      close = \"q\",\n      close_alt = \"\u003cEsc\u003e\",\n    },\n  },\n\n  -- Override highlight group colors\n  highlights = {\n    -- Example: change HTTP method colors\n    -- PosteMethodGET    = { fg = \"#00ff00\", bold = true },\n    -- PosteMethodPOST   = { fg = \"#ffff00\", bold = true },\n    -- PosteMethodDELETE = { fg = \"#ff0000\", bold = true },\n    --\n    -- Example: customize SQL dataset look\n    -- PosteSqlHeader    = { fg = \"#ff8800\", bold = true },\n    -- PosteSqlCellSelected = { bg = \"#334455\", fg = \"#ffffff\", bold = true },\n  },\n})\n```\n\nFull list of highlight groups you can override: `PosteLatency`, `PosteSpinner`, `PosteSuccess`, `PosteError`, `PosteSeparator`, `PosteRequestName`, `PosteVarRef`, `PosteMagicVar`, `PosteMethodGET[...]`\n\n## Completion\n\nPoste provides context-aware completions.\n\n### HTTP (`.http`/`.rest`)\n\n- **HTTP methods** — `GET`, `POST`, `PUT`, `DELETE`, etc.\n- **Header names** — `Content-Type`, `Authorization`, `Accept-Encoding`, etc.\n- **Header values** — `application/json`, `Bearer `, `gzip`, etc.\n- **Variables / env vars** — `{{...}}` references from env.json\n\nWorks with both **nvim-cmp** and **blink.cmp**. Registration is automatic.\n\n### SQL (`.sql`/`.sqlite`)\n\n- **SQL keywords** — `SELECT`, `FROM`, `WHERE`, `JOIN`, etc.\n- **Tables, columns, schemas** — introspected from your database\n- **Functions** — aggregate and scalar functions per dialect\n- **Connection-aware** — completions reflect the actual schema\n\nRequires **blink.cmp**. Auto-registers as `poste_sql` source provider.\n\n```vim\n:PosteCmpStatus     \" HTTP completion status\n:PosteSQLCmpStatus  \" SQL completion status\n```\n\n## SQL Features\n\n### Connection management\n\nConnections are defined in `connections.json` (walked up from the SQL file). Reference them in your `.sql` files:\n\n```sql\n-- @connection pg-dev\n-- @connection my-blog\n```\n\nThe `USE database;` statement switches the active database for parsing/completion context.\n\n### Dataset buffer\n\nQuery results render in a rich dataset buffer with:\n- **Cell navigation** — hjkl to move between cells\n- **Sorting** — press `s` on any column\n- **Search \u0026 filter** — `\u003cleader\u003e/` for search, `\u003cleader\u003ece` to filter by cell value\n- **Pagination** — configurable page size, `\u003cleader\u003epa` to toggle\n- **Multi-result tabs** — each statement gets its own tab, `\u003cTab\u003e`/`\u003cS-Tab\u003e` to switch\n- **Raw mode** — `\u003cleader\u003egp` to toggle compact view\n\n### Dataset editing\n\nInline editing directly in the dataset buffer:\n- **Enter edit mode** — `i` to insert before cursor, `a` to append after\n- **Edit cells** — Type to modify, `\u003cEsc\u003e` to exit edit, `\u003cCR\u003e` to confirm\n- **Manage rows** — `dd` to delete, `o`/`O` to insert below/above\n- **Undo changes** — `u` to undo edits (before commit)\n- **Generate \u0026 commit DML** — `\u003cleader\u003ew` or `:W` to auto-generate UPDATE/INSERT/DELETE statements and execute with transaction\n\n### DB Browser\n\nPress `\u003cleader\u003edb` 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`.\n\n### Data import/export\n\n**Export current dataset:**\n- `\u003cleader\u003eec` — CSV (RFC 4180 compliant)\n- `\u003cleader\u003eej` — JSON (array of objects)\n- `\u003cleader\u003ees` — SQL INSERT statements (dialect-aware)\n\n**Import data:**\n- `:PosteImport \u003cfile\u003e` — Load CSV/JSON data into a new result tab\n\n### SQL Integration Tests\n\n```bash\n# Start test databases (PG 16 on 15432, MySQL 8.0 on 13306)\ncd tests/sql \u0026\u0026 docker compose up -d\n\n# Run queries\ncargo run -- run tests/sql/queries/postgres.sql --line 4 --env dev\n\n# Run Lua tests\ntests/run.sh\n```\n\n## CLI\n\n```bash\n# Execute a specific request by line number\nposte run requests/api.http --line 4 --env dev\n\n# Introspect database schema\nposte introspect --connection pg-dev --env dev\n\n# List available connections\nposte connection list --env dev\n```\n\n## Architecture\n\n```\nposte/\n├── crates/\n│   ├── poste-core/    # Request parsing, SQL parsing, env management (no I/O)\n│   ├── poste-exec/    # Protocol execution, SQL connection/dialect, response\n│   └── poste-cli/     # CLI binary (poste run / connection / introspect)\n├── lua/\n│   └── poste/         \n│       ├── http/      # HTTP protocol handling\n│       └── sql/       # SQL protocol handling (buffer, editor, export, import, etc.)\n└── tests/\n    ├── run.sh         # Lua tests\n    └── sql/           # Docker Compose + SQL integration tests\n```\n\n## Development Status\n\n**Progress: 34/38 steps completed** (~90%)\n\n| Phase | Description | Status |\n|-------|-------------|--------|\n| **1A** | Rust infrastructure | ✅ Complete |\n| **1B** | Lua dataset panel | ✅ Complete |\n| **1C** | MySQL/SQLite executors | ✅ Complete |\n| **2** | Connection \u0026 context management | ✅ Complete |\n| **3** | DB structure browser | ✅ Complete |\n| **4** | Table operations + DDL + completion | ✅ Complete |\n| **5** | Import/export + pagination | ✅ Complete |\n| **6** | Advanced features (editor, transactions) | ✅ Complete |\n\n**Tests:** 300+ passing (230 Rust + 70 Lua)\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbeyondlex%2Fposte","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbeyondlex%2Fposte","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbeyondlex%2Fposte/lists"}