In this post, I will describe how to use Morloc to transform simple functional libraries into composable CLI tools, HTTP/TCP APIs, and UNIX daemons. I’m focusing on one aspect of Morloc. Future posts will explore the underlying polyglot functional programming language, type system, and data marshalling systems.
I will start by defining one simple Morloc module that prints a calendar to the terminal:
module cal (cal, CalConfig)
import root-py
--' Calendar display options
--' unroll: true
--' arg: --cal-config
record CalConfig where
--' Start week on Monday
--' true: --monday
--' false: --sunday
--' default: true
monday_first :: Bool
--' Number of months to show
--' arg: -n/--months
--' default: 1
num_months :: Int
--' Highlight today
--' true: -t/--show-today
--' default: false
highlight_today :: Bool
--' Show week numbers
--' true: -w/--week-numbers
--' default: false
show_week_numbers :: Bool
record Py => CalConfig = "dict"
--' Show a monthly calendar
--' name: cal
--' return: Formatted calendar text
cal :: CalConfig -> Str
source Py from "cal.py" ("show_calendar_wrapper" as cal)
This code exports a function that takes a record of parameters and returns a string showing the calendar. The Morloc program sources Python code from the cal.py file. This file contains idiomatic Python — with no Morloc-specific dependencies — that defines a function for generating a calender string given a config record. The record passed to this function is annotated in the Morloc script with descriptions for each field. These descriptions inform the generation of the CLI tool. For a full overview of the Morloc syntax, see the docs.
This program can be compiled with morloc make to generate the executable
cal. You can install and build this tool with morloc install --build ./cal
. This command both installs the Morloc module and creates the executable cal.
We can access the usage info for this executable:
$ cal -h
Usage: cal [OPTION...]
Show a monthly calendar
Nexus options:
--print Pretty-print output for human consumption
--output-file Print to this file instead of STDOUT
--output-form Output format [json|mpk|voidstar]
Daemon mode:
--daemon Run as a long-lived daemon
--http-port PORT Listen on HTTP port
--port PORT Listen on TCP port
--socket PATH Listen on UNIX socket
Group arguments:
CalConfig: Calendar display options
--cal-config CalConfig
--sunday
default: true
Start week on Monday
-n, --months Int
default: 1
Number of months to show
-t, --show-today
default: false
Highlight today
-w, --week-numbers
default: false
Show week numbers
Return: Str
Formatted calendar text
We can call this command like so:
$ cal --print
February 2026
Mon Tue Wed Thu Fri Sat Sun
----------------------------
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28
The --print option tells the executable to pretty print the output rather than dumping raw JSON.
The Python file cal.py contains the following content (with the body of
show_calendar elided for brevity):
import calendar
from datetime import date
def show_calendar_wrapper(kwargs):
return show_calendar(**kwargs)
def show_calendar(
num_months : int = 1,
monday_first : bool = True,
highlight_today : bool = True,
show_week_numbers : bool = True
) -> str:
...
Note that this is pure idiomatic Python code – no Morloc-specific dependencies or idioms. The Morloc compiler generates the wiring needed to pass data to the Python function.
In addition to the CLI, we can also launch the program as an HTTP server:
$ cal --daemon --http-port 8080 &
[1] 129
$ curl -s localhost:8080/health
{"status":"ok","result":[true]}
$ curl -s localhost:8080/discover | jq .
{
"status": "ok",
"result": {
"name": "cal",
"version": 1,
"commands": [
{
"name": "cal",
"type": "remote",
"return_type": "Str",
"return_schema": "<str>s",
"args": [
{
"kind": "grp",
"metavar": "CalConfig",
"desc": "Calendar display options"
}
],
"desc": "Show a monthly calendar"
}
]
}
}
$ curl -s -X POST localhost:8080/call/cal -d '[{"monday_first":true,"num_months":1,"highlight_today":true,"show_week_numbers":false}]' | jq -r '.result'
February 2026
Mon Tue Wed Thu Fri Sat Sun
----------------------------
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28
We can similarly build TCP and UNIX domain socket daemons. Or build one server that listens over all three:
$ cal --daemon \
--http-port 8080 \
--port 9001 \
--socket /tmp/cal.sock
Now suppose we have a second module that prints the current weather:
module weather (weather, WeatherConfig)
import root-py
--' Weather display options
--' unroll: true
--' arg: --weather-config
record WeatherConfig where
--' City or location name
--' arg: -l/--location
--' default: "New York"
--' literal: true
location :: Str
--' Use metric units
--' true: --metric
--' false: --imperial
--' default: true
metric :: Bool
--' Show compact one-line output
--' true: --compact
--' false: --full
--' default: false
compact :: Bool
record Py => WeatherConfig = "dict"
--' Get current weather for a location
--' name: weather
--' return: Weather report
weather :: WeatherConfig -> Str
source Py from "weather.py" ("get_weather" as weather)
Both of these modules can be used independently as CLI tools or server/daemons. But they are also Morloc modules and can be imported into other Morloc programs. To demonstrate this, let’s define a third module, creatively named foo, that imports both and exports all their terms. This module also defines a new Morloc function that reuses the string output of the cal and weather functions:
module foo (cal, weather, briefing)
import root-py
import cal
import weather
source Py from "briefing.py" ("format_briefing")
format_briefing :: Str -> Str -> Str
--' Morning briefing with calendar and weather
--' return: Combined calendar and weather report
briefing :: CalConfig -> WeatherConfig -> Str
briefing c w = format_briefing (cal c) (weather w)
This new module can be compiled into a new executable (or server/daemon) that composes the original two modules. The three functions exported from this new module are translated into three subcommands.
$ foo -h
Usage: foo [OPTION...] COMMAND [ARG...]
Nexus options:
-h, --help Print this help message
-p, --print Pretty-print output for human consumption
-o, --output-file Print to this file instead of STDOUT
-f, --output-format Output format [json|mpk|voidstar]
Daemon mode:
--daemon Run as a long-lived daemon
--http-port PORT Listen on HTTP port
--port PORT Listen on TCP port
--socket PATH Listen on Unix socket
Commands (call with -h/--help for more info):
cal Show a monthly calendar
weather Get current weather for a location
briefing Morning briefing with calendar and weather
The usage statement for foo inherits documentation through its types, here is the
usage output for foo briefing:
$ foo briefing -h
Usage: foo briefing [OPTION...]
Morning briefing with calendar and weather
Group arguments:
CalConfig: Calendar display options
--cal-config CalConfig
--sunday
default: true
Start week on Monday
-n, --months Int
default: 1
Number of months to show
-t, --show-today
default: false
Highlight today
-w, --week-numbers
default: false
Show week numbers
Group arguments:
WeatherConfig: Weather display options
--weather-config WeatherConfig
-l, --location Str
default: "New York"
City or location name
--imperial
default: true
Use metric units
--compact
default: false
Show compact one-line output
Return: Str
Combined calendar and weather report
Note that these examples were all written in Python, but Morloc allows mixing of supported languages and automatically handles interop.