Most backend work is a tight feedback loop: send a request, inspect JSON, change code, and repeat. Heavy GUI clients can interrupt that loop; command-line tools start quickly, compose in scripts, and work equally well in a terminal or CI job.
A practical backend CLI kit should cover four jobs: sending requests, parsing responses, exposing local services, and running tests. This guide walks through 10 tools that fit that workflow, with a command you can run for each. For broader context, see this guide to API development.
What makes a CLI tool lightweight?
A lightweight development tool minimizes setup and maximizes composability. Use these criteria when deciding whether a tool belongs in your daily workflow:
-
Small installation footprint: Prefer a single binary or small
npx/package install over tools that require a runtime, project config, or dashboard. - Fast startup: A tool should be ready before you switch back to your editor. This matters when it runs repeatedly in scripts.
- Useful defaults: You should get a result without creating an account, project file, or configuration wizard.
- Unix-friendly behavior: Read from stdin, write to stdout, return meaningful exit codes, and work in pipelines.
The tools below range from single-purpose utilities to fuller API workflow tools. curl is likely already installed; most of the rest take only a few minutes to add.
1. curl
curl is the baseline HTTP client for scripts and automation. It is installed on most systems, supports a wide range of protocols, and makes every request explicit.
curl -s -X POST https://api.github.com/repos/curl/curl/issues \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"title":"Test issue"}'
Use these flags to make curl more automation-friendly:
# Include response headers
curl -i https://api.example.com/health
# Print only the HTTP status code
curl -s -o /dev/null -w '%{http_code}\n' https://api.example.com/health
# Return a non-zero exit code for 4xx and 5xx responses
curl --fail https://api.example.com/health
Best for: shell scripts, CI health checks, and shareable reproducible requests.
Limit: JSON bodies and headers require manual quoting and flags. Use HTTPie or xh when you want a more interactive syntax.
2. HTTPie
HTTPie provides a friendlier interface for manually exploring APIs. It formats JSON responses, enables colors by default, and lets you construct JSON bodies with request items.
http POST httpbin.org/post name=apidog role=api-tool active:=true
This sends:
{
"name": "apidog",
"role": "api-tool",
"active": true
}
Request-item syntax:
# String value
name=apidog
# Raw JSON value
active:=true
count:=42
# Header
Authorization:"Bearer $TOKEN"
For example:
http GET https://api.example.com/users \
Authorization:"Bearer $TOKEN"
Best for: interactive API exploration where readable input and formatted output matter.
Limit: HTTPie is a Python package, so startup is slower than a native binary and Python must be available.
3. xh
xh provides HTTPie-style syntax as a Rust binary. Use it when you want the same request-item ergonomics without a Python runtime.
xh POST httpbin.org/post name=apidog age:=24
You can use the same familiar request syntax:
xh GET https://api.example.com/users \
Authorization:"Bearer $TOKEN"
Because xh is a single binary with no runtime dependency, it is useful in slim containers and CI images. It also supports HTTP/2 and HTTP/3.
Best for: HTTPie-style requests in scripts, containers, and environments where startup time matters.
Limit: It covers common HTTPie workflows, but not every HTTPie plugin or extension.
4. jq
jq turns raw JSON responses into scriptable data. Combine it with curl, xh, or HTTPie to extract only the fields your script needs.
curl -s https://api.github.com/repos/stedolan/jq | jq '.stargazers_count'
Common patterns:
# Extract a field from every item in an array
jq '.items[] | .name'
# Filter active records
jq '.users[] | select(.active)'
# Return raw text without JSON quotes
jq -r '.token'
Use it in shell variables:
VERSION=$(curl -s https://api.example.com/version | jq -r '.version')
echo "$VERSION"
Best for: filtering, extracting, and transforming API responses in scripts and CI.
Limit: Complex nested transformations can become hard to read. Keep queries small or store them in separate .jq files.
5. gh (GitHub CLI)
gh lets you automate GitHub workflows without hand-writing authenticated REST calls. Authenticate once, then create pull requests, inspect checks, trigger workflows, and call GitHub APIs.
gh auth login
Create a pull request from the current branch:
gh pr create --title "Add rate limiting" --body "Closes #42" --base main
Useful commands:
# Watch checks for the current pull request
gh pr checks --watch
# Follow a GitHub Actions workflow run
gh run watch
# Make an authenticated GitHub API request
gh api repos/OWNER/REPO/issues
Best for: GitHub-based review, release, CI, and repository automation.
Limit: It is GitHub-specific. It does not help with GitLab or Bitbucket workflows.
6. ngrok
ngrok exposes a local port through a public HTTPS URL. It is especially useful when developing webhook handlers or testing callbacks from external services.
ngrok http 8080
This forwards a public https:// URL to localhost:8080. Configure your webhook provider to send requests to the generated URL.
While the tunnel is running, inspect requests locally at:
http://127.0.0.1:4040
The inspector lets you review and replay requests, which is useful for debugging GitHub, payment, or third-party webhooks.
Best for: webhook development, external callbacks, and sharing a local work-in-progress.
Limit: ngrok is a commercial service with a free tier. Free URLs rotate between sessions and are rate-limited.
7. mkcert
mkcert creates locally trusted HTTPS certificates. Use it when your application needs real local HTTPS for secure cookies, OAuth callbacks, browser APIs, or service worker testing.
mkcert -install
mkcert localhost 127.0.0.1 myapp.local
The first command creates and installs a local certificate authority. The second generates a certificate and key for the listed hostnames.
Pass those files to your local server or reverse proxy. For example, configure your application to serve https://myapp.local instead of relying on a browser warning for a self-signed certificate.
Best for: trusted HTTPS in local development.
Limit: Use mkcert only for development. Do not use generated certificates in production, and protect the local root CA key.
8. watchexec
watchexec reruns a command when files change. It is language-agnostic, respects .gitignore by default, and works well for fast edit-run loops.
Run Python tests whenever Python files change:
watchexec -e py -r 'pytest tests/'
Other examples:
# Restart a Go server
watchexec -r 'go run .'
# Rerun a JavaScript test suite
watchexec 'npm test'
# Restart a Node server when source files change
watchexec -e js,ts -r 'node server.js'
The -r flag restarts a long-running command instead of allowing multiple processes to stack up.
Best for: automatically rerunning servers, tests, and scripts on file changes.
Limit: It restarts processes; it does not provide hot-module replacement or preserve in-memory state.
9. Docker CLI
The Docker CLI is heavier than the other entries, but it is the simplest way to run disposable backing services locally. Use it for Postgres, Redis, queues, or dependencies needed by integration tests.
Start a temporary Postgres instance:
docker run --rm \
-e POSTGRES_PASSWORD=dev \
-p 5432:5432 \
postgres:16
Your application can now connect to:
postgresql://postgres:dev@localhost:5432/postgres
The key flags are:
-
--rm: remove the container when it stops. -
-e: set environment variables. -
-p: map a container port to your host.
Swap the image to run another dependency:
docker run --rm -p 6379:6379 redis:7
Best for: reproducible local services and integration-test dependencies.
Limit: Docker requires a daemon and uses real memory and disk. It is not lightweight as a runtime, but its CLI workflow is highly scriptable.
10. apidog-cli
Once you are running API requests from the terminal, you may also need to run the test scenarios, environments, schemas, and endpoints defined in your API project. Apidog provides apidog-cli for that workflow.
Install and authenticate:
npm install -g apidog-cli
apidog login --with-token <YOUR_TOKEN>
Run a saved test scenario against an environment:
apidog run -t <scenario_id> -e <env_id> -r cli
apidog run prints step-by-step results and returns exit code 0 when assertions pass. A failed assertion returns a non-zero exit code, so you can use it directly as a CI gate:
apidog run -t "$SCENARIO_ID" -e "$ENV_ID" -r cli
The CLI also includes command groups for:
-
endpointandschemafor API design resources -
importandexportfor OpenAPI, Swagger, and Postman specifications -
mockfor mock expectations -
environmentandvariablesfor project configuration
Its structured JSON output and agentHints.nextSteps also make it suitable for AI coding assistants doing API development.
For command details, see the complete Apidog CLI guide and the Apidog CLI installation guide.
Best for: running API test scenarios in CI and managing API project resources from scripts, especially in a spec-first API development workflow.
Honest note: Apidog is a commercial product with a free tier, not an open-source project. The lightweight component is apidog-cli; the full Apidog platform provides a GUI over the same project.
How to choose
These tools are mostly complementary. A typical stack might include an HTTP client, jq, a watcher, a tunnel, and a test runner.
| Tool | Best for | Install | Open source? |
|---|---|---|---|
| curl | Scripted requests and CI health checks | Preinstalled | Yes (curl license) |
| HTTPie | Readable interactive requests | pip install httpie |
Yes (BSD) |
| xh | HTTPie-style syntax with native speed |
cargo install xh / binary |
Yes (MIT) |
| jq | Filtering JSON responses |
brew install jq / binary |
Yes (MIT) |
| gh | GitHub PR and CI automation |
brew install gh / binary |
Yes (MIT) |
| ngrok | Exposing localhost and testing webhooks | Download binary | No (freemium) |
| mkcert | Trusted local HTTPS certificates |
brew install mkcert / binary |
Yes (BSD) |
| watchexec | Rerunning commands on file changes | cargo install watchexec-cli |
Yes (Apache-2.0) |
| Docker CLI | Disposable local backing services | Docker install | Yes (Apache-2.0) |
| apidog-cli | Test scenarios and API project management | npm install -g apidog-cli |
No (freemium) |
Choose based on the task:
-
Send requests: use
xhor HTTPie interactively; usecurlin scripts. -
Read JSON: pipe responses into
jq. -
Expose a local service: use
ngrok. -
Test local HTTPS behavior: use
mkcert. -
Rerun work on save: use
watchexec. - Start databases and dependencies: use Docker.
-
Run API test scenarios and manage API resources: use
apidog-cli.
Wrapping up
A productive backend CLI setup is not one large tool. It is a small set of focused tools that work together:
curl -s https://api.example.com/users \
| jq '.items[] | select(.active) | .email'
Use curl or xh to send requests, jq to process responses, ngrok and mkcert for local access, watchexec for the edit-run loop, and Docker for disposable infrastructure.
apidog-cli connects that terminal workflow back to the API endpoints, environments, and test scenarios your team maintains. Download Apidog to set up a project, then run its scenarios from the command line in your CI pipeline.
Top comments (0)