A real cloud simulator. It simulates real cloud resources (AWS, Azure, GCP) entirely in-memory on your machine.
See the code
In-memory AWS, Azure & GCP — run it as a local cloud, or mock in-process.
Any language. $0. Deterministic. Resettable.
cloudemu emulates the cloud APIs of AWS, Azure, and GCP entirely in memory. Point the real SDKs or CLIs — in any language — at a local endpoint, and your unmodified code runs against an in-memory backend. No accounts, no network, no bill; instant, deterministic, and resettable.
It emulates the API control surface your code actually calls, not real infrastructure — which is exactly what removes cost, latency, and flakiness from the loop.
cloudemu serve (or docker run … ghcr.io/stackshy/cloudemu). A long-lived local cloud you point any app, CLI, or SDK at, LocalStack-style.httptest.NewServer your tests point the real SDKs at. No container.cloud.EC2.RunInstances(ctx, …).Get the cloudemu CLI — pick whichever fits your setup:
# Homebrew (macOS / Linux)
brew install stackshy/tap/cloudemu
# One-line install script (macOS / Linux) — downloads the release binary and verifies its checksum
curl -fsSL https://raw.githubusercontent.com/stackshy/cloudemu/HEAD/install.sh | sh
# Go toolchain
go install github.com/stackshy/cloudemu/v2/cmd/cloudemu@latest
# Docker — no install, just run the server
docker run --rm -p 4566:4566 -p 4568:4568 -p 4569:4569 -p 4570:4570 \
ghcr.io/stackshy/cloudemu:latest
Prebuilt binaries for every OS/arch are on the releases page. The install script honours a version arg and an INSTALL_DIR override, e.g. ... | sh -s -- v2.5.0 or INSTALL_DIR="$HOME/bin" ... | sh. To use cloudemu as a Go library instead, see Quickstart below.
To integrate cloudemu with an existing application, run it in server mode and set your SDK's endpoint (AWS_ENDPOINT_URL / BaseEndpoint, option.WithEndpoint, or the Azure ARM endpoint override), then point your already-running app or services at it. Do not write a _test.go file to spin it up in-process for integration — that's library mode, for unit tests inside cloudemu-aware Go code (shown last).
docker run --rm -p 4566:4566 -p 4568:4568 -p 4569:4569 -p 4570:4570 \
ghcr.io/stackshy/cloudemu:latest
# AWS 4566 · Azure 4568 (TLS) · GCP 4569 · Kubernetes 4570 (TLS)
# Apple Silicon: add --platform linux/amd64 if the amd64 image won't start natively.
Point any existing SDK or CLI at it — nothing cloudemu-specific:
export AWS_ACCESS_KEY_ID=test AWS_SECRET_ACCESS_KEY=test AWS_DEFAULT_REGION=us-east-1
aws --endpoint-url http://127.0.0.1:4566 s3 mb s3://demo
aws --endpoint-url http://127.0.0.1:4566 s3 ls
The same override in code — your app builds its client exactly as in production, only the endpoint changes:
// AWS (aws-sdk-go-v2) — or just export AWS_ENDPOINT_URL=http://127.0.0.1:4566
client := s3.NewFromConfig(cfg, func(o *s3.Options) {
o.BaseEndpoint = aws.String("http://127.0.0.1:4566")
o.UsePathStyle = true
})
// GCP (cloud.google.com/go)
gcs, _ := storage.NewClient(ctx,
option.WithEndpoint("http://127.0.0.1:4569"),
option.WithoutAuthentication())
// Azure (azure-sdk-for-go) — ARM endpoint override (HTTPS, self-signed cert)
cloudCfg := cloud.Configuration{Services: map[cloud.ServiceName]cloud.ServiceConfiguration{
cloud.ResourceManager: {Endpoint: "https://127.0.0.1:4568", Audience: "https://management.azure.com"},
}}
Now the live code path runs end-to-end — the real app writes an object and reads it straight back from the in-memory backend (no assertions, no test harness):
_, _ = client.PutObject(ctx, &s3.PutObjectInput{
Bucket: aws.String("demo"), Key: aws.String("hello.txt"),
Body: strings.NewReader("hi from my app")})
out, _ := client.GetObject(ctx, &s3.GetObjectInput{
Bucket: aws.String("demo"), Key: aws.String("hello.txt")})
// out.Body streams "hi from my app"
kubectl apply -f deployment.yaml round-trips against the in-memory cluster, and curl -X POST http://127.0.0.1:4566/_cloudemu/reset clears all state between tests. Full flags and per-SDK wiring: docs/standalone-server.md.
For Go unit tests you own, skip the server and run it in-process:
cloud := cloudemu.NewAWS()
ts := httptest.NewServer(awsserver.NewFromProvider(cloud))
defer ts.Close()
cfg, _ := config.LoadDefaultConfig(ctx) // credentials/region are ignored
client := s3.NewFromConfig(cfg, func(o *s3.Options) {
o.BaseEndpoint = aws.String(ts.URL)
o.UsePathStyle = true
})
client.PutObject(ctx, &s3.PutObjectInput{ /* … */ }) // hits the in-memory backend
go get github.com/stackshy/cloudemu/v2 (Go 1.25+) · docs/getting-started.md
76 AWS · 75 Azure · 55 GCP services — 173 service interfaces, 3,700+ operations — plus a real in-memory Kubernetes data plane. The always-current, generated list is docs/coverage; the highlights:
The Kubernetes data plane does real CRUD, server-side apply, and watch streaming — so client-go informers work — and converges controllers synchronously (a Deployment materializes Pods to Running on write). It runs a real scheduler (node & inter-pod affinity, topology spread, scoring), an opt-in multi-node cluster (--k8s-nodes N, taints/tolerations, dynamic node add/remove), and exec/attach over WebSocket. See docs/services.md.
apply / plan / destroy against cloudemu, proven idempotent in CI. Zero boilerplate with the cloudemu-tf wrapper. → docs/terraform.mdBy default everything is in memory — no real database, cache, or code runs. When you want a resource to do the real thing — actual SQL, real Redis, your uploaded function or container — opt in with config.With<X>Engine(...). Two sibling modules keep the heavy dependencies out of the core:
python3/node for Lambda/Functions code.The in-memory default is unchanged; Provider.Close() tears down whatever you wired.
State is in memory and resettable, so it's ephemeral by default. When you want it to survive a restart, snapshot the whole emulator — every stateful service across all four providers, identity-preserving — to a single JSON file and restore it into a fresh instance. Run the background server with --persist, capture named states with cloudemu snapshot save/load, hit GET/POST /_cloudemu/snapshot, or drive it from Go with the persist package. Named states also support time travel — POST /_cloudemu/snapshot/{name}/rewind restores a checkpoint and …/{from}/fork/{to} branches off it. → docs/persistence.md
cloudemu serve --vcr record --vcr-cassette tape.json tapes the wire traffic; --vcr replay serves it back with no backend, so a captured session reruns deterministically.cloudemu doctor verifies the default ports are free, prints the build version, and reports whether Docker is available.Contributions are welcome — see CONTRIBUTING.md for the dev setup and the branch-from-development flow, and the Code of Conduct. Questions or bugs? Open a GitHub issue; for security, follow SECURITY.md.
MIT
Go
100.0%
A real cloud simulator. It simulates real cloud resources (AWS, Azure, GCP) entirely in-memory on your machine.
See the code
In-memory AWS, Azure & GCP — run it as a local cloud, or mock in-process.
Any language. $0. Deterministic. Resettable.
cloudemu emulates the cloud APIs of AWS, Azure, and GCP entirely in memory. Point the real SDKs or CLIs — in any language — at a local endpoint, and your unmodified code runs against an in-memory backend. No accounts, no network, no bill; instant, deterministic, and resettable.
It emulates the API control surface your code actually calls, not real infrastructure — which is exactly what removes cost, latency, and flakiness from the loop.
cloudemu serve (or docker run … ghcr.io/stackshy/cloudemu). A long-lived local cloud you point any app, CLI, or SDK at, LocalStack-style.httptest.NewServer your tests point the real SDKs at. No container.cloud.EC2.RunInstances(ctx, …).Get the cloudemu CLI — pick whichever fits your setup:
# Homebrew (macOS / Linux)
brew install stackshy/tap/cloudemu
# One-line install script (macOS / Linux) — downloads the release binary and verifies its checksum
curl -fsSL https://raw.githubusercontent.com/stackshy/cloudemu/HEAD/install.sh | sh
# Go toolchain
go install github.com/stackshy/cloudemu/v2/cmd/cloudemu@latest
# Docker — no install, just run the server
docker run --rm -p 4566:4566 -p 4568:4568 -p 4569:4569 -p 4570:4570 \
ghcr.io/stackshy/cloudemu:latest
Prebuilt binaries for every OS/arch are on the releases page. The install script honours a version arg and an INSTALL_DIR override, e.g. ... | sh -s -- v2.5.0 or INSTALL_DIR="$HOME/bin" ... | sh. To use cloudemu as a Go library instead, see Quickstart below.
To integrate cloudemu with an existing application, run it in server mode and set your SDK's endpoint (AWS_ENDPOINT_URL / BaseEndpoint, option.WithEndpoint, or the Azure ARM endpoint override), then point your already-running app or services at it. Do not write a _test.go file to spin it up in-process for integration — that's library mode, for unit tests inside cloudemu-aware Go code (shown last).
docker run --rm -p 4566:4566 -p 4568:4568 -p 4569:4569 -p 4570:4570 \
ghcr.io/stackshy/cloudemu:latest
# AWS 4566 · Azure 4568 (TLS) · GCP 4569 · Kubernetes 4570 (TLS)
# Apple Silicon: add --platform linux/amd64 if the amd64 image won't start natively.
Point any existing SDK or CLI at it — nothing cloudemu-specific:
export AWS_ACCESS_KEY_ID=test AWS_SECRET_ACCESS_KEY=test AWS_DEFAULT_REGION=us-east-1
aws --endpoint-url http://127.0.0.1:4566 s3 mb s3://demo
aws --endpoint-url http://127.0.0.1:4566 s3 ls
The same override in code — your app builds its client exactly as in production, only the endpoint changes:
// AWS (aws-sdk-go-v2) — or just export AWS_ENDPOINT_URL=http://127.0.0.1:4566
client := s3.NewFromConfig(cfg, func(o *s3.Options) {
o.BaseEndpoint = aws.String("http://127.0.0.1:4566")
o.UsePathStyle = true
})
// GCP (cloud.google.com/go)
gcs, _ := storage.NewClient(ctx,
option.WithEndpoint("http://127.0.0.1:4569"),
option.WithoutAuthentication())
// Azure (azure-sdk-for-go) — ARM endpoint override (HTTPS, self-signed cert)
cloudCfg := cloud.Configuration{Services: map[cloud.ServiceName]cloud.ServiceConfiguration{
cloud.ResourceManager: {Endpoint: "https://127.0.0.1:4568", Audience: "https://management.azure.com"},
}}
Now the live code path runs end-to-end — the real app writes an object and reads it straight back from the in-memory backend (no assertions, no test harness):
_, _ = client.PutObject(ctx, &s3.PutObjectInput{
Bucket: aws.String("demo"), Key: aws.String("hello.txt"),
Body: strings.NewReader("hi from my app")})
out, _ := client.GetObject(ctx, &s3.GetObjectInput{
Bucket: aws.String("demo"), Key: aws.String("hello.txt")})
// out.Body streams "hi from my app"
kubectl apply -f deployment.yaml round-trips against the in-memory cluster, and curl -X POST http://127.0.0.1:4566/_cloudemu/reset clears all state between tests. Full flags and per-SDK wiring: docs/standalone-server.md.
For Go unit tests you own, skip the server and run it in-process:
cloud := cloudemu.NewAWS()
ts := httptest.NewServer(awsserver.NewFromProvider(cloud))
defer ts.Close()
cfg, _ := config.LoadDefaultConfig(ctx) // credentials/region are ignored
client := s3.NewFromConfig(cfg, func(o *s3.Options) {
o.BaseEndpoint = aws.String(ts.URL)
o.UsePathStyle = true
})
client.PutObject(ctx, &s3.PutObjectInput{ /* … */ }) // hits the in-memory backend
go get github.com/stackshy/cloudemu/v2 (Go 1.25+) · docs/getting-started.md
76 AWS · 75 Azure · 55 GCP services — 173 service interfaces, 3,700+ operations — plus a real in-memory Kubernetes data plane. The always-current, generated list is docs/coverage; the highlights:
The Kubernetes data plane does real CRUD, server-side apply, and watch streaming — so client-go informers work — and converges controllers synchronously (a Deployment materializes Pods to Running on write). It runs a real scheduler (node & inter-pod affinity, topology spread, scoring), an opt-in multi-node cluster (--k8s-nodes N, taints/tolerations, dynamic node add/remove), and exec/attach over WebSocket. See docs/services.md.
apply / plan / destroy against cloudemu, proven idempotent in CI. Zero boilerplate with the cloudemu-tf wrapper. → docs/terraform.mdBy default everything is in memory — no real database, cache, or code runs. When you want a resource to do the real thing — actual SQL, real Redis, your uploaded function or container — opt in with config.With<X>Engine(...). Two sibling modules keep the heavy dependencies out of the core:
python3/node for Lambda/Functions code.The in-memory default is unchanged; Provider.Close() tears down whatever you wired.
State is in memory and resettable, so it's ephemeral by default. When you want it to survive a restart, snapshot the whole emulator — every stateful service across all four providers, identity-preserving — to a single JSON file and restore it into a fresh instance. Run the background server with --persist, capture named states with cloudemu snapshot save/load, hit GET/POST /_cloudemu/snapshot, or drive it from Go with the persist package. Named states also support time travel — POST /_cloudemu/snapshot/{name}/rewind restores a checkpoint and …/{from}/fork/{to} branches off it. → docs/persistence.md
cloudemu serve --vcr record --vcr-cassette tape.json tapes the wire traffic; --vcr replay serves it back with no backend, so a captured session reruns deterministically.cloudemu doctor verifies the default ports are free, prints the build version, and reports whether Docker is available.Contributions are welcome — see CONTRIBUTING.md for the dev setup and the branch-from-development flow, and the Code of Conduct. Questions or bugs? Open a GitHub issue; for security, follow SECURITY.md.
MIT
Go
100.0%