🦀🐚 Beavuck Hermit
Hermit is a zero-config OpenAPI mock server. Point it at a spec file, and it starts serving lightning-fast schema-accurate responses out of the box -- no stubs to write, no configuration.
At the moment, it is made for running on Linux AMD64 platforms (x86_64) only.
📊 Status
📗 Use cases
Hermit is useful whenever you need an API to be available but don't want to run the real backend:
- Frontend development -- build and iterate against real HTTP endpoints without depending on a live backend
- Integration and E2E testing -- run tests in CI against a predictable, schema-accurate server with no database or external services
- Contract validation -- verify that your OpenAPI spec produces the shapes your consumers actually expect
🔍 How it works
sequenceDiagram
participant Client
participant Hermit
participant Spec as OpenAPI Spec
Note over Hermit, Spec: Startup -- once (specs loaded in parallel)
Hermit ->> Spec: Read & parse YAML (one thread per spec file)
Hermit ->> Hermit: Resolve $refs, flatten allOf/oneOf
Hermit ->> Hermit: Pre-generate mock responses for all routes
Note over Client, Hermit: Runtime -- per request
Client ->> Hermit: GET /projects/{projectId}
Hermit -->> Client: 200 {"id": "abc", "name": "echo", ...}
Client ->> Hermit: POST /projects {"name": "my project"}
Hermit ->> Hermit: Merge request body into mock response
Hermit -->> Client: 201 {"id": "abc", "name": "my project", ...}
All schema work (ref resolution, composition, value generation) happens once at startup. Requests are served from an in-memory map with no I/O.
👓 Request body echo
For POST, PUT, and PATCH requests, Hermit merges the fields you send into the mock response. This means your code
sees its own writes reflected back -- the most useful behavior for frontend development:
# Start Hermit
# Create a project -- the response reflects the name you sent
|
# {
# "id": "foxtrot",
# "name": "Acme Redesign",
# "status": "active",
# ...
# }
🧬 Polymorphic responses
When a POST endpoint uses oneOf with a discriminator, Hermit inspects the request body to pick the right response
shape:
# Creating a "feature" task returns a FeatureTask shape
|
# "feature"
# Creating a "bug" task returns a BugTask shape
|
# "bug"
📄 Response generation
Response field values are resolved in priority order:
| Priority | Source | When |
|---|---|---|
| 1 | Request body fields | POST, PUT, PATCH -- caller's values win, except for readOnly fields |
| 2 | example in schema |
Field has an explicit example value |
| 3 | default in schema |
Field has a default value and no example |
| 4 | Random value | Fallback -- random word, number, boolean, or format-aware value (UUID, date-time, …) |
Fields marked readOnly: true in the schema are never overridden by request body values. Fields marked
writeOnly: true are excluded from generated responses entirely.
🛠️ Install
See install.md.
📦 🦀 Install and run from Cargo
See cargo.md.
🚀 Quick start
Run Hermit against your spec (replace the path with your actual spec file):
You can point to a directory containing multiple specs to load them all at once -- Hermit merges their routes and loads them in parallel:
To see what arguments are available, run:
Stop the server with Ctrl+C, or if it's running in the background:
🔒 Privacy
See PRIVACY.md.
📜 License
See UNLICENSE.
And now some dev stuff
🛞 Build and run
Load multiple specs in one command:
The server listens on port 8532 by default. Override with --port.
To see what arguments are available, run:
🔧 Development setup
Install just:
Install dev tools:
In RustRover, go to Settings > Version Control > Commit > Advanced commit checks and choose the pre-commit
configuration to run these checks automatically on commit.
Explore justfile for available commands.
✅ API tests
Requires the server to be running. Run with Bruno:
&&
🐳 Docker
See DOCKER.md.
🏗️ Architecture
See docs/architecture.md.