Skip to content

Editors

outry lsp is a language server built into the CLI: the same checks, names and variables as outry check and the desktop app, in your own editor. For VS Code (and Cursor, Windsurf, VSCodium) there is an extension with a response view; any other editor with an LSP client can use the server directly, with syntax highlighting from the tree-sitter grammar in editors/tree-sitter-outry.

  • Errors as you type — everything outry check reports: syntax, unknown requests and shapes (with a quick fix for “did you mean”), call arguments, cycles.
  • Environment warnings — what outry check --env reports for the current environment: variables that aren’t defined and calls to requests limited by only.
  • Differences from the Go code — in a Go project, what outry import go --check reports, on the lines of the request, with a link to the handler. Differences that --fix can fix have a quick fix, and “Fix all differences with the code” fixes the whole file. Unsaved edits count.
  • Completion — request fields at the start of a line, requests and flows with their parameters, call arguments, variables of the current environment (secrets masked), saved values, file lets, parameters, built-in functions, value methods after ., shapes after matches, environments in only: [...], common header names.
  • Hover — a variable’s value and where it comes from (env.toml, keychain, OUTRY_*, save; secrets masked), a called request’s method, path, description and parameters, a shape’s fields.
  • Go to definition — a call → the request or flow; a variable → its line in env.toml and the saves that set it; a shape → its declaration, and from the declaration → the Go struct; handler: → the route in Go.
  • Send — a code lens “▶ Send · dev” above every request (“▶ Run flow” above flows), and the same in the code actions menu. The response is written to ~/.cache/outry/responses/<Name>.http and opened next to the request; the result is shown as a message. Calls, the run cache, cookies and saved values work as in the app; confirm: true asks first.
  • Format — outry fmt as document formatting.
  • Outline — requests, flows, shapes and lets of the file.

Install Outry API Client from the Visual Studio Marketplace or, in Cursor, Windsurf and VSCodium, from Open VSX. The packages for Linux, macOS and Windows include outry, so nothing else is needed. Elsewhere install the CLI: the extension finds it on PATH or in ~/.local/bin, or set outry.path. Each release also has the .vsix files for Extensions → ⋯ → Install from VSIX….

Besides everything above, the extension adds:

  • Response beside the file. ▶ Send (or Ctrl+Enter on any line of a request) opens the same view as the desktop app: the body with highlighting and search, image and HTML preview, headers, checks from expect, the trace of called requests, the request as it was sent, and saving the body to a file. A flow shows its checks and trace.
  • in… — send once in another environment without switching to it; confirm: true asks first.
  • Copy as curl — the request with variables, calls (Login().body.token) and the run’s cookies resolved. The calls are sent, the request itself is not.
  • Environment in the status bar, remembered per workspace.
  • Sidebar — the project’s requests and flows by folder (click to open, ▶ to send), and the variables of the current environment with where each comes from; secrets are masked.
Setting Default
outry.path the bundled binary, then PATH Path to outry
outry.env default from env.toml Environment to start with
outry.keyring, outry.import, outry.goDir As keyring, import, goDir in Settings

The output of the language server is in Output → Outry; Outry: Restart Language Server restarts it (after outry update, for example).

Neovim 0.11 or newer:

vim.filetype.add({ extension = { outry = "outry" } })
vim.lsp.config("outry", {
cmd = { "outry", "lsp" },
filetypes = { "outry" },
root_markers = { "env.toml", ".git" },
-- init_options = { env = "dev" },
handlers = {
-- Re-read the response file when it is already open.
["window/showDocument"] = function(err, params, ctx)
local result = vim.lsp.handlers["window/showDocument"](err, params, ctx)
vim.cmd.checktime()
return result
end,
},
})
vim.lsp.enable("outry")
-- Code lenses: keep them fresh and send the request under the cursor.
vim.api.nvim_create_autocmd({ "LspAttach", "BufEnter", "InsertLeave" }, {
pattern = "*.outry",
callback = function(ev) vim.lsp.codelens.refresh({ bufnr = ev.buf }) end,
})
vim.keymap.set("n", "<leader>rs", vim.lsp.codelens.run, { desc = "Outry: send" })

Highlighting: build the parser and copy the queries (Neovim reads parser/ and queries/ from its runtime path):

Terminal window
git clone --depth 1 https://github.com/1rowvy/outry /tmp/outry
cd /tmp/outry/editors/tree-sitter-outry
mkdir -p ~/.local/share/nvim/site/parser ~/.config/nvim/queries/outry
cc -shared -fPIC -O2 -I src -o ~/.local/share/nvim/site/parser/outry.so src/parser.c
cp queries/highlights.scm ~/.config/nvim/queries/outry/
vim.api.nvim_create_autocmd("FileType", {
pattern = "outry",
callback = function() vim.treesitter.start() end,
})

In ~/.config/helix/languages.toml:

[language-server.outry]
command = "outry"
args = ["lsp"]
[[language]]
name = "outry"
scope = "source.outry"
file-types = ["outry"]
roots = ["env.toml"]
comment-token = "//"
block-comment-tokens = { start = "/*", end = "*/" }
indent = { tab-width = 2, unit = " " }
language-servers = ["outry"]
[[grammar]]
name = "outry"
# rev: a branch, tag or commit of the outry repository
source = { git = "https://github.com/1rowvy/outry", rev = "master", subpath = "editors/tree-sitter-outry" }
Terminal window
hx --grammar fetch && hx --grammar build
mkdir -p ~/.config/helix/runtime/queries/outry
curl -fsSL https://raw.githubusercontent.com/1rowvy/outry/master/editors/tree-sitter-outry/queries/helix/highlights.scm \
-o ~/.config/helix/runtime/queries/outry/highlights.scm

Helix has no code lenses: Send is in the code actions menu (Space a) on any line of a request. If the response file is already open, :reload shows the new response.

Any LSP client works: the command is outry lsp over stdio (--stdio is accepted and ignored), the language id is outry, files are *.outry.

The grammar in editors/tree-sitter-outry (with queries/highlights.scm in the capture names of nvim-treesitter and Zed) can be used by any editor that loads tree-sitter grammars.

Pass them as initializationOptions (init_options in Neovim), or later with workspace/didChangeConfiguration as { "outry": { … } }:

Setting Default Meaning
env default from env.toml Environment for variables, warnings and Send
keyring true Read secrets from the system keychain
import true Compare requests with the Go code
goDir the parent of api/, else the project folder Folder with the Go code, relative to the workspace root

outry lsp --env <ENV> and --no-keyring do the same from the command line.

Commands (workspace/executeCommand), for key bindings and editor extensions:

Command Arguments
outry.run [uri, line, env?] Send the request or run the flow at line (1-based), in env if given instead of the current environment. Returns the outcome as JSON
outry.curl [uri, line, env?] The request at line as a curl command (a string). Calls in it are sent, the request is not
outry.selectEnv [env] or none Switch the environment; without an argument the editor shows a choice

When the project has several environments, the code lens “env: dev” above the first request runs outry.selectEnv.