Postguy
Guide

Import and export

Import Postman, OpenAPI, HAR, cURL, Bruno folders and .proto files. Export collections, environments, globals and the whole workspace.

Postguy reads many formats into your workspace. It writes collections, environments and globals back out. Everything is local: the import box never fetches a URL.

Import dialog

Open it with the sidebar import button, Cmd/Ctrl+I, or the command palette (Import…). The dialog has:

  • A text box for pasted JSON, YAML or a cURL command, and an Import text button.
  • Choose files… and Choose folder… (native pickers).
  • A Replace existing checkbox.
  • An OpenAPI: folders by path (default: by tag) checkbox.
  • Drag and drop. Drop files or folders anywhere in the window to open the dialog and import.

After each run, the dialog lists every file with its result, an Open link, warnings and dropped items. This is the import report (see below).

URLs are refused on purpose: URL imports are not fetched automatically; download the file and drop it here. Fetching a document from a URL is a tracked gap, not a hidden network call.

How the format is detected

Pasted text is classified in this order. A leading UTF-8 byte-order mark is ignored.

First charactersTreated as
nothing (empty input)error: nothing to import
{ or [JSON: OpenAPI/Swagger, then HAR, then Postman collection, environment or globals
http:// or https://refused (no fetch)
syntax = "…" or package x; on the first content line.proto source: refused as text, import the file instead
%YAML, or a first line that looks like key: valueYAML: accepted only if it is an OpenAPI 3 or Swagger 2 document
anything elsecURL commands

A file with the .proto extension is always imported as protobuf, whatever its content. Files must be UTF-8 text and at most 100 MiB.

Name clashes and Replace

  • If an imported collection, environment or globals id already exists, it gets a fresh id.
  • If a name is taken, it gets a numeric suffix: Payments API (2), Payments API (3), and so on. Names are compared case-insensitively.
  • With Replace existing, only a collection or environment with the same id is overwritten. An environment is also matched by name. Globals are replaced as a whole.
  • Importing globals when globals already exist, without Replace, fails with globals already exist; tick Replace existing to import over them.

Import report

Every import returns:

  • Counts for collections, environments, globals, requests, folders and examples.
  • A list of warnings.
  • A list of dropped items.

Each list keeps at most 200 entries. Nothing is dropped silently. If a field cannot be represented, the report names it.

Postman

Postguy reads Collection Format v2.0 and v2.1 JSON, environments and globals.

  • Folders, bodies, auth, scripts, variables and saved responses (examples) are mapped.
  • Unknown fields are preserved and written back on export.
  • Tests written in the Tests tab round-trip through an extra item key, postguyTests.
  • gRPC and WebSocket items are reported as dropped (only HTTP requests are imported so far).
  • Collection Format v1 is refused, with instructions to convert it to v2 first.
  • Postman v3 YAML is not imported.
  • Limits: 100 MiB per document, nesting depth 256.

OpenAPI 3 and Swagger 2

Postguy reads JSON or YAML (openapi: 3.x or swagger: "2.0").

  • Folders. Folders follow the first tag of each operation (default). With OpenAPI: folders by path ticked, they follow the path. The tool argument is folders: tags or paths.
  • Base URL. A baseUrl collection variable comes from servers[0], or from host plus basePath. Requests use {{baseUrl}} in the URL (shown as code here because it is a variable reference).
  • References. Only local $ref values are followed, with cycle cuts. External $ref, callbacks, webhooks, links and x-* extensions are reported, not imported.
  • Examples. Example bodies come from examples or from bounded schema samples.
  • Auth. Security schemes map to Basic, Bearer, API key and OAuth 2.0 auth. They use placeholder variables: username, password, bearerToken, apiKey, clientId, clientSecret.
  • Limits:
    • 20 MiB document.
    • 10,000 operations.
    • $ref depth 32.
    • Example size 64 KiB and 5,000 nodes.
    • Folder depth 32.
    • 20 examples per operation.
    • YAML is read with a budget: depth 100, 1,000,000 nodes, 4,000,000 events, 10,000 aliases and 10,000 anchors.

HAR 1.2

  • You get one flat collection with one request per entry. It is named after the first page title (Imported HAR if there is none).
  • The recorded URL is kept verbatim.
  • Pseudo-headers, Content-Length and Host are skipped and reported.
  • Recorded responses become examples. Invalid base64 or bodies over 5 MiB are dropped and reported.
  • An unsupported method becomes GET with a warning.
  • Limits: 10,000 entries, 5 MiB per body.

cURL

Paste one or several commands.

  • Commands are split on lines that start with curl.
  • \ and ^ line continuations are joined.
  • Each request is named after its method and last path segment (GET payments).
  • The collection is named Imported cURL.

Mapped flags:

FlagResult
-X, --request, --methodmethod
--url, a bare URLURL, kept verbatim (query parameters are not split out)
-H, --headerheader
-A, --user-agent; -e, --refererUser-Agent, Referer headers
-b, --cookieCookie header; @file is read (up to 64 KiB), @- is refused
-d, --data, --data-raw, --data-ascii, --data-urlencode, --data-binaryraw body; several pieces are concatenated without a separator; implies POST
-F, --form, --form-stringform-data body
-u, --userBasic auth
--jsonbody, plus Content-Type: application/json if none is set
-G, --getdata moves into the query string
-L, --locationfollow redirects on; without -L the imported request has follow redirects off, like cURL
-k, --insecureSSL verification off for that request
-I, --headHEAD
--max-redirs, -m/--max-timeper-request max redirects and timeout
--http1.0, --http1.1, --http2, --http2-prior-knowledgeper-request HTTP version

Reported and ignored: --compressed, -o, -c, --connect-timeout, --retry, --noproxy, -E/--certificate, --key, --cert, --cacert, --unix-socket, --resolve, --header-file, --config and -K.

Other flag behaviour:

  • -x/--proxy is parsed but not stored, because a request has no proxy field. Set a proxy in Settings instead.
  • Unknown flags produce a warning, not an error.
  • Flags such as -s, -v, -i and --fail are ignored without a warning.

Limits: 1 MiB of input, 8,192 lines, 4,096 tokens per command, 256 KiB per token, 200 warnings.

The request builder also detects a cURL command pasted into the URL bar.

Bruno collection folders

Postguy imports a Bruno collection folder: a directory that contains bruno.json.

  • Without that file, the import fails with … is not a Bruno collection (no bruno.json).
  • Only the .bru file format is read.
  • Picking or dropping a folder that contains bruno.json routes here automatically. The tool is import_bruno.

What the importer reads

Bruno fileBecomes
bruno.jsonthe collection name (the folder name if name is empty); its ignore list skips those top-level entries
collection.bru (root only)collection-level description, variables, auth, scripts and headers. A collection.bru in a subfolder is dropped with a report entry
folder.brua folder's name (from meta), description, variables, auth, scripts and headers
other .bru filesrequests
environments/<name>.bruone environment per file
any other filea collection asset, with its relative path kept

Ordering: items are sorted by meta seq. Items without one go last, sorted by name.

The walk skips names that start with ., node_modules, and symlinks. These are not copied as assets: top-level bruno.json, package.json, package-lock.json, and everything under environments/.

How requests are mapped

  • Request types and methods. Types http and graphql are imported. Other types, and the trace and connect methods, are dropped and reported. Supported methods: get, post, put, patch, delete, options, head.
  • Query and path parameters. Query parameters in the URL become parameter rows. Disabled params:query rows are added as disabled rows. params:path rows become path variables.
  • Headers. Mapped one to one. Postguy has no field for headers set in folder.bru or collection.bru. They are copied onto every request below that does not already set them, and the report says so.
  • Body modes. none; json; text; xml; sparql (imported as plain text); form-urlencoded; multipart-form; graphql (query plus variables); file. Any other mode is dropped and reported.
  • Files in bodies. A multipart value @file(path) becomes a file row holding {{% file('path') %}}. A file body becomes a binary body with the same shortcode. The file is copied into the collection's Assets. See Variables for shortcodes.
  • Auth. none, inherit, basic, bearer, digest and apikey (placement queryparams becomes a query parameter, anything else a header). Any other mode is reported as auth mode … is not supported and kept as an unknown auth kind. The parity file lists Bruno OAuth 2.0 and AWS modes as missing.
  • Scripts. script:pre-request becomes the pre-request script. script:post-response becomes the post-response script.
  • Vars. Request-level vars:pre-request entries become pg.variables.set(…) lines at the top of the pre-request script. vars:post-response entries become pg.setVar(…) lines at the end of the post-response script. At collection and folder level, vars:pre-request becomes ordinary collection or folder variables.
  • Tests. The tests block becomes the Tests-tab script. Each assert line becomes a Tests-tab assertion using the same operator tokens (Scripts and tests). An assertion with an unknown operator is imported disabled, as eq, with the original text as its value. The report notes it.
  • Docs. The docs block becomes the description.
  • npm packages. A require of anything other than a relative path, fs, path or buffer is reported (requires npm package …, which Postguy cannot load). Relative requires work because the scripts' files are imported as assets.
  • Unknown blocks. Any block the importer does not know is reported as not supported.

Imported scripts run with Postguy's bru, req, res, test and expect globals. The scripting reference lists what is and is not supported (bru.sleep, bru.cwd and bru.runRequest throw).

Environments and secrets

  • vars entries become variables.
  • Names listed in vars:secret become secret variables with no value. Set them in the app.
  • Other blocks are dropped and reported.
  • {{process.env.X}} is rewritten to {{X}} everywhere. Each such X becomes a secret variable in every environment.
  • Its value comes from the .env file at the folder root when that file names it (KEY=value lines; read up to 64 KiB, quotes stripped). Otherwise it is left empty and the report lists the missing names.
  • Secret values go to the workspace secrets store, not into environment files (Workspace).

Limits

LimitValue
One .bru file5 MiB
.bru files per import20,000 (more fails the import)
Folder depth walked32
Non-.bru files queued as assets100,000
Asset importdepth 16, 10,000 files, 100 MiB per file, 2 GiB per import, path 1,024 bytes, component 255 bytes

Files that are not UTF-8 text, or that fail a cap, are skipped and listed in the report.

Postguy does not write .bru files or export Bruno folders.

.proto files

Choose or drop one or more .proto files. Select them together so their imports resolve.

  • The files and the imports they pull in are copied to <workspace>/protos/<name>/ and compiled. The bundled google/protobuf imports are not copied.
  • Postguy creates a collection with one gRPC request per service method, grouped in a folder per service.
  • Each request uses the URL {{grpcUrl}} and an example message built from the input type.
  • The collection has a grpcUrl variable that defaults to localhost:50051.
  • A name clash suffixes the set (-2 … -1000). With Replace, the old set moves to the trash.
  • Compile errors read file:line:column: message.
  • Limits: 1 MiB per file, 16 MiB total, 256 files.

See gRPC.

Zip files

import_zip reads .json entries (collections, environments, globals) from a zip through the normal importers.

  • Entries with unsafe paths are refused. Other entries are skipped.
  • Limits: the first 5,000 entries are read; 100 MiB per entry and 1 GiB in total.
Zip import is available as a tool (import_zip) only. The import dialog does not accept .zip files.

Export

You can export a collection, an environment, the globals or the whole workspace. Start from any of these:

  • The Export items in the sidebar context menus.
  • The collection and environment editors.
  • The Globals editor.
  • The command Export all workspace data….
WhatFormatsDefault file name
CollectionPostman JSON (Collection v2.1) or Postguy native JSON<name>.postman.json, <name>.json
EnvironmentPostman environment<name>.postman_environment.json
GlobalsPostman globalsglobals.postman_globals.json
All workspace datazipWorkspace.zip

Characters that are invalid in file names (/ \ : * ? " < > |) are replaced by - in the name.

Secrets:

  • Collection exports always blank secret variable values. The secret flag stays. OAuth 2.0 access and refresh tokens are cleared.
  • Environment and globals exports omit secret values unless you tick Include secret values.

The workspace zip contains workspace documents. It leaves out .postguy/ (secrets, cookies, response cache, lock), .trash/ and .bak files.

Restoring from the zip is documents-only. Only JSON documents are re-imported. Files, protos and settings are not restored from the archive.

Limits: 50,000 entries and 1 GiB uncompressed.

Headless

TaskTool
Import pasted text (Postman, OpenAPI, HAR, cURL)import_text (text, replace, folders)
Import a file (size-capped at 100 MB, path confined to --root)import_file
Import a Bruno folderimport_bruno
Import .proto filesproto_import
Import a zip of JSON documentsimport_zip
Exportexport_collection, export_environment, export_globals, workspace_export_zip

Details and arguments: Automation tools.

Copyright © 2026