This was originally published in my blog here
TLDR; modern REST clients follow a collections-first approach that breaks down with growing complexity of microservices and devops. I am introducing a service-first design philosophy, where each service is a self-contained unit with its own endpoints, versions, history and evolution. All of this with a secure by design approach, guardrails for unsafe requests, git-native, local-only, native application built with Tauri framework. XRest is a highly experimental prototype that I built and am actively using for my personal/pet projects. This post explains the philosophy, walks through the functionality with screenshots, and invites feedback from developers facing similar microservices workflow pain.
My story
I started developing APIs and webpages when XML was the preferred option of communications between two systems. I was wide eyed when AJAX, JSON and HTTP API revolution took over the world. Those days, I used firefox with a few plugins to inspect API endpoints, and then progressed into postman, insomnia, hoppscotch, bruno over the last two decades. They are all great, developed by brilliant engineers and teams with a vision to support the developer experience.
There were also revolutionary Microservices and DevOps movements that changed the way I worked. 10 years ago, I used to develop and maintain just one application, with one context path and one auth type. Today, I build and maintain more than a handful of applications. Each of those have different auth mechanisms, request payloads, versions, environments, the list goes on. Today, none of the REST clients are working for me anymore.
What most, if not all, REST clients are optimized for is quick onboarding. Want to try an API? Click add, paste the URL, select the method, add request details, save—done. Another endpoint from the same service? Click, paste, select, save. Simple enough.
Slowly, this model introduces entropy. The URL needs to point to QA—make a copy, change the URL, save. Dev has a different endpoint version coming—another copy, modify everything, save again. Too many duplicates to manage manually, so you build an environment. Now you need to figure out which variables go where and sync them across dozens of requests. Auth tokens? That's a separate request to a different endpoint, which means another environment, more variables to manage, more naming conventions to remember. Folder names that made sense for three requests become meaningless with thirty. Sharing this setup with teammates means exporting collections, syncing environment files, explaining which secrets go where.
And URLs are not the only ones that change, payloads, headers, params all change. They all change depending on the environments.
Then there are a lot of devs and teams who have access to production as well, me included. There are times I have to query production, and it is not safe by default, which makes me nervous about what I am doing. I have accidentally hit production URLs, only realizing that auth or environment was incorrect. I cannot share production details to everyone either, and that is another friction point that I always have to remember while exporting collections.
What started as "quick onboarding" became a maintenance nightmare.
What if there was a REST client, that had an opinionated view of how services need to be managed. Not requests or collections, the service as a whole, from its inception and its evolution, with guard rails. An opinionated approach and design, where everything required for that service is contained and managed together—"right first time".
Service-first design
For many years, I thought the HTTP clients was a solved problem space. Existing tools handled the problem they set out to solve, which is to help teams quickly onboard and test APIs. But they weren't designed for long-term management across dozens of services. Same problem space, different time perspectives.
Service-first design treats each service as the primary unit of organization, with endpoints, environments, authentication, and configurations scoped to that service boundary rather than globally managed collections.
In order to solve this problem I applied bounded context thinking to this dev-centric tool. Just as microservices organize code by business domains rather than technical layers, service-first organizes interactions by service boundaries rather than HTTP method collections. Each service becomes a bounded context with its own environments, auth, safety rules, and evolutionary history — eliminating the cross-service pollution that happens when everything shares global state.
And to test this out, I built an HTTP client. I am calling this XRest right now, and it is highly experimental. It works for me, and I have stopped using other clients already.
XRest - Service First, Git Native API Client
XRest is built with modern, lightweight technologies:
Rust backend via Tauri for native performance and security
Vue 3 + TypeScript for reactive UI
Shadcn-vue for accessible, composable components
SQLite for local history storage
YAML for human-readable configuration
Core Features
Service Management
Create and manage services as self-contained units
Service-level authentication with pre-flight token acquisition
Environment definitions scoped to each service (DEV, STAGING, PROD)
Unsafe environment guardrails with mandatory confirmation dialogs
Import from a swagger / openapi doc
Endpoint Operations
Full HTTP method support: GET, POST, PUT, DELETE, PATCH
Content types:
application/json,text/plain,application/x-www-form-urlencodedRequest configuration: params, headers, body
Automatic auth inheritance from service configuration
Secret and environment variable support in editable fields
Import from curl
Version Control & History
Git-native architecture with automatic commits for all configuration changes
Service definitions stored as YAML files in your local directory
Schema specification in development to support pluggable storage backends
Basic git status in the service settings view
Per-endpoint revision history showing request evolution and backed up into git
Global execution history stored in local SQLite database (not git backed)
Security
System keychain integration (macOS) for secret storage
Environment-based safety controls for production access
Others
Native desktop application (Tauri + Rust + Vue.js)
Dark mode support
Here are a few initial screenshots and features.
Main page
The service sidebar on the left lists all your services with their active environment. The main area is empty until you select an endpoint or create one. Two quick-action buttons are at the bottom: New Service and New Endpoint.
Add a new service
If you click the plus icon on the sidebar, it will show more options - Add New Service, Add New Endpoint, Import from Directory, Import from Swagger.
Add a new service: A three-field form: Service Name, Save Directory (local path where YAML files live), and a toggle for Service Authentication if the service needs an auth token.
Environment variables setup: The second step of service creation. A table where you define variables (like BASE_URL) with columns for each environment (Dev, Stage, Prod). Each environment gets its own value for the same variable.
Add a new endpoint
This is a small dialog scoped to a service. You pick the service, give the endpoint a name, select the HTTP method, and define the path. The endpoint inherits the service's environments and auth automatically.
Request panel
The main workspace. Left sidebar shows the endpoint tree under the service. The top bar shows the resolved BASE_URL for the active environment. Tabs for Params, Auth, Headers, Body, History, and Preflight. The Send button is on the right.
Clicking the environment badge on the service opens a dropdown (DEV, STAGE, PROD). Switching environment changes the resolved BASE_URL across all endpoints in that service instantly.
When the active environment is PROD, the service badge turns red and the Send button turns red.
Clicking Send on a PROD request triggers a confirmation modal. It states which environment is marked unsafe, asks for explicit confirmation, and shows a countdown (10 seconds) after which it auto-cancels. You have to actively click "I Accept the Risk" to proceed.
Service settings
Service level settings which contains General Information (name, base directory), Service Authentication config (auth type selector, pre-flight toggle), Git Status, and the Shared Environments & Variables table. Each environment column has an UNSAFE toggle.
Secrets and environment variables
XRest keeps sensitive values out of plain text. Secrets are created once and stored securely in your macOS Keychain. From there, you have two ways to use them:
Directly in any text field using {{secret.SECRET_KEY}} syntax, or mapped to an environment variable and referenced using {{ENV_NAME}}. The second approach exists because not every environment needs secrets. A local DEV setup might use hardcoded values, while STAGE and PROD pull from the Keychain. By mapping secrets through environment variables, each environment can define its own resolution strategy or skip secrets entirely.
Environment variables themselves follow the same {{ENV_NAME}} interpolation and work across params, headers, URLs, and body fields.
In the variables table, clicking a cell reveals a "Link Secret" option. This lets you map a Keychain secret to a specific environment variable. DEV might have a hardcoded value while STAGE and PROD pull from secrets.
When typing in any field (URL, params, body, headers), typing {{secret. triggers an autocomplete dropdown listing all available secrets from the Keychain. Values are masked with dots.
Service Level Auth ( pre-flight auth )
The settings page lets you configure a request that runs before the actual request. The primary use case is that the service needs a token before any endpoint call. You define the token endpoint, its payload, and map the response (e.g., the access_token field) to a variable that the main request uses automatically. This runs transparently on every Send, so you never manually fetch and paste tokens. There is also an option to cache the token based on the auth response model.
Endpoint history
The History tab shows a numbered version list of the endpoint. Each version is timestamped. Expanding a version shows a diff of what changed (URL, params, body). A "Restore This Version" button lets you roll back to any previous state. Each version syncs to the YAML file and git automatically.
Other Features
Import from Swagger / OpenAPI
Import from CURL
Export to curl, axios, java and kotlin
Global history with filters
What Next?
I am exploring whether this design resonates with the developer community. You are welcome to try out the pre-alpha versions for Mac, click here to download it. You may be greeted with a Mac security warning, and that can be bypassed in Settings > Privacy and Security.
I'm looking for
Feedback on whether service-first design resonates
Developers who've felt similar pain with existing tools
Contributors who want to help build this
If you've managed multiple microservices and felt the same friction, I'd love to hear whether service-first design makes sense to you. Drop your thoughts in the comments or open a discussion on GitHub or join me on Discord
As for features and roadmap, I have a lot of exciting ones to work on that helps me to manage services more efficiently. Some of them are
Integration with password managers (1Password, Bitwarden)
Custom env support and management
Secret manager support (AWS, GCP, Vault)
Windows and Linux testing and releases
Manual git commit workflow
Migrating from postman, insomnia and others
And a stable release
XRest is MIT licensed and available at Github
















Top comments (0)