Every Ema site built with Ema.runSite exposes a small CLI out of the box. It picks one of two subcommands and a handful of flags, hands the result to your EmaSite’s siteInput, and does the right thing.
Subcommands
-
run— start the Live Server. Also the default when no subcommand is given. -
gen DEST— do a one-shot static build intoDESTand exit.
Flags
Under run:
-
--host HOST— interface to bind to. Defaults to127.0.0.1. -
--port PORT— TCP port. If omitted, a random free port is chosen and printed at startup. -
--no-ws— disable the websocket that powers hot-reload. The server still serves HTML, it just won’t push updates.
Top-level:
-
-v,--verbose— drop the log level fromInfotoDebug.
How the CLI reaches your code
Ema.runSite parses argv into an Ema.CLI.Cli and routes the contained Ema.CLI.Action to your site: Generate dest triggers a static build, Run RunArgs{..} starts the live server. Your EmaSite instance receives the Action via siteInput, so you can condition behavior on whether Ema is generating or live-serving — e.g. skipping expensive watchers during a one-shot build.
Handing Ema a pre-built Cli
If you want to control CLI parsing yourself — adding custom subcommands, re-ordering flags, or embedding Ema inside a larger tool — use runSiteWith instead of runSite and pass a SiteConfig carrying your own Ema.CLI.Cli value:
import Ema qualified
import Ema.CLI qualified
main :: IO ()
main = do
cli <- myCustomParser -- your own optparse-applicative
let cfg = Ema.SiteConfig cli def
void $ Ema.runSiteWith @MyRoute cfg mySiteArg
This is the escape hatch when the stock Ema.CLI.cliParser doesn’t fit your UX.
Composing custom flags under run
Ema.CLI.runArgsParser :: Parser RunArgs is exported so downstream applications can splice Ema’s --host / --port / --no-ws parser into their own run subcommand alongside custom flags. Prefer this over rebuilding hostParser/portParser/noWebSocketParser by hand — if Ema later grows a new run-mode field, the composed parser picks it up automatically.
import Ema.CLI qualified
import Options.Applicative
data RunCmd = RunCmd
{ runEmaArgs :: Ema.CLI.RunArgs
, runMyFlag :: Maybe Int
}
runCmdParser :: Parser RunCmd
runCmdParser = RunCmd
<$> Ema.CLI.runArgsParser
<*> optional (option auto (long "my-flag" <> metavar "N"))
-- When it's time to hand control to Ema, project RunCmd back into Ema.CLI.Cli:
toEmaCli :: RunCmd -> Ema.CLI.Cli
toEmaCli rc = Ema.CLI.Cli
{ Ema.CLI.action = Ema.CLI.Run (runEmaArgs rc)
, Ema.CLI.verbose = False
}