← All writing

Zun: A Language for Lightweight Services

By Published 4 min readArticle / Build logs

Why Zun makes HTTP part of its syntax, keeps types dynamic with optional runtime checks, and includes data and auth tools, with AI agents as a future direction.

Topics: software-engineering, ai-agents

Contents (6)

Zun is a language for independent developers writing scripts and lightweight network services. I want it to keep the direct feel of scripting while bringing together the capabilities that API work repeatedly needs, so an idea can become a running service sooner.

Zun hummingbird logo and wordmark

Get a service running first

What matters to me in building Zun is how much preparation an independent developer needs to get from an idea to something that runs.

Even a small API often starts with choosing a framework, organizing routes, adding a server entry point, and connecting a database and authentication. That work has value. When testing an idea, though, I would like to do less setup and get the smallest useful service running first.

That means choosing a scope: scripts, small tools, lightweight APIs, and internal services. A Zun project can start in one file and split into modules when needed. Its structure can grow with the problem instead of having to be laid out before the first piece of business logic.

Put HTTP in the language

Zun makes HTTP routes part of its syntax. $GET and $POST declare endpoints directly, a function returns the result, and zun serve starts the service. Calling a function an endpoint means the language understands the service entry point. It does not mean it deploys the service to the cloud for you.

The implementation is written in Rust, while Zun programs are currently interpreted. Existing capabilities include an HTTP server and client, SQLite, PostgreSQL, sessions, JWT, password hashing, authorization, and CSRF protection. There are also modules, a test runner, a REPL, and an LSP. Keeping common capabilities together is meant to reduce the wiring needed to use them. Current project overview

Built-in capabilities also give the language more to maintain. Each addition brings error behavior, configuration, and testing to consider, beyond simply making a call shorter to write.

Add types where constraints help

I want quick experimentation and explicit boundaries to coexist in the same language.

Without type annotations, variables are dynamic by default. With annotations, their values are checked at runtime. Constraints can also be added gradually to function parameters, return values, and custom types. To be precise, this is runtime protection, not a complete system of static compile-time checking.

$Type has an explicit identity boundary too. A declared User requires an actual User instance. An ordinary Map does not become the same type just because it happens to have matching fields. Gradual typing guide

The idea behind $

There was some playfulness in $ from the beginning: “Writing code is making money.” In the context of independent development, the point is to test whether something has value as soon as possible, rather than simply finish writing the code.

Early ideas included making payments, Webhooks, and API exposure fit more naturally into the language, with the eventual possibility of one file and one command becoming a service that could charge for its use. That is a longer-term product vision. It is neither an existing capability nor a firm near-term roadmap commitment. Early design ideas

Explore AI agents next

The repository’s direction is direct: HTTP today, AI agents next. I want to explore what this small language could do in agent services. Its existing HTTP, JSON, and database capabilities do not yet amount to an implemented agent runtime.

The public repository does not currently define stable AI interfaces or concrete mechanisms. This remains a direction to explore. Having networking and data capabilities is not a reason to count unimplemented agent features as part of the language. Current direction

An earlier network-function programming draft also explored hyper-function chains, asynchronous operations, and WebSockets. Those forms are design explorations, not syntax that should be copied and expected to run today. Network-function programming draft

Still early

Zun has plenty of gaps to address. It does not have an established package ecosystem, observability is limited, and the language may continue to introduce breaking changes.

One boundary deserves particular attention: the current runtime has no sandbox. Scripts can use the files, environment variables, and network capabilities available to their host process. Existing authentication and authorization do not make it safe to execute untrusted code. Current security boundaries

The question I want to keep testing is whether Zun can remain simple as its capabilities grow, and shorten the path from one person’s idea to a running service a little further.

Site search