Hermit is an 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, sensible defaults, configurable.
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
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.
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
hermit --specs my-api.openapi.yml other-api.openapi.yml
# Create a project -- the response reflects the name you sent
curl -s -X POST http://localhost:8532/projects \
-H 'Content-Type: application/json' \
-d '{"name": "Acme Redesign", "status": "active"}' | jq .
# {
# "id": "foxtrot",
# "name": "Acme Redesign",
# "status": "active",
# ...
# }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
curl -s -X POST http://localhost:8532/projects/abc/tasks \
-H 'Content-Type: application/json' \
-d '{"type": "feature", "storyPoints": 8}' | jq .type
# "feature"
# Creating a "bug" task returns a BugTask shape
curl -s -X POST http://localhost:8532/projects/abc/tasks \
-H 'Content-Type: application/json' \
-d '{"type": "bug", "severity": "high"}' | jq .type
# "bug"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 (if --use-examples) |
| 3 | default in schema |
Field has a default value and no example (if --use-examples) |
| 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.
See install.md.
See cargo.md.
See docker.md.
Run Hermit against your spec (replace the path with your actual spec file):
hermit --specs ~/Documents/dev/hermit/specs_assets/taskflow.openapi.ymlYou can point to a directory containing multiple specs to load them all at once -- Hermit merges their routes and loads them in parallel:
hermit --specs-dir ~/Documents/dev/hermit/specs_assetsTo see what arguments are available, run:
hermit --helpStop the server with Ctrl+C, or if it's running in the background:
kill $(lsof -ti :8532)Replacing the port number at need.
See options.md.
See PRIVACY.md.
See UNLICENSE.
And now some dev stuff
Load multiple specs in one command:
cargo run --release -- --specs-dir specs_assetsThe server listens on port 8532 by default. Override with --port.
To see what arguments are available, run:
hermit --helpInstall just:
cargo install justInstall dev tools:
just setupIn 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.
Requires the server to be running. Run with Bruno:
cd api_tests/hermit_api_tests && npx --yes @usebruno/cli run --env hermit_env --reporter-html test_report.html --reporter-json test_report.jsonSee docker.dev.md.
See architecture.dev.md.
See docs/dev