simoom / Use cases / CLI and desktop apps
Inside CLIs, desktop apps and daemons
A local HTTP endpoint without turning your program async
A command-line tool needs a callback for an OAuth login. A desktop app wants to show a live dashboard in the browser. A daemon needs a health and metrics endpoint. None of them should have to adopt an async runtime or a web framework to get there. With simoom you write plain functions, call start(), and keep the rest of your program as it is.
How it sits in your program
start() runs the server on its own threads and returns a handle. Your main thread stays yours: keep running the UI, the CLI or the daemon, then stop() and join() when you are done.
Fast work on the loop
A service runs on the event loop thread and returns an Outcome. Reading state, building a small JSON answer or serving a page from memory is fast enough to do there.
Slow work elsewhere
Anything that waits (a file, a database, a network call) goes to the bounded offload pool with blocking, or to your own threads with Reply::defer. The loop never waits.
use simoom::{Outcome, Reply, Request, Response, Server};
let server = Server::builder()
.listen("127.0.0.1:8080")
.service(|req: &mut Request<'_>, reply: Reply<'_>| -> Outcome {
let owned = req.to_owned_request();
let responder = reply.defer();
std::thread::spawn(move || {
responder.send(Response::text(format!("done: {}", owned.path_str())));
});
Outcome::Done
})
.start()
.unwrap();
Bind to 127.0.0.1 for an endpoint only the local machine can reach. More in services and replies and slow work.
Live updates to the browser
A dashboard needs pushes, not polling. simoom has WebSocket (also over HTTP/2 and HTTP/3, with permessage-deflate) and server-sent events, both without async code.
use simoom::{Reply, Request, Router, WebSocket, WebSocketHandler, WsMessage};
struct Echo;
impl WebSocketHandler for Echo {
fn on_message(&mut self, ws: &mut WebSocket<'_>, msg: WsMessage<'_>) {
match msg {
WsMessage::Text(t) => ws.send_text(t),
WsMessage::Binary(b) => ws.send_binary(b),
}
}
}
let router = Router::new()
.get("/ws", |_: &mut Request<'_>, r: Reply<'_>| r.websocket(Echo));
Guides: WebSocket and streaming and server-sent events. Calling other services from the same program? simoom also has an HTTP client.
Windows, Linux and macOS
| platform | back end | status |
|---|---|---|
| Windows | IOCP | test suite runs (777 tests); cold start and memory measured |
| Linux | epoll, io_uring | test suite runs (791 tests on WSL2); cloud benchmarks |
| macOS | kqueue | compile-checked only |
On a Windows 11 workstation, against the server it replaced (Cameleer's old thread-per-connection server), cold start was 8.04 ms against 9.19 ms, and 1,000 idle connections used 5.1 MB of private memory against 15.2 MB. Windows start-up is measured until the server prints that it is ready, because a connect attempt to a port nobody listens on yet takes about 200 ms to fail there. Source: docs/STATUS.md, 2026-11-09. The Linux start-up figure is from campaign 4, 2026-11-12, on a cloud droplet.
Common questions
How do I embed an HTTP server in a Rust app?
Add simoom, build a Server with Server::builder(), give it a service or a Router, and call start(). It runs on its own threads and returns a handle you can stop() and join(), so the rest of your program keeps running.
Can I add a WebSocket server to a Rust CLI without tokio?
Yes. Implement WebSocketHandler and upgrade a route with Reply::websocket. It works without async, also over HTTP/2 and HTTP/3.
Will a slow handler freeze the server?
It must not run on the loop thread. Send slow work to the offload pool with simoom::blocking, or answer from your own thread with Reply::defer. A stall watchdog also moves a route whose inline handler turns out slow to the offload pool.
Does it run on Windows and macOS?
Yes: IOCP on Windows and kqueue on macOS, epoll or io_uring on Linux. The test suite runs on Windows and Linux; macOS is compile-checked only.
Can simoom serve the files of my web UI?
It has no static-file server. Serve embedded assets from memory with a route, or put the files behind a server such as Caddy if you need directory serving.
Add it to your program
One crate, one function, one call to start().
cargo add simoom