@allenwu06/qreq
v0.1.0
Published
A deliberately tiny, local-first HTTP request client. `npx qreq req.qreq` sends a request from a plaintext, git-diffable request file — no account, no login, no telemetry, no daemon, no DB. Built for devs who want to do 95% of daily API poking and conscio
Maintainers
Readme
qreq
A tiny tool for sending an API request and seeing the response — nothing else.
You know the heavy app you open just to fire one HTTP request at an API and look at what comes back? This is the opposite of that. One plain-text file format. No account, no login, no background process, no database, no usage tracking. It opens instantly because there is almost nothing to open, and your saved requests live in your code repo as readable text.
npx @allenwu06/qreq req.qreqqreq is built to do the 95% of everyday API poking you actually do and to deliberately refuse the other 5%. That refused 5% is exactly the weight that made every other tool heavy. Being tiny is the whole feature. If you need that 5%, qreq is honestly the wrong tool — and it tells you that up front, not after you've invested in it.
The screenshot
$ qreq users.qreq --env dev.qenv
✓ login POST http://api.local/login 200 (12ms)
✓ me GET http://api.local/users/42 200 (4ms)
PASS — 2 request(s)That is real output (minus color). There are no fabricated speed claims in this README, on purpose — see Honesty below.
Why this exists
There is a long, repeated, verbatim request from developers for an "unbloated, easy Postman" — and a running complaint that the usual alternatives still feel like a lot (an app, a workspace, an account, a sync). qreq is a narrow answer to one specific pain, and it is honest that it is narrow. It is not trying to replace those tools' full feature set; it is trying to be the thing you reach for when you just want to send the request and see the response, and have that request live in your repo as plain text.
It is good at exactly one thing, or it is no use to you at all:
tiny · instant-start · no account · plain-text request files that diff in git
If that one thing doesn't matter to you, use something else — genuinely.
Install
Nothing to install, really:
npx @allenwu06/qreq path/to/request.qreqOr add it to a project so a teammate's checkout can run your requests with zero setup:
npm i -D @allenwu06/qreq # then: npx @allenwu06/qreq api/smoke.qreq --env api/dev.qenvRequires Node 20+ (uses the built-in fetch; zero runtime
dependencies — npm ls --omit=dev is empty).
The request file (plain text, diffs in git)
A request file is plain text. A collection is one file with several
named requests separated by ### name. The full grammar is one short page:
SPEC.md. The whole thing:
# users.qreq
### login
@expect-status 200
@capture TOKEN = json:token
POST {{BASE}}/login
Content-Type: application/json
{"user": "{{USER}}", "pass": "{{PASSWORD}}"}
### me
@expect-status 200
@expect-jsonpath user.name == alice
GET {{BASE}}/me
Authorization: Bearer {{TOKEN}}qreq users.qreq --env dev.qenv # PASSWORD comes from your shell env
qreq users.qreq --only me # run just one named request
qreq users.qreq --json # machine-readable, for CI- Variables:
{{NAME}}resolves, first hit wins:@captured-this-run →--envfile →process.env. - Secrets: a real token/password belongs in
process.env, never in the collection. That is the entire point:git diffof a collection shows what changed and never leaks a credential. The.qenvfile is for non-secret config (base URLs, ids) and is safe to commit. - Assertions:
@expect-statusand@expect-jsonpathmake a collection a CI smoke test (qreq api/smoke.qreq→ non-zero exit on failure). - Chaining:
@capture X = json:pathbinds a value from one response for use in a later request — no scripting language, by design.
Exit codes (CI-usable)
| Code | Meaning |
| ---- | --------------------------------------------------- |
| 0 | all requests sent, all assertions passed |
| 1 | usage / file / parse error |
| 2 | an assertion failed, or a variable was unresolved |
| 3 | a network/transport error reaching the target |
Coming from Postman / Insomnia / a curl you pasted
There is no importer for proprietary project formats — that is a non-goal
(below). There is a curl on-ramp, because a curl line is the
universal interchange format everyone already has:
qreq curl import "curl -X POST https://api/x -H 'A: b' -d '{\"k\":1}'" > x.qreq
qreq curl export x.qreq # back to a runnable curlPaste a curl from your browser's devtools or from API docs, get a clean
.qreq file, commit it.
Non-goals (by design — this list is the product)
These are not "not yet". They are deliberately refused because each one is a documented step on the path to the bloat people are escaping. If you need one of these, qreq is the wrong tool and says so honestly:
- No account, no login, no cloud sync, no workspace. A paid optional team-sync tier may exist later, wired entirely outside this CLI; the CLI itself will never grow auth or a network call that isn't your request.
- No GUI / Electron app. It is a CLI/terminal tool. That is the whole idea.
- No pre-request scripting / JS sandbox / plugin system. The day a request file can run arbitrary code is the day it stops being a readable plaintext artifact. Use a shell script around qreq if you need logic.
- No binary attachments / multipart file-upload builder. Plaintext
bodies only. (You can pipe to
curlfor a one-off upload.) - No full JSONPath / JMESPath / XPath. Assertions and captures support
a.b.candarr.0.k. That covers the overwhelming common case; anything more is scope-creep. - No GraphQL/gRPC/WebSocket clients, no mock server, no API designer, no environments-as-a-service, no history UI, no response visualizer.
- No telemetry, ever. No analytics, no "anonymous usage stats", no update-check phone-home.
If a missing piece is genuinely a daily essential (not the 5%), that is exactly what we want to hear — see FEEDBACK.md. The bar for adding anything is "a real developer cannot do a normal daily task without it", not "it would be nice".
The zero-network promise (and how it is enforced)
The only HTTP request qreq makes is the one you wrote in the request file. No update check, no telemetry beacon, no account handshake.
This is not just a claim — it is a test. test/no-network.test.js scans
every shipped source file and fails the build if any network call exists
outside the single sanctioned sender (src/run.js), or if any
telemetry/account/login primitive appears in the code. The CI also runs the
whole suite, and package-lock.json has zero runtime dependencies
(only vitest for development).
You can verify it yourself with everything except loopback blocked:
git clone <repo> && cd qreq && npm ci && npm testis the entire trust surface. No API key. No external network. No account.
Note on
npm audit: it flags advisories in vitest's dev-only toolchain (the esbuild/vite dev server).npm audit --omit=devreports 0 vulnerabilities, because shippedqreqhas no runtime dependencies — none of that code is ever installed by users.
Honesty
- The output shown above is real (color stripped); there are no invented benchmark numbers anywhere in this README. "Instant start" means there is no daemon/DB/account to initialize and zero runtime deps to load — not a measured figure we are asking you to take on faith.
- This is an entrenched space with capable incumbents. qreq is not "better Postman". It is a smaller, different thing for people who specifically want smaller and different. If that's not you, the incumbents are good — use them.
- It is young. The format is v1 and intentionally minimal. Tell us what daily task it can't do.
Feedback
What did qreq fail to do, or do awkwardly, for a real daily task? That's the single most useful thing you can report — it's how we tell a missing-essential from scope-creep we should refuse.
Zero-friction: add the qreq-feedback label to a GitHub issue.
Structured: the qreq feedback issue template. Either way, your words
are stored and read exactly as written — not summarized, not paraphrased.
See FEEDBACK.md.
License
MIT.
