Getting Started with Rift
Rift is a high-performance, Mountebank-compatible HTTP/HTTPS mock server. This guide will help you install Rift and create your first imposter.
Installation
Docker (Recommended)
The easiest way to run Rift is using Docker:
# Pull the latest image
docker pull zainalpour/rift-proxy:latest
# Run Rift on port 2525 (Mountebank-compatible admin port)
docker run -p 2525:2525 zainalpour/rift-proxy:latest
Publish every imposter port you intend to call from the host as well (for example -p 4545:4545), and see Docker for the -static image. With no --api-key, the admin API is open to anyone who can reach the port; Rift logs a warning saying so at startup.
Homebrew (macOS/Linux)
brew tap achird-labs/rift
brew install rift
This installs four binaries: rift (the server), rift-lint, rift-tui, and rift-verify.
Download Binary
Release archives are published per platform on the releases page, named rift-vX.Y.Z-<target>.tar.gz (.zip on Windows). Each unpacks to a bin/ directory containing rift, rift-lint, rift-tui, and rift-verify.
# macOS (Apple Silicon) — substitute your platform triple from the list below
VERSION=v0.17.0
TARGET=aarch64-apple-darwin
curl -LO https://github.com/achird-labs/rift/releases/download/$VERSION/rift-$VERSION-$TARGET.tar.gz
tar -xzf rift-$VERSION-$TARGET.tar.gz
sudo mv rift-$VERSION-$TARGET/bin/* /usr/local/bin/
rift --version
Available platform triples:
- Linux:
x86_64-unknown-linux-gnu,aarch64-unknown-linux-gnu,x86_64-unknown-linux-musl,aarch64-unknown-linux-musl - macOS:
x86_64-apple-darwin,aarch64-apple-darwin - Windows:
x86_64-pc-windows-msvc
Cargo (crates.io)
cargo install rift-http-proxy
Note that cargo names the installed binary after the crate — rift-http-proxy, not rift. Every other install method above puts it on your PATH as rift, which is the name used throughout these docs.
Build from Source
Requires Rust 1.92+ (see rust-version in Cargo.toml):
git clone https://github.com/achird-labs/rift.git
cd rift
cargo build --release
./target/release/rift-http-proxy
Node.js / npm
For Node.js projects, install the official npm package:
npm install @rift-vs/rift
Usage:
import { rift, imposter, onGet, okJson, times } from '@rift-vs/rift';
await using engine = await rift.embedded(); // or rift.connect(url) / rift.spawn()
const users = await engine.create(
imposter('users').stub(onGet('/api/users/1').willReturn(okJson({ id: 1, name: 'Alice' }))));
await users.verify(onGet('/api/users/1'), times(1));
The Mountebank-compatible rift.create({ port }) API stays available as a permanent drop-in if you are migrating.
See the Node.js Integration Guide for complete documentation.
Java / JVM
For JVM projects, add the official rift-java SDK to your test scope:
<dependency>
<groupId>io.github.achird-labs</groupId>
<artifactId>rift-java-core</artifactId>
<scope>test</scope>
</dependency>
Usage:
try (Rift rift = Rift.embedded()) { // or Rift.connect(uri) / Rift.spawn()
Imposter users = rift.create(
imposter("users").stub(onGet("/api/users/1").willReturn(okJson("{\"id\":1}"))));
users.verify(onGet("/api/users/1"), times(1));
}
Rift.embedded() runs the engine in-process over Panama FFM, so no separate binary or container is needed; Rift.spawn() manages a downloaded binary for you, and Rift.connect(uri) targets any running admin endpoint. See the rift-java documentation for the JUnit 5, Spring, and Testcontainers integrations.
Go
For Go projects, add the official rift-go SDK and fetch the native library once:
go get github.com/achird-labs/rift-go
go run github.com/achird-labs/rift-go/cmd/rift-fetch@latest -version v0.17.0
Usage:
func TestUserLookup(t *testing.T) {
users := rifttest.Imposter(t, rift.NewImposter("users").
Stub(rift.OnGet("/api/users/1").Return(rift.OKJSON(`{"id":1}`))))
callSUT(t, users.BaseURL())
rifttest.AssertReceived(t, users, rift.OnGet("/api/users/1"), rift.Once())
}
The engine runs in-process through purego rather than cgo, so CGO_ENABLED=0 keeps working and no C toolchain is needed. rift.Spawn(ctx, …) manages a binary instead, and rift.Connect(url, …) targets any running admin endpoint — neither needs the native library. See the rift-go documentation.
Scala 3
libraryDependencies += "io.github.achird-labs" %% "rift-scala-zio" % "0.1.4" % Test
There is a module per effect system — ZIO, Cats Effect 3 / FS2, or no effect system at all — over one shared typed model. See rift-scala.
All four SDKs
Install snippets, hello-worlds, the transport matrix and the version-compatibility table for Java, Scala, Node/TypeScript and Go live in Language SDKs.
Verify Installation
Once Rift is running, verify it’s working:
# Liveness
curl http://localhost:2525/health
# {"status":"ok"}
# The admin API root
curl http://localhost:2525/
# Expected response (hrefs are absolute, built from the admin host and port):
{
"_links": {
"config": { "href": "http://localhost:2525/config" },
"imposters": { "href": "http://localhost:2525/imposters" },
"logs": { "href": "http://localhost:2525/logs" }
}
}
Your First Imposter
Create a simple HTTP mock that responds to GET requests:
curl -X POST http://localhost:2525/imposters \
-H "Content-Type: application/json" \
-d '{
"port": 4545,
"protocol": "http",
"name": "My First Imposter",
"stubs": [{
"predicates": [{
"equals": {
"method": "GET",
"path": "/api/greeting"
}
}],
"responses": [{
"is": {
"statusCode": 200,
"headers": { "Content-Type": "application/json" },
"body": { "message": "Hello from Rift!" }
}
}]
}]
}'
Test your imposter:
curl http://localhost:4545/api/greeting
# Response:
{"message":"Hello from Rift!"}
If Rift runs in Docker, start it with -p 4545:4545 as well, or the imposter is unreachable from the host. A request that matches no stub gets 200 with an empty body, as in Mountebank.
Load Existing Configuration
If you have an existing Mountebank configuration file, load it directly:
# Using Docker (publish every port your imposters listen on)
docker run -p 2525:2525 -p 4545:4545 -v $(pwd)/imposters.json:/imposters.json \
zainalpour/rift-proxy:latest --configfile /imposters.json
# Using binary
rift --configfile imposters.json
Mountebank’s EJS tags (<% include %>, <%- stringify() %>, <%= process.env.X %>) work in the file; any other <% %> tag is refused, so pass --no-parse if a file holds a literal <%. YAML is accepted too — see Configuration.
Example imposters.json:
{
"imposters": [
{
"port": 4545,
"protocol": "http",
"stubs": [
{
"predicates": [{ "equals": { "path": "/users" } }],
"responses": [{ "is": { "statusCode": 200, "body": "[]" } }]
}
]
}
]
}
Next Steps
- Quick Start Tutorial - Detailed walkthrough
- Node.js Integration - npm package for Node.js projects
- Language SDKs - Java, Scala, Node/TypeScript and Go, with the transport and version-compatibility matrices
- Java / JVM SDK - rift-java for JUnit 5, Spring, and Testcontainers
- Scala SDK - rift-scala for ZIO, Cats Effect, FS2, and zio-bdd
- Go SDK - rift-go for
testing.T, embedded via purego (no cgo) - Predicates Guide - Request matching
- Responses Guide - Response configuration
- Migration Guide - Switching from Mountebank